pyqt 显示图片的若干方法

news2024/11/16 0:03:57

date: 2022-11-30 14:23
status: public
title: ‘pyqt 显示图片的若干方法’


单张图片

使用lable 显示图片

特点是最简单,但功能也最少。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys

from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QLabel


class ImageLabel(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(600, 400)
        self.setWindowTitle("label image")

        pix = QPixmap(r'C:\fruits.jpg')
        label = QLabel(self)
        label.setPixmap(pix)
        label.setScaledContents(True)  # 自适应QLabel大小

        layout = QVBoxLayout()
        layout.addWidget(label)
        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWidget = ImageLabel()
    mainWidget.show()
    sys.exit(app.exec_())

使用pyqtgraph 控件显示图片

来源 【PyQtGraph】显示图像
特点 可以对图片进行缩放操作,继承了pyqtgraph 的一些特点功能。

"""
安装依赖库:
1. Pillow
2. PySide2
3. PyQtGraph
from https://blog.csdn.net/zhy29563/article/details/119754910
"""

import sys

import numpy as np
import pyqtgraph as pg
from PIL import Image
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QPushButton, QWidget, QFileDialog
from pyqtgraph import ImageView

# 设置 PyQtGraph 显示配置
########################################################################################################################
# 设置显示背景色为白色,默认为黑色
pg.setConfigOption('background', 'w')
# 设置显示前景色为黑色,默认为灰色
pg.setConfigOption('foreground', 'k')
# 设置图像显示以行为主,默认以列为主
pg.setConfigOption('imageAxisOrder', 'row-major')


class PyQtGraphicDemo(QWidget):
    def __init__(self, parent=None):
        super(PyQtGraphicDemo, self).__init__(parent)

        self.resize(600, 400)

        # 图像显示控件
        self.graphicsView = ImageView(self)
        # 隐藏直方图,菜单按钮,ROI
        self.graphicsView.ui.histogram.hide()
        self.graphicsView.ui.menuBtn.hide()
        self.graphicsView.ui.roiBtn.hide()

        image = Image.open(r'C:\fruits.jpg')
        if image is not None:
            # 如果之前未设置显示选项以行为主,这里需要对显示图像进行转置
            self.graphicsView.setImage(np.array(image))

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.addWidget(self.graphicsView)

        # 设置窗口布局
        self.setLayout(self.verticalLayout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = PyQtGraphicDemo()
    window.show()
    sys.exit(app.exec_())

多张图片

使用scrollArea 显示多张图片

来源:PyQt5-使用scrollArea实现图片查看器功能

特点是当窗口大小小于scrollArea 区域大小时有滑动条显示,可以拖动滑动条滑动界面。

但是这份代码有个缺点,就是当窗口大小大于scrollArea 区域大小时,你会发现scrollArea 以外的区域是空白的,也就是scrollArea 是固定大小的,区域外不会显示内容。注释掉 self.setFixedSize(850, 600) 可以测试看到。
这份代码的显示原理大致如下:创建一个scrollArea控件,对多张图像依次执行下面循环的操作:1. 创建一个label 显示image;2. label 添加到 一个QVBoxLayout 中,3. QVBoxLayout 作为一个临时的QWidget layout,4. 移动这个临时的 QWidget 到指定坐标。emmm 就不是很优雅。

# from https://blog.csdn.net/HG0724/article/details/116702824
import sys

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.uic import loadUi


class Picture(QMainWindow):
    def __init__(self, parent=None, url=None):
        super().__init__(parent)
        self.url = url
        self.ui()

    def ui(self):
        loadUi('./show_pic.ui', self)

        # self.setFixedSize(850, 600)

        total = len(self.url)

        self.qw = QWidget()
        if total % 5 == 0:
            rows = int(total / 5)
        else:
            rows = int(total / 5) + 1
        self.qw.setMinimumSize(850, 230 * rows)
        for i in range(total):

            photo = QPixmap(self.url[i])
            # print('photo:',photo)
            # photo.loadFromData(req.content)
            width = photo.width()
            height = photo.height()
            print('width:', width, '      ', 'height:', height)

            if width == 0 or height == 0:
                continue
            tmp_image = photo.toImage()  # 将QPixmap对象转换为QImage对象
            size = QSize(width, height)
            # photo.convertFromImage(tmp_image.scaled(size, Qt.IgnoreAspectRatio))
            photo = photo.fromImage(tmp_image.scaled(size, Qt.IgnoreAspectRatio))

            # 为每个图片设置QLabel容器
            label = QLabel()
            label.setFixedSize(150, 200)
            label.setStyleSheet("border:1px solid gray")
            label.setPixmap(photo)
            label.setScaledContents(True)  # 图像自适应窗口大小

            vl = QVBoxLayout()
            vl.addWidget(label)

            tmp = QWidget(self.qw)
            tmp.setLayout(vl)
            tmp.move(160 * (i % 5), 230 * int(i / 5))

        self.scrollArea.setWidget(self.qw)  # 和ui文件中名字相同


if __name__ == '__main__':
    app = QApplication(sys.argv)
    # 这是我的文件夹中图片的路径

    import glob

    url = glob.glob(r"C:\waDump\*.jpg")
    pic = Picture(url=url)
    pic.show()
    sys.exit(app.exec_())

使用scrollArea + gridLayout 显示多张图片

可以缩放窗口,图像可以随着窗口变化,但只是图像间距拉伸,每行的图片数量没有变化

# -*- coding: utf-8 -*-
import glob
import time

from PyQt5 import QtWidgets
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QLabel, QGridLayout


class Picture(QtWidgets.QWidget):

    def __init__(self, parent=None):
        super(Picture, self).__init__(parent)
        print('Picture init')
        self.setWindowTitle('All Images')
        self.resize(800, 600)

        # ui components
        self.scrollArea = QtWidgets.QScrollArea()
        self.scrollArea.setWidgetResizable(True)
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        # self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.gridLayout = QGridLayout(self.scrollAreaWidgetContents)
        self.v_layout = QtWidgets.QVBoxLayout(self)
        self.v_layout.addWidget(self.scrollArea)
        self.setLayout(self.v_layout)

        # vars
        self.max_columns = 5

    def load_images(self, paths):
        print('load images --start')
        total = len(paths)
        col = 0
        row = 0
        for i in range(total):
            self.max_columns = total if total < 5 else 5

            photo = QPixmap(paths[i])
            width = photo.width()
            height = photo.height()

            if width == 0 or height == 0:
                continue
            tmp_image = photo.toImage()  # 将QPixmap对象转换为QImage对象
            size = QSize(width, height)
            # photo.convertFromImage(tmp_image.scaled(size, Qt.IgnoreAspectRatio))
            photo = photo.fromImage(tmp_image.scaled(size, Qt.IgnoreAspectRatio))

            # 为每个图片设置QLabel容器
            label = QLabel()
            w = int(self.width() / self.max_columns * 0.8)
            h = int(w * photo.height() / photo.width())
            label.setFixedSize(w, h)
            label.setStyleSheet("border:1px solid gray")
            label.setPixmap(photo)
            label.setScaledContents(True)  # 图像自适应窗口大小

            self.gridLayout.addWidget(label, row, col)
            # 计算下一个label 位置
            if col < self.max_columns - 1:
                col = col + 1
            else:
                col = 0
                row += 1

        print('load images --end')


if __name__ == '__main__':
    start_time = time.time()
    print('main layout show')
    app = QApplication([])
    main_window = Picture()
    main_window.show()
    image_list = url = glob.glob(r"C:\waDump\*.jpg")
    # 加载图像显示
    main_window.load_images(image_list)
    print("耗时: {:.3f}秒".format(time.time() - start_time))
    app.exec_()

使用 QListWidget + 自定义的 QListWidgetItem 显示多张图片

可以缩放窗口,图像可以随着窗口重新排列,自定义的QListWidgetItem 可以灵活自定义显示样式。
代码参考这两个博客 PyQt使用笔记(六) 可多选, 有右键复制删除功能的ListWidget 2021.03.23 和 [pyqt] 使用自定义QListWidgetItem

# -*- coding: utf-8 -*-
import time

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import QSize
from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QCursor
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMenu, QAbstractItemView, QListWidgetItem, QListView
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout


class ImageListWidget(QtWidgets.QListWidget):
    signal = pyqtSignal(list)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.image_cmp_widget = None
        self.single_image = None
        self.setWindowTitle('All Images')
        self.resize(1400, 700)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        # 创建QMenu信号事件
        self.customContextMenuRequested.connect(self.showMenu)
        self.contextMenu = QMenu(self)
        self.CMP = self.contextMenu.addAction('比较')
        # self.CP = self.contextMenu.addAction('复制')
        self.DL = self.contextMenu.addAction('删除')
        # self.CP.triggered.connect(self.copy)
        self.DL.triggered.connect(self.del_text)

        # 设置每个item size
        self.setGridSize(QtCore.QSize(220, 190))
        # 设置横向list
        self.setFlow(QListView.LeftToRight)
        # 设置换行
        self.setWrapping(True)
        # 窗口size 变化后重新计算列数
        self.setResizeMode(QtWidgets.QListView.Adjust)
        # 设置选择模式
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setIconSize(QSize(200, 150))

    # 显示右键菜单
    def showMenu(self, pos):
        # pos 鼠标位置
        # 菜单显示前,将它移动到鼠标点击的位置
        self.contextMenu.exec_(QCursor.pos())  # 在鼠标位置显示

    # 获取选择行的内容
    def selected_text(self):
        try:
            selected = self.selectedItems()
            texts = ''
            for item in selected:
                if texts:
                    texts = texts + '\n' + item.text()
                else:
                    texts = item.text()
        except BaseException as e:
            print(e)
            return
        print('selected_text texts', texts)
        return texts

    def copy(self):
        text = self.selected_text()
        if text:
            clipboard = QApplication.clipboard()
            clipboard.setText(text)

    def del_text(self):
        try:
            index = self.selectedIndexes()
            row = []

            for i in index:
                r = i.row()
                row.append(r)
            for i in sorted(row, reverse=True):
                self.takeItem(i)
        except BaseException as e:
            print(e)
            return
        self.signal.emit(row)

    def mouseDoubleClickEvent(self, e: QtGui.QMouseEvent) -> None:
        super().mouseDoubleClickEvent(e)
        print('double click')
        selected = self.selectedItems()
        img_path = ''
        for item in selected:
            img_path = item.image_path()
        if len(img_path) > 0:
            # 打开新窗口显示单张图片
            # self.single_image = SingleImageView(image=img_path, background=Qt.white)
            # self.single_image.show()
            pass
        pass

    def load_images(self, paths):
        for i in range(len(paths)):
            img_item = ImageQListWidgetItem("dump image ***", paths[i])
            self.addItem(img_item)
            self.setItemWidget(img_item, img_item.widget)

            # 刷新界面
            QApplication.processEvents()


# 自定义的item 继承自QListWidgetItem
class ImageQListWidgetItem(QListWidgetItem):
    def __init__(self, name, img_path):
        super().__init__()

        self.img_path = img_path
        # 自定义item中的widget 用来显示自定义的内容
        self.widget = QWidget()
        # 用来显示name
        self.nameLabel = QLabel()
        self.nameLabel.setText(name)
        # 用来显示avator(图像)
        self.avatorLabel = QLabel()
        # 设置图像源 和 图像大小
        img_obg = QPixmap(img_path)
        width = img_obg.width()
        height = img_obg.height()
        scale_size = QSize(200, 150)
        if width < height:
            scale_size = QSize(150, 200)
        self.avatorLabel.setPixmap(QPixmap(img_path).scaled(scale_size))
        # 图像自适应窗口大小
        self.avatorLabel.setScaledContents(True)
        # 设置布局用来对nameLabel和avatorLabel进行布局
        self.hbox = QVBoxLayout()
        self.hbox.addWidget(self.avatorLabel)
        self.hbox.addWidget(self.nameLabel)
        self.hbox.addStretch(1)
        # 设置widget的布局
        self.widget.setLayout(self.hbox)
        # 设置自定义的QListWidgetItem的sizeHint,不然无法显示
        self.setSizeHint(self.widget.sizeHint())

    def image_path(self):
        return self.img_path


if __name__ == '__main__':
    print('main layout show')
    now = time.time()
    app = QApplication([])
    main_window = ImageListWidget()
    main_window.show()

    image_list = ['icon.jpg', 'icon.jpg', 'icon.jpg']
    # 数据扩充
    image_list = image_list + image_list + image_list + image_list
    main_window.load_images(image_list)

    # 绑定点击槽函数 点击显示对应item中的name
    main_window.itemClicked.connect(lambda item: print('clicked item label:', item.nameLabel.text()))
    print("ImageListWidget 耗时: {:.2f}秒".format(time.time() - now))

    app.exec_()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/129421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVAGUI编程初识之AWT

文章目录前言一 GUI编程简介二 AWT简介2.1 组件(Component)和容器(Container)2.2 Frame2.2.1 演示1-创建一个窗口2.2.2 演示2-多个窗口的创建2.3 Panel2.3.1 演示-Panel使用三 布局管理3.1 布局管理器之FlowLayout3.1.1 FlowLayout简介3.1.2 演示-FlowLayout使用3.2 布局管理器…

电子签章结构以及规范讲解

前言&#xff1a; 安全电子签章是通过采用PKI公钥密码技术&#xff0c;将数字图像处理技术与电子签名技术进行结合&#xff0c;以电子形式对加盖印章图像数据的电子文档进行数字签名&#xff0c;以确保文档来源的真实性以及文档的完整性&#xff0c;防止对文档未经授权的篡改&…

算法训练 —— 链表(1)

目录 1. LeetCode203.移除链表元素 2. LeetCode21.合并两个有序链表 3. LeetCode206.翻转链表 4. LeetCode707.设计链表 1. LeetCode203.移除链表元素 移除链表元素 题解&#xff1a;通过两个指针来控制&#xff0c;cur和prev&#xff1b;cur指针去找val&#xff0c;prev…

冰冰学习笔记:位图与布隆过滤器

欢迎各位大佬光临本文章&#xff01;&#xff01;&#xff01; 还请各位大佬提出宝贵的意见&#xff0c;如发现文章错误请联系冰冰&#xff0c;冰冰一定会虚心接受&#xff0c;及时改正。 本系列文章为冰冰学习编程的学习笔记&#xff0c;如果对您也有帮助&#xff0c;还请各位…

MySQL复制技术方案——半同步复制配置

Google为MySQL和InnoDB设计了一个大规模补丁集以量身打造服务器和存储引擎。其中一个修补程序可用于MySQL5.0版本&#xff0c;是半同步的复制补丁。MySQL已经打上了该补丁并在MySQL5.5中发布了。 半同步复制的理念是在允许更改操作继续执行前&#xff0c;确保更改操作至少被写…

34、基于STM32的电子时钟设计(DS1302)时钟、秒表、倒计时(Proteus仿真+程序)

编号&#xff1a;34 基于STM32的电子时钟设计&#xff08;DS1302&#xff09;时钟、秒表、倒计时 功能描述&#xff1a; 本系统由STM32F103系统LCD1602液晶显示按键模块DS1302时钟模块声光报警模块组成。 1、使用LCD1602显示当前日期、时间、星期 2、具有闹钟、倒计时、计时功…

【Java寒假打卡】Java基础-抽象类

【Java寒假打卡】Java基础-抽象类一、概述二、抽象类注意事项三、模板设计模式四、final关键字五、代码块一、概述 抽象方法&#xff1a;将共性的方法抽取到父类之后&#xff0c;发现该方法的实现逻辑无法在父类中给出具体明确&#xff0c;该方法就可定义为抽象方法抽象类&…

【C++初阶8-vector】熟悉的ta

前言 本期看看这位熟悉又陌生的朋友——vector。 博主水平有限&#xff0c;不足之处望请斧正&#xff01; 是什么 vecotr是序列容器&#xff0c;可变大小的数组。 *vector有矢量、向量的意思&#xff0c;用其命名可能想强调“序列”这个概念。 class template std::vecto…

独占指针 std::unique_ptr

学习智能指针之前需要知道的&#xff1a; 智能指针是原始指针的封装&#xff0c;在头文件<memory>中&#xff0c;优点就是自动分配内存&#xff0c;不用担心潜在的内存泄漏。不是所有的指针都可以封装成智能指针&#xff0c;很多时候原始指针更方便。各指针中&#xff0…

Webpack中常见的Loader?解决了什么问题?

一、是什么 loader 用于对模块的源代码进行转换&#xff0c;在 import 或"加载"模块时预处理文件 webpack做的事情&#xff0c;仅仅是分析出各种模块的依赖关系&#xff0c;然后形成资源列表&#xff0c;最终打包生成到指定的文件中。如下图所示&#xff1a; 在web…

【网络安全】——web渗透的前缀知识

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门 创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座…

ArcGIS基础实验操作100例--实验18合并表格

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 基础编辑篇--实验18 合并表格 目录 一、实验背景 二、实验数据 三、实验步骤 方法一&#xff1a;导出…

whisper

Robust Speech Recognition via Large-Scale Weak Supervision 介绍 大规模弱监督的训练。先前的方法都是通过大量的无监督学习训练&#xff08;无监督的数据容易收集&#xff0c;所以通过大量无监督的学习可以训练出一个质量较好的encoder&#xff09;。但是用的时候还需要找…

Redis配置文件

Redis配置文件 自定义目录 /myreids/redis.conf Units 单位 配置大小单位&#xff0c;开头定义了一些基本的度量单位&#xff0c;只支持bytes&#xff0c;不支持bit。大小写不敏感 INCLUDES 包含 多实例的情况可以把公用的配置文件提取出来 网络配置相关 bind 默认情况…

【WSL】[01] windows subsytem linux 配置和使用 - ubuntu GUI安装

第【1】章前言&#xff1a; AI的训练和设计似乎ubuntu是必要的&#xff0c;而且&#xff0c;GPU的配置似乎也是要在Ubuntu下&#xff0c;某些模式版本才能兼容。单独搞一个编译服务器是个思路&#xff0c;但是&#xff0c;如果资金不够&#xff0c;也许要考虑在Windwos和Linux…

程序员出身备考PMP,如何避开备考误区顺利拿到3A成绩?

还在犹豫2023年如何才能提升自己的职场竞争力吗&#xff1f;PMP项目管理证书值得大家了解。掌握这些备考技巧&#xff0c;让你的PMP学习少走弯路。有计划明年3月参考PMP的小伙伴注意啦&#xff01; 今天小赛邀请了一位程序员出身的小伙伴&#xff0c;一起来看看他是如何在忙碌…

linux下如何使用configure/make/make install命令编译安装卸载程序

源码的安装一般由3个步骤组成&#xff1a;配置&#xff08;configure&#xff09;、编译&#xff08;make&#xff09;、安装&#xff08;make install&#xff09;。安装成功的源码就是所谓的可执行文件&#xff0c;在你不需要的时候&#xff0c;也是可以删除/卸载&#xff08…

leetcode1456. 定长子串中元音的最大数目

给你字符串 s 和整数 k 。 请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。 英文中的 元音字母 为&#xff08;a, e, i, o, u&#xff09;。 示例 1&#xff1a; 输入&#xff1a;s “abciiidef”, k 3 输出&#xff1a;3 解释&#xff1a;子字符串…

Spring的7种事务传播方式

Spring事务传播行为体现在某个service方法调用另一个service方法&#xff0c;事务该如何进行下去。 Spring支持7中事务传播方式&#xff0c;在Propagation类中可以看到&#xff0c;如下&#xff1a; REQUIRED(0), SUPPORTS(1), MANDATORY(2), REQUIRES_NEW(3), NOT_SUPPORTED…

【操作系统】进程的属性及状态(三态五态七态)

文章目录进程的概念进程的属性1、结构性2、共享性3、动态性4、独立性5、制约性6、并发性进程状态1、三态模型2、五态模型3、七态模型进程的概念 程进程是一个可并发执行的具有独立功能的程序关于某个数据集合的一次执行过程&#xff0c;也是操作系统进行资源分配和保护的基本…