ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

pyqt5-文件夹下图片浏览,点击图片出现右键菜单

2021-05-15 15:01:41  阅读:261  来源: 互联网

标签:self pyqt5 id width 右键 pushbutton image def 图片


转载原因:这篇文章不错,参考这篇文章我实现了图片翻页的功能
原文链接:
https://blog.csdn.net/qq_42516200/article/details/105719789.

如果这篇文章没能解决你的问题,可以看我参考这篇文章,写的实现图片翻页、和图片点击出现右键功能的文章

最近需要写一个训练数据清洗筛选的辅助小工具,之前一直习惯用tkinter来写些小工具,没有接触过PyQt。但是看需求感觉用tkinter不是很好实现(应该是我太菜了),想到以前同事推荐过我用QT,所以这是一篇PyQt5新手小白三天来学习的备忘录。

首先,PyQt5的安装。直接pip安装的方式给我后面打包成exe挖了一个坑。因为版本的原因,打包出来的exe会爆找不到PyQt5模块,后来回滚到5.10版本就没出现这个错误了。可能最新版的PyQt导入包的时候不能这样写吧,要是有路过的大佬可能解释一下这个报错,不胜感激

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys, os, time, shutil
import json

我们先创建一个类叫Example,因为后面我要用到状态栏,所以我选择继承自QMainWindow,然后创建一个initUI方法用于绘制界面


class Example(QMainWindow):
 
 
    def __init__(self):
        super().__init__()
        self.initUI()##界面绘制
 
    def initUI(self):
        '''
        do something
        '''
 
if __name__ == '__main__':
    ##创建应用对象
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

获取屏幕大小

self.desktop = QApplication.desktop()
self.height = self.desktop.height()
self.width = self.desktop.width()

设置窗体大小并显示在屏幕中间

self.resize(int(self.width*0.85), int(self.height*0.8))
self.center()
##窗体居中函数
def center(self):
    qr = self.frameGeometry()
    cp = QDesktopWidget().availableGeometry().center()
    qr.moveCenter(cp)
    self.move(qr.topLeft())
            

添加按键,状态栏等等控件。这里利用QVBoxlaayout控制界面垂直布局,其中最主要的就是QScrollArea滚动条组件。QScrollArea内部有一个网络布局分布(QGridLayout)的QWidget子组件,用以显示文件夹下的所有图片。

##创建状态栏和文本编辑栏
        self.status = self.statusBar()
        self.textbox = QLineEdit(self)
        ##不显示QLineEdit的边缘,设置位置,字体样式,不可编辑
        self.textbox.setStyleSheet("background:transparent;border-width:0;border-style:outset")
        self.textbox.move(70+int(self.width*0.7), 50)
        self.textbox.resize(int(self.width*0.1), 100)
        self.textbox.setFocusPolicy(Qt.NoFocus)
        self.textbox.setFont(QFont("Arial", 20))
        self.textbox.setText("    NOP:")
##创建滚动条
        self.scroll_area_images = QScrollArea(self)
        self.scroll_area_images.setWidgetResizable(True)
        self.scrollAreaWidgetContents = QWidget(self)
        self.scrollAreaWidgetContents.setObjectName('scrollAreaWidgetContends')
        self.gridLayout = QGridLayout(self.scrollAreaWidgetContents)
        self.scroll_area_images.setWidget(self.scrollAreaWidgetContents)
        self.scroll_area_images.setGeometry(50, 50, int(self.width*0.7), int(self.height*0.7))
        self.vertocall = QVBoxLayout()
##添加按键
        ##选择文件夹按键
        self.open_file_pushbutton = QPushButton(self)
        self.open_file_pushbutton.setGeometry(120+int(self.width*0.7), 250, 100, 30)
        self.open_file_pushbutton.setObjectName('open_pushbutton')
        self.open_file_pushbutton.setText('选择根文件夹')
        self.open_file_pushbutton.clicked.connect(self.open)##关联函数
        ##上一个文件夹按键
        self.before_pushbutton = QPushButton(self)
        self.before_pushbutton.setGeometry(120+int(self.width*0.7), 350, 100, 30)
        self.before_pushbutton.setObjectName('before_pushbutton')
        self.before_pushbutton.setText('上一个文件夹')
        self.before_pushbutton.clicked.connect(self.before)
        ##下一个文件夹按键
        self.next_pushbutton = QPushButton(self)
        self.next_pushbutton.setGeometry(120+int(self.width*0.7), 450, 100, 30)
        self.next_pushbutton.setObjectName('next_pushbutton')
        self.next_pushbutton.setText('下一个文件夹')
        self.next_pushbutton.clicked.connect(self.next)
        self.vertocall.addWidget(self.scroll_area_images)

界面效果如下:

----------------------------------------分割线,以上是界面层,下面是逻辑层。---------------------------------------------------------------------------

通过按键选择跟文件夹

    def open(self):
        self.file_path = QFileDialog.getExistingDirectory(self, '选择文文件夹', '/')

每次进入新的文件夹,清空图像

#初始化滚动栏
    def clear_layout(self):
        for i in range(self.gridLayout.count()):
            self.gridLayout.itemAt(i).widget().deleteLater()

加载图片

