用 Pyqt5 打造一个精美 图片浏览器

前言


Pyqt5 是一套Qt 应用框架与 python的结合,同时支持 2.x 和 3.x。是附属于 python 一款强大的 GUI 库。

本片文章写的 图片浏览程序 就是基于 pyqt5 所完成的,由于 图片预览器 中我们需要增加一些滚动滑轮,所以这里我用到的控件主要是 pyqt5的 QScrollArea ;能够伴随着图片的不断增加而增加页面空间,

可以看一下最终的实现效果:

实现过程


实现这个 图片浏览程序 主要分为两大模块:界面模块 和 逻辑实现模块

界面模块

​ 就是程序的 UI 界面,与用户交互所用到的平台;主界面是用 QWidget 开发的,界面利用垂直布局分布 ( 这里用到的是 QVBoxlayout 控件):主界面上面添加两个起始按钮(QPushbutton),界面的下面放置就是一个 QScrollArea 组件(滚动条);

class img_viewed(QWidget):


    def __init__(self,parent =None):
        super(img_viewed,self).__init__(parent)
        self.parent = parent
        self.width = 960
        self.height = 500

        self.scroll_ares_images = QScrollArea(self)
        self.scroll_ares_images.setWidgetResizable(True)

        self.scrollAreaWidgetContents = QWidget(self)
        self.scrollAreaWidgetContents.setObjectName('scrollAreaWidgetContends')

        # 进行网络布局
        self.gridLayout = QGridLayout(self.scrollAreaWidgetContents)
        self.scroll_ares_images.setWidget(self.scrollAreaWidgetContents)

        self.scroll_ares_images.setGeometry(20, 50, self.width, self.height)
        self.vertocal1 = QVBoxLayout()


        # self.meanbar = QMenu(self)
        # self.meanbar.addMenu('&菜单')
        # self.openAct = self.meanbar.addAction('&Open',self.open)
        # self.startAct =self.meanbar.addAction('&start',self.start_img_viewer)
        self.open_file_pushbutton =QPushButton(self)
        self.open_file_pushbutton.setGeometry(150,10,100,30)
        self.open_file_pushbutton.setObjectName('open_pushbutton')
        self.open_file_pushbutton.setText('打开文件夹...')
        self.open_file_pushbutton.clicked.connect(self.open)


        self.start_file_pushbutton = QPushButton(self)
        self.start_file_pushbutton.setGeometry(750, 10, 100, 30)
        self.start_file_pushbutton.setObjectName('start_pushbutton')
        self.start_file_pushbutton.setText('开始')
        self.start_file_pushbutton.clicked.connect(self.start_img_viewer)
        				            				       
        self.vertocal1.addWidget(self.scroll_ares_images)
        
if __name__ =='__main__':
    app =QApplication(sys.argv)
    windo = img_viewed()
    windo.show()
    sys.exit(app.exec_())

预览效果如下:

1.png

上面的 QScrollArea 模块内部又加了一个 QWidget 组件,因为图片分布是逐排顺序进行的,所以组件的内部利用的是网络布局分布( QGridLayout 分布控件 )

逻辑功能实现

逻辑界面已经完成,接下来就是给界面加上相应的功能:

  • 文件打开软件启动功能开发;
  • 对图片排布开发相应的功能;

文件打开 这里用到的是 QFileDialog.getExistingDirectory 控件;然后用函数进行封装起来,如果选取的文件为空,需要弹出一个提示对话框来告诉用户,选择的文件夹不合法:

    def open(self):
        file_path = QFileDialog.getExistingDirectory(self, '选择文文件夹', '/')
        if file_path ==None:
            QMessageBox.information(self,'提示','文件为空,请重新操作')
        else:
            self.initial_path =file_path#self.initial_path用来存放图片所在的文件夹

然后就是在 类的主功能函数 init 下面加上一行代码,让打开按钮对这个函数进行衔接:

self.open_file_pushbutton.clicked.connect(self.open)

然后就能达到下面的效果了:

gif33.gif

软件启动 图片文件夹已经获取到了,接下来就是对对文件夹中的图片进行预览功能的开发:

  • 图片布局与显示问题:图片布局就是之前提到的网络布局方式(Qgridlayout),图片显示是利用 (Qlbel控件)

    • 图片布局分布时,首先设定图片的固定宽度,然后根据自己设定窗口大小,进行图片分布,每排容纳的图片数量 = 设定窗口 / 图片固定宽度;
    • 初始的时候把图片的所在位置都设为0,然后每当每一排的图片数量达到最大容纳数量时,就加一;
        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 =self.col +1
            else:
                self.col =0
                self.row +=1
    
            print('行数为{}'.format(self.row))
            print('此时布局内不含有的元素数为{}'.format(nr_of_widgets))
    
            print('列数为{}'.format(self.col))
            clickable_image = QClickableImage(self.displayed_image_size, self.displayed_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)
            def loc_fil(self,stre):
          print('存放地址为{}'.format(stre))
            self.initial_path = stre
    	
        
        #下面两个函数是用来接受传递信号用的;
        
        def geng_path(self,loc):
            print('路径为,,,,,,{}'.format(loc))
        def gen_type(self,type):
            print('图片类型为:,,,,{}'.format(type))
    
    • 图片显示的话,利用的 Qpixmap 控件;这里又开发了一个类,用来传递经过处理(尺寸改变,加图片源地址) 之后的 Pixmap,用的是 pyqSignal 方法(信号传递)

    • QClickableImage ;这个模块主要是生成一个 QWidget : 这个 Qwidget用的是垂直布局分布,上面放的是图片,下面放的是图片的 地址 ( image_id );

      class QClickableImage(QWidget):
          image_id =''
      
          def __init__(self,width =0,height =0,pixmap =None,image_id = ''):
              QWidget.__init__(self)
      
              self.layout =QVBoxLayout(self)
              self.label1 = QLabel()
              self.label1.setObjectName('label1')
              self.lable2 =QLabel()
              self.lable2.setObjectName('label2')
              self.width =width
              self.height = height
              self.pixmap =pixmap
      
              if self.width and self.height:
                  self.resize(self.width,self.height)
              if self.pixmap:
                  pixmap = self.pixmap.scaled(QSize(self.width,self.height),Qt.KeepAspectRatio,Qt.SmoothTransformation)
                  self.label1.setPixmap(pixmap)
                  self.label1.setAlignment(Qt.AlignCenter)
                  self.layout.addWidget(self.label1)
              if image_id:
                  self.image_id =image_id
                  self.lable2.setText(image_id)
                  self.lable2.setAlignment(Qt.AlignCenter)
                  ###让文字自适应大小
                  self.lable2.adjustSize()
                  self.layout.addWidget(self.lable2)
              self.setLayout(self.layout)
      
          clicked = pyqtSignal(object)
          rightClicked = pyqtSignal(object)
      
          def mouseressevent(self,ev):
              print('55555555555555555')
              if ev.button() == Qt.RightButton:
                  print('dasdasd')
                  #鼠标右击
                  self.rightClicked.emit(self.image_id)
              else:
                  self.clicked.emit(self.image_id)
      
          def imageId(self):
              return self.image_id
        
      

      当以上所有功能都已经开发完之后,接下来就是对那个 软件启动 按钮添加功能:这里做的是一个函数封装,主要实现是先递归文件夹中的每张照片,然后对每张照片利用 addImage() 函数添加到界面的相应位置。

          def start_img_viewer(self):
              if self.initial_path:
                  file_path = self.initial_path
                  print('file_path为{}'.format(file_path))
                  print(file_path)
                  img_type = 'png'
                  if file_path and img_type:
      
                      png_list = list(i for i in os.listdir(file_path) if str(i).endswith('.{}'.format(img_type)))
                      print(png_list)
                      num = len(png_list)
                      if num !=0:
                          for i in range(num):
                              image_id = str(file_path + '/' + png_list[i])
                              print(image_id)
                              pixmap = QPixmap(image_id)
                              self.addImage(pixmap, image_id)
                              print(pixmap)
                              QApplication.processEvents()
                      else:
                          QMessageBox.warning(self,'错误','生成图片文件为空')
                          self.event(exit())
                  else:
                      QMessageBox.warning(self,'错误','文件为空,请稍后')
              else:
      
                  QMessageBox.warning(self, '错误', '文件为空,请稍后')
            
      

      最后设置一个程序的启动主函数 –name-- ==–main– ;

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

最后


以上就是基于 pyqt5 开发这个简单 图片编辑器的 整个过程;程序中存在的不足当然还有很多,界面也没有进行任何的美化,因为自己也刚接触这个库,也在学习阶段当中;整个程序的源码我已经放在 Github上了 ,地址:Github;

个人微信公众号:小张Python;专注于 python爬虫,数据分析、可视化;python图像处理方面,没事的话可以常来坐坐!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小张Python1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值