Pyqt5 关于流式布局和滚动条的综合使用示例代码


Posted in Python onMarch 24, 2020

流式布局

所谓流式布局指的是容器中的元素像流水一样,是可以浮动的,当元素一行或者一列占满的时候,它会自动流入到下一行或者下一列。

pyqt5流式布局

pyqt中采用流式布局的方法原理是,通过contentsMargins获取到子元素距离布局的上下左右宽度,然后我们将所有子元素进行遍历,如果它加上边距可以在一行放入的话,那么就放在一行内,如果不能,就放入到下一行,具体代码如下:

m = self.contentsMargins()
effective_rect = rect.adjusted(+m.left(), +m.top(), -m.right(), -m.bottom())
    x = effective_rect.x()
    y = effective_rect.y()
    line_height = 0

    for item in self._item_list:
      wid = item.widget()

      space_x = self.spacing()
      space_y = self.spacing()
      if wid is not None:
        space_x += wid.style().layoutSpacing(
          QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal)
        space_y += wid.style().layoutSpacing(
          QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)

      next_x = x + item.sizeHint().width() + space_x
      if next_x - space_x > effective_rect.right() and line_height > 0:
        x = effective_rect.x()
        y = y + line_height + space_y
        next_x = x + item.sizeHint().width() + space_x
        line_height = 0

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

      x = next_x
      line_height = max(line_height, item.sizeHint().height())

滚动条的设置

pyqt中有专门的滚动条组件QScrollBar,这个组件需要配合其他组件使用,我们这里使用QScrollArea这个组件进行滚动条的设置。

滚动条的使用方法

首先,我们需要声明QScrollArea

然后,我们需要设置QScrollArea的位置大小

最后,我们将需要产生滚动条的元素放入它的内部。

q = QWidget()
qscrollarea = QtWidgets.QScrollArea(q)   qscrollarea.setGeometry(QRect(50,100,600,500))
qscrollarea.setWidgetResizable(True)
listWidget = QtWidgets.QListWidget()
qscrollarea.setWidget(listWidget)

流式布局和滚动条的结合案例:

在文件当前目录创建一个images文件夹,然后放入想要展示的多张图片,然后执行当前程序,就会看到带有滚动条的流式布局界面。

运行程序,需要安装pyqt5

Pyqt5 关于流式布局和滚动条的综合使用示例代码

from PyQt5.QtCore import QPoint, QRect, QSize, Qt,pyqtSignal
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import (
  QApplication, QLayout, QPushButton, QSizePolicy, QWidget, QGridLayout)
import sys
class Window(QWidget):
  def __init__(self):
    self.imageheight = 100
    super(Window, self).__init__()
    self.resize(800, 600)

    #self.listwidget = QtWidgets.QListWidget(self)
    #self.listwidget.resize(400,300)
    #self.listwidget.setGeometry(QtCore.QRect(0, 0, 300, 200))
    #self.listwidget.addItem("test")

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

    # self.centralwidget = QtWidgets.QWidget(MainWindow)
    # self.gongzuomoshi = QtWidgets.QGroupBox(self.centralwidget)
    self.listWidget = QtWidgets.QListWidget(self)
    #self.listWidget.setFixedWidth(600)
    container_layout = QtWidgets.QVBoxLayout()
    g = QtWidgets.QGroupBox('')
    l = FlowLayout()
    g.setLayout(l)
    for file in iter(self.files_it):
      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)
        label.setFixedWidth(autoWidth)
        l.addWidget(label)

    container_layout.addWidget(g)
    container_layout.addStretch()
    self.listWidget.setLayout(container_layout)

    self.qscrollarea = QtWidgets.QScrollArea(self)
    self.qscrollarea.setGeometry(QRect(50,100,600,500))
    self.qscrollarea.setWidgetResizable(True)
    self.qscrollarea.setWidget(self.listWidget)
    self.setWindowTitle("Flow Layout Scroll")

class FlowLayout(QLayout):
  """流式布局,使用说明
  1.声明流式布局 layout = FlowLayout
  2.将元素放入流式布局中
  3.将QGroupBox应用流式布局
  4.如果期望水平流式,将QGroupBox放入到QHBoxLayout,如果期望垂直布局,将QGroupBox放入到QVBoxLayout
  """
  heightChanged = pyqtSignal(int)

  def __init__(self, parent=None, margin=0, spacing=-1):
    super().__init__(parent)
    if parent is not None:
      self.setContentsMargins(margin, margin, margin, margin)
    self.setSpacing(spacing)

    self._item_list = []

  def __del__(self):
    while self.count():
      self.takeAt(0)

  def addItem(self, item): # pylint: disable=invalid-name
    self._item_list.append(item)

  def addSpacing(self, size): # pylint: disable=invalid-name
    self.addItem(QSpacerItem(size, 0, QSizePolicy.Fixed, QSizePolicy.Minimum))

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

  def itemAt(self, index): # pylint: disable=invalid-name
    if 0 <= index < len(self._item_list):
      return self._item_list[index]
    return None

  def takeAt(self, index): # pylint: disable=invalid-name
    if 0 <= index < len(self._item_list):
      return self._item_list.pop(index)
    return None

  def expandingDirections(self): # pylint: disable=invalid-name,no-self-use
    return Qt.Orientations(Qt.Orientation(0))

  def hasHeightForWidth(self): # pylint: disable=invalid-name,no-self-use
    return True

  def heightForWidth(self, width): # pylint: disable=invalid-name
    height = self._do_layout(QRect(0, 0, width, 0), True)
    return height

  def setGeometry(self, rect): # pylint: disable=invalid-name
    super().setGeometry(rect)
    self._do_layout(rect, False)

  def sizeHint(self): # pylint: disable=invalid-name
    return self.minimumSize()

  def minimumSize(self): # pylint: disable=invalid-name
    size = QSize()

    for item in self._item_list:
      minsize = item.minimumSize()
      extent = item.geometry().bottomRight()
      size = size.expandedTo(QSize(minsize.width(), extent.y()))

    margin = self.contentsMargins().left()
    size += QSize(2 * margin, 2 * margin)
    return size

  def _do_layout(self, rect, test_only=False):
    m = self.contentsMargins()
    effective_rect = rect.adjusted(+m.left(), +m.top(), -m.right(), -m.bottom())
    x = effective_rect.x()
    y = effective_rect.y()
    line_height = 0

    for item in self._item_list:
      wid = item.widget()

      space_x = self.spacing()
      space_y = self.spacing()
      if wid is not None:
        space_x += wid.style().layoutSpacing(
          QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal)
        space_y += wid.style().layoutSpacing(
          QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)

      next_x = x + item.sizeHint().width() + space_x
      if next_x - space_x > effective_rect.right() and line_height > 0:
        x = effective_rect.x()
        y = y + line_height + space_y
        next_x = x + item.sizeHint().width() + space_x
        line_height = 0

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

      x = next_x
      line_height = max(line_height, item.sizeHint().height())

    new_height = y + line_height - rect.y()
    self.heightChanged.emit(new_height)
    return new_height

if __name__ == '__main__':
  app = QApplication(sys.argv)
  mainWin = Window()

  mainWin.show()
  sys.exit(app.exec_())

到此这篇关于Pyqt5 关于流式布局和滚动条的综合使用示例代码的文章就介绍到这了,更多相关Pyqt5 流式布局和滚动条内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python 可爱的大小写
Sep 06 Python
python实现根据ip地址反向查找主机名称的方法
Apr 29 Python
Python实现保证只能运行一个脚本实例
Jun 24 Python
opencv实现静态手势识别 opencv实现剪刀石头布游戏
Jan 22 Python
为何人工智能(AI)首选Python?读完这篇文章你就知道了(推荐)
Apr 06 Python
python实现远程控制电脑
May 23 Python
python开启debug模式的方法
Jun 27 Python
pandas进行时间数据的转换和计算时间差并提取年月日
Jul 06 Python
python障碍式期权定价公式
Jul 19 Python
浅谈Python type的使用
Nov 19 Python
Python Pivot table透视表使用方法解析
Sep 11 Python
pandas 实现将NaN转换为None
May 14 Python
Python+Appium实现自动化测试的使用步骤
Mar 24 #Python
Python3标准库之dbm UNIX键-值数据库问题
Mar 24 #Python
python网络编程socket实现服务端、客户端操作详解
Mar 24 #Python
python实现批量修改文件名
Mar 23 #Python
Python3 filecmp模块测试比较文件原理解析
Mar 23 #Python
python实现遍历文件夹图片并重命名
Mar 23 #Python
Python3 mmap内存映射文件示例解析
Mar 23 #Python
You might like
第五节--克隆
2006/11/16 PHP
MYSQL环境变量设置方法
2007/01/15 PHP
域名和cookie问题(域名后缀)
2012/10/10 PHP
VIM中设置php自动缩进为4个空格的方法详解
2013/06/14 PHP
php代码审计比较有意思的例子
2014/05/07 PHP
PHP+MariaDB数据库操作基本技巧备忘总结
2018/05/21 PHP
用JavaScript实现仿Windows关机效果
2007/03/10 Javascript
js+html+css实现鼠标移动div实例
2013/01/30 Javascript
Javascript中 关于prototype属性实现继承的原理图
2013/04/16 Javascript
固定表格行列(expression)在IE下适用
2013/07/25 Javascript
JS和JQUERY获取页面大小,滚动条位置,元素位置(示例代码)
2013/12/14 Javascript
jQuery判断checkbox(复选框)是否被选中以及全选、反选实现代码
2014/02/21 Javascript
javascript中日期函数new Date()的浏览器兼容性问题
2015/09/05 Javascript
使用JavaScript和CSS实现文本隔行换色的方法
2015/11/04 Javascript
Vue2 模板template的四种写法总结
2018/02/23 Javascript
Vue 中使用vue2-highcharts实现曲线数据展示的方法
2018/03/05 Javascript
express启用https使用小记
2019/05/21 Javascript
JS实现动态倒计时功能(天数、时、分、秒)
2019/12/12 Javascript
react-native 实现购物车滑动删除效果的示例代码
2021/01/15 Javascript
[04:27]2014DOTA2国际邀请赛 NAVI战队官方纪录片
2014/07/21 DOTA
python实现发送和获取手机短信验证码
2016/01/15 Python
python生成器/yield协程/gevent写简单的图片下载器功能示例
2019/10/28 Python
Python 依赖库太多了该如何管理
2019/11/08 Python
Django框架教程之中间件MiddleWare浅析
2019/12/29 Python
python进度条显示之tqmd模块
2020/08/22 Python
Python根据字典的值查询出对应的键的方法
2020/09/30 Python
使用Python将xmind脑图转成excel用例的实现代码(一)
2020/10/12 Python
恒华伟业笔试面试题
2015/02/26 面试题
请说出以下代码输出什么
2013/08/30 面试题
初中毕业典礼演讲稿
2014/09/09 职场文书
农村党支部书记党群众路线四风问题整改措施
2014/09/26 职场文书
教师政风行风自查自纠报告
2014/10/21 职场文书
2014年房产销售工作总结
2014/12/08 职场文书
2015年卫生院健康教育工作总结
2015/07/24 职场文书
继续教育心得体会(共6篇)
2016/01/19 职场文书
《钢铁是怎样炼成的》高中读后感
2019/08/07 职场文书