1. 程式人生 > 程式設計 >python GUI框架pyqt5 對圖片進行流式佈局的方法(瀑布流flowlayout)

python GUI框架pyqt5 對圖片進行流式佈局的方法(瀑布流flowlayout)

流式佈局

流式佈局,也叫做瀑布流佈局,是網頁中經常使用的一種頁面佈局方式,它的原理就是將高度固定,然後圖片的寬度自適應,這樣加載出來的圖片看起來就像瀑布一樣整齊的水流淌下來。

pyqt流式佈局

那麼在pyqt5中我們怎麼使用流式佈局呢?pyqt沒有這個控制元件,需要我們自己去封裝,下面是流式佈局的封裝程式碼。

class FlowLayout(QLayout):
 def __init__(self,parent=None,margin=0,spacing=-1):
  super(FlowLayout,self).__init__(parent)

  if parent is not None:
   self.setContentsMargins(margin,margin,margin)

  self.setSpacing(spacing)

  self.itemList = []

 def __del__(self):
  item = self.takeAt(0)
  while item:
   item = self.takeAt(0)

 def addItem(self,item):
  self.itemList.append(item)

 def count(self):
  return len(self.itemList)

 def itemAt(self,index):
  if index >= 0 and index < len(self.itemList):
   return self.itemList[index]

  return None

 def takeAt(self,index):
  if index >= 0 and index < len(self.itemList):
   return self.itemList.pop(index)

  return None

 def expandingDirections(self):
  return Qt.Orientations(Qt.Orientation(0))

 def hasHeightForWidth(self):
  return True

 def heightForWidth(self,width):
  height = self.doLayout(QRect(0,width,0),True)
  return height

 def setGeometry(self,rect):
  super(FlowLayout,self).setGeometry(rect)
  self.doLayout(rect,False)

 def sizeHint(self):
  return self.minimumSize()

 def minimumSize(self):
  size = QSize()

  for item in self.itemList:
   size = size.expandedTo(item.minimumSize())

  margin,_,_ = self.getContentsMargins()

  size += QSize(2 * margin,2 * margin)
  return size

 def doLayout(self,rect,testOnly):
  x = rect.x()
  y = rect.y()
  lineHeight = 0

  for item in self.itemList:
   wid = item.widget()
   spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,QSizePolicy.PushButton,Qt.Horizontal)
   spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,Qt.Vertical)
   nextX = x + item.sizeHint().width() + spaceX
   if nextX - spaceX > rect.right() and lineHeight > 0:
    x = rect.x()
    y = y + lineHeight + spaceY
    nextX = x + item.sizeHint().width() + spaceX
    lineHeight = 0

   if not testOnly:
    item.setGeometry(QRect(QPoint(x,y),item.sizeHint()))

   x = nextX
   lineHeight = max(lineHeight,item.sizeHint().height())

  return y + lineHeight - rect.y()

封裝好的流式佈局類,我們只要傳入相應的layout之後,他就會自動計算頁面的元素,適應頁面的寬度。

下面是我們寫的一個瀑布流顯示圖片的程式碼:

from PyQt5.QtCore import QPoint,QRect,QSize,Qt
import os
from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5.QtWidgets import (
  QApplication,QLayout,QPushButton,QSizePolicy,QWidget,QGridLayout)

class Window(QWidget):
  def __init__(self):
    self.imageheight = 100
    super(Window,self).__init__()
    self.resize(400,300)

    flowLayout = FlowLayout()

    highlight_dir = "./"
    self.files_it = iter([os.path.join(highlight_dir,file)
               for file in os.listdir(highlight_dir)])

    print()
    for file in iter(self.files_it):
      layout = QGridLayout()
      pixmap = QtGui.QPixmap(file)
      if not pixmap.isNull():
        autoWidth = pixmap.width()*self.imageheight/pixmap.height()
        label = QtWidgets.QLabel(pixmap=pixmap)
        label.setScaledContents(True)
        label.setFixedHeight(self.imageheight)
        print(autoWidth)
        label.setFixedWidth(autoWidth)
        #label.setFixedSize(100,50)
        layout.addWidget(label)

        widget = QWidget()
        widget.setLayout(layout)
        flowLayout.addWidget(widget)

    self.setLayout(flowLayout)

    self.setWindowTitle("Flow Layout")

class FlowLayout(QLayout):
  def __init__(self,spacing=-1):
    super(FlowLayout,self).__init__(parent)

    if parent is not None:
      self.setContentsMargins(margin,margin)

    self.setSpacing(spacing)

    self.itemList = []

  def __del__(self):
    item = self.takeAt(0)
    while item:
      item = self.takeAt(0)

  def addItem(self,item):
    self.itemList.append(item)

  def count(self):
    return len(self.itemList)

  def itemAt(self,index):
    if index >= 0 and index < len(self.itemList):
      return self.itemList[index]

    return None

  def takeAt(self,index):
    if index >= 0 and index < len(self.itemList):
      return self.itemList.pop(index)

    return None

  def expandingDirections(self):
    return Qt.Orientations(Qt.Orientation(0))

  def hasHeightForWidth(self):
    return True

  def heightForWidth(self,width):
    height = self.doLayout(QRect(0,True)
    return height

  def setGeometry(self,rect):
    super(FlowLayout,self).setGeometry(rect)
    self.doLayout(rect,False)

  def sizeHint(self):
    return self.minimumSize()

  def minimumSize(self):
    size = QSize()

    for item in self.itemList:
      size = size.expandedTo(item.minimumSize())

    margin,_ = self.getContentsMargins()

    size += QSize(2 * margin,2 * margin)
    return size

  def doLayout(self,testOnly):
    x = rect.x()
    y = rect.y()
    lineHeight = 0

    for item in self.itemList:
      wid = item.widget()
      spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,Qt.Horizontal)
      spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,Qt.Vertical)
      nextX = x + item.sizeHint().width() + spaceX
      if nextX - spaceX > rect.right() and lineHeight > 0:
        x = rect.x()
        y = y + lineHeight + spaceY
        nextX = x + item.sizeHint().width() + spaceX
        lineHeight = 0

      if not testOnly:
        item.setGeometry(QRect(QPoint(x,item.sizeHint()))

      x = nextX
      lineHeight = max(lineHeight,item.sizeHint().height())

    return y + lineHeight - rect.y()

if __name__ == '__main__':

  import sys

  app = QApplication(sys.argv)
  mainWin = Window()
  mainWin.show()
  sys.exit(app.exec_())

到此這篇關於python GUI框架pyqt5 對圖片進行流式佈局的方法(瀑布流flowlayout)的文章就介紹到這了,更多相關python pyqt5圖片流式佈局內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!