用 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;

個人微信公衆號:Z先生點記;專注於 python爬蟲,數據分析、可視化;python圖像處理方面,沒事的話可以常來坐坐!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章