def start_img_viewer(self):
        if self.initial_path:
            photo_list = self.sort_photo([os.path.join(self.initial_path[self.num], photo) for photo in os.listdir(self.initial_path[self.num]) if os.path.splitext(photo)[-1].lower()=='.jpg'])##获取文件夹里的所有jpg图片,并对每张图片的相似频率进行排序
            photo_num = len(photo_list)
            if photo_num != 0:
                for i in range(photo_num):
                    image_id = photo_list[i]
                    pixmap = QPixmap(image_id)
                    self.addImage(pixmap, image_id)
                    QApplication.processEvents()##实时加载,可能图片加载数量比较多
 
            else:
                QMessageBox.information(self, '提示', '该文件夹图片为空')
        else:
            QMessageBox.information(self, '提示', '请先选择根文件夹')
 
    def get_nr_of_image_columns(self):
        #展示图片的区域,计算每排显示图片数。返回的列数-1是因为我不想频率拖动左右滚动条,影响数据筛选效率
        scroll_area_images_width = int(0.68*self.width)
        if scroll_area_images_width > self.display_image_size:
 
            pic_of_columns = scroll_area_images_width // self.display_image_size  #计算出一行几列;
        else:
            pic_of_columns = 1
 
        return pic_of_columns-1
 
    def addImage(self, pixmap, image_id):
        ##获取图片列数
        nr_of_columns = self.get_nr_of_image_columns()
        nr_of_widgets = self.gridLayout.count()
        self.max_columns = nr_of_columns
        if self.col < self.max_columns:
            self.col += 1
        else:
            self.col = 0
            self.row += 1
        clickable_image = QClickableImage(self.display_image_size, self.display_image_size, pixmap, image_id)
        clickable_image.clicked.connect(self.on_left_clicked)
        clickable_image.rightClicked.connect(self.on_right_clicked)
        self.gridLayout.addWidget(clickable_image, self.row, self.col)

图片显示的模块封装成了一个类QClickableImage,其作用是生成一个Qwidget。里面上面一个Qlabel()显示图片,下面一个Qlabel()显示图片名。图片显示利用的是Qpixmap控件,对图片进行尺寸调整

class QClickableImage(QWidget):
    image_id =''
    def __init__(self,width =0,height =0,pixmap =None,image_id = ''):
        QWidget.__init__(self)
 
        self.width =width
        self.height = height
        self.pixmap =pixmap
 
        self.layout =QVBoxLayout(self)
        self.lable2 =QLabel()
        self.lable2.setObjectName('label2')
 
        if self.width and self.height:
            self.resize(self.width,self.height)
        if self.pixmap and image_id:
            pixmap = self.pixmap.scaled(QSize(self.width,self.height),Qt.KeepAspectRatio,Qt.SmoothTransformation)
            self.label1 = MyLabel(pixmap, image_id)
            self.label1.setObjectName('label1')
            #self.label1.connect(self.mouseressevent())
            self.layout.addWidget(self.label1)
 
        if image_id:
            self.image_id =image_id
            self.lable2.setText(image_id.split('\\')[-1])
            self.lable2.setAlignment(Qt.AlignCenter)
            ###让文字自适应大小
            self.lable2.adjustSize()
            self.layout.addWidget(self.lable2)
        self.setLayout(self.layout)
 
    clicked = pyqtSignal(object)
    rightClicked = pyqtSignal(object)
 
    def imageId(self):
        return self.image_id

因为我需要实现右键菜单触发不同操作的功能,所以QClickableImage里显示图片的Qlabel()我又封成了一个类MyLabel()

class MyLabel(QLabel):
    global NOP_value, NOP_dict
    def __init__(self, pixmap =None, image_id = None):
        QLabel.__init__(self)
        self.pixmap = pixmap
        self.image_id = image_id
        self.setPixmap(pixmap)
 
        self.setAlignment(Qt.AlignCenter)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.rightMenuShow)  # 开放右键策略
 
    def rightMenuShow(self, point):
        # 添加右键菜单
        self.popMenu = QMenu()
        ch = QAction(u'撤回', self)
        sc = QAction(u'删除', self)
        xs = QAction(u'显示相似频率', self)
        self.popMenu.addAction(ch)
        self.popMenu.addAction(sc)
        self.popMenu.addAction(xs)
        # 绑定事件
        ch.triggered.connect(self.reback)
        sc.triggered.connect(self.delete)
        xs.triggered.connect(self.rshow)
        self.showContextMenu(QCursor.pos())
 
 
 
    def rshow(self):
        '''
        do something
        '''
 
    def delete(self):
        '''
        do something
        '''
 
    def reback(self):
        '''
        do something
        '''
 
    def showContextMenu(self, pos):
        # 调整位置
        '''''
        右键点击时调用的函数
        '''
        # 菜单显示前,将它移动到鼠标点击的位置
 
        self.popMenu.move(pos)
        self.popMenu.show()
 
    def menuSlot(self, act):
        print(act.text())

写到这里和PyQt相关的内容就算写完了,最后效果大概这样

参考文章:

利用 pyqt5 打造属于你自己的图片浏览器

PyQt5 QLabel自定义右键弹出菜单

标签:self,pyqt5,id,width,右键,pushbutton,image,def,图片
来源: https://blog.csdn.net/iamgoodevil/article/details/116850502

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有