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中if语句的嵌套用法
May 14 Python
python获取指定时间差的时间实例详解
Apr 11 Python
Python实现全排列的打印
Aug 18 Python
在IPython中进行Python程序执行时间的测量方法
Nov 01 Python
django解决跨域请求的问题
Nov 11 Python
Pycharm 设置默认头的图文教程
Jan 17 Python
python实现学员管理系统
Feb 26 Python
如何利用Python模拟GitHub登录详解
Jul 15 Python
Python字符串和正则表达式中的反斜杠('\')问题详解
Sep 03 Python
Python3之乱码\xe6\x97\xa0\xe6\xb3\x95处理方式
May 11 Python
keras 解决加载lstm+crf模型出错的问题
Jun 10 Python
python中time tzset()函数实例用法
Feb 18 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
PHP初学者头疼问题总结
2006/10/09 PHP
第十五节--Zend引擎的发展
2006/11/16 PHP
PHP+.htaccess实现全站静态HTML文件GZIP压缩传输(一)
2007/02/15 PHP
说明的比较细的php 正则学习实例
2008/07/30 PHP
php中静态类与静态变量用法的区别分析
2015/01/15 PHP
深入php内核之php in array
2015/11/10 PHP
Iframe自适应高度绝对好使的代码 兼容IE,遨游,火狐
2011/01/27 Javascript
js中复制行和删除行的操作实例
2013/06/25 Javascript
jQuery判断div随滚动条滚动到一定位置后停止
2014/04/02 Javascript
微信分享的标题、缩略图、连接及描述设置方法
2014/10/14 Javascript
JavaScript实现获得所有兄弟节点的方法
2015/07/23 Javascript
JS实现简单的天数计算器完整实例
2017/04/28 Javascript
用angular实现多选按钮的全选与反选实例代码
2017/05/23 Javascript
jQuery条件分页 代替离线查询(附代码)
2017/08/17 jQuery
微信小程序获取复选框全选反选选中的值(实例代码)
2019/12/17 Javascript
python基础教程之Hello World!
2014/08/29 Python
Python深入学习之上下文管理器
2014/08/31 Python
Python的Django中将文件上传至七牛云存储的代码分享
2016/06/03 Python
python+PyQT实现系统桌面时钟
2020/06/16 Python
python 实现调用子文件下的模块方法
2018/12/07 Python
PyQt QListWidget修改列表项item的行高方法
2019/06/20 Python
python、Matlab求定积分的实现
2019/11/20 Python
浅析Python面向对象编程
2020/07/10 Python
Html5自定义字体解决方法
2019/10/09 HTML / CSS
cosme官方海外旗舰店:日本最大化妆品和美容产品的综合口碑网站
2017/01/18 全球购物
Get The Label中文官网:英国运动时尚购物平台
2017/04/19 全球购物
英国旅游额外服务市场领导者:Holiday Extras(机场停车场、酒店、接送等)
2017/10/07 全球购物
电子商务网站的创业计划书
2014/01/05 职场文书
国际贸易求职信
2014/07/05 职场文书
商铺消防安全责任书
2014/07/29 职场文书
教师节倡议书
2014/08/30 职场文书
公安四风对照检查材料思想汇报
2014/10/11 职场文书
个人借款协议书范本
2014/11/17 职场文书
电工实训心得体会
2016/01/14 职场文书
Nginx域名转发使用场景代码实例
2021/03/31 Servers
win10截图快捷键win+shift+s没有反应无法截图怎么解决?
2022/08/14 数码科技