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自动化测试工具Splinter简介和使用实例
May 13 Python
Python实现获取磁盘剩余空间的2种方法
Jun 07 Python
python与sqlite3实现解密chrome cookie实例代码
Jan 20 Python
python OpenCV学习笔记直方图反向投影的实现
Feb 07 Python
Anaconda2 5.2.0安装使用图文教程
Sep 19 Python
Python编程图形库之Pillow使用方法讲解
Dec 28 Python
python树莓派红外反射传感器
Jan 21 Python
python实现简单银行管理系统
Oct 25 Python
解决TensorFlow调用Keras库函数存在的问题
Jul 06 Python
如何基于Python Matplotlib实现网格动画
Jul 20 Python
Python如何合并多个字典或映射
Jul 24 Python
python 判断一组数据是否符合正态分布
Sep 23 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使用memcache存储session的详解
2013/06/25 PHP
解决PHP mysql_query执行超时(Fatal error: Maximum execution time …)
2013/07/03 PHP
浅析十款PHP开发框架的对比
2013/07/05 PHP
ThinkPHP实现二级循环读取的方法
2014/11/03 PHP
PHP中Memcache操作类及用法实例
2014/12/12 PHP
PHP+Mysql无刷新问答评论系统(源码)
2016/12/20 PHP
Laravel 5.1 框架Blade模板引擎用法实例分析
2020/01/04 PHP
JavaScript 入门·JavaScript 具有全范围的运算符
2007/10/01 Javascript
js 实现打印网页中定义的部分内容的代码
2010/04/01 Javascript
基于jQuery的投票系统显示结果插件
2011/08/12 Javascript
70+漂亮且极具亲和力的导航菜单设计国外网站推荐
2011/09/20 Javascript
javascript中this做事件参数相关问题解答
2013/03/17 Javascript
引用外部js乱码问题分析及解决方案
2013/04/12 Javascript
JS动态修改表格cellPadding和cellSpacing的方法
2015/03/31 Javascript
浅谈js 闭包引起的内存泄露问题
2015/06/22 Javascript
浅谈jquery中delegate()与live()
2015/06/22 Javascript
javascript实现3D切换焦点图
2015/10/16 Javascript
jQuery插件imgPreviewQs实现上传图片预览
2016/01/15 Javascript
编写高质量JavaScript代码的基本要点
2016/03/02 Javascript
Angular2平滑升级到Angular4的步骤详解
2017/03/29 Javascript
详解react-router如何实现按需加载
2017/06/15 Javascript
vue实现手机号码抽奖上下滚动动画示例
2017/10/18 Javascript
基于mpvue的小程序项目搭建的步骤
2018/05/22 Javascript
Vue实现动态添加或者删除对象和对象数组的操作方法
2018/09/21 Javascript
封装一下vue中的axios示例代码详解
2020/02/16 Javascript
Python自动重试HTTP连接装饰器
2015/04/28 Python
Python及PyCharm下载与安装教程
2017/11/18 Python
Python3 加密(hashlib和hmac)模块的实现
2017/11/23 Python
用python统计代码行的示例(包括空行和注释)
2018/07/24 Python
CSS3只让背景图片旋转180度的实现示例
2021/03/09 HTML / CSS
保密工作责任书
2014/04/16 职场文书
大学生党员自我剖析材料
2014/10/06 职场文书
教师个人自我评价
2015/03/04 职场文书
总经理致辞
2015/07/29 职场文书
六年级上册《闻官军收河南河北》的教学设计
2019/11/15 职场文书
解决vue $http的get和post请求跨域问题
2021/06/07 Vue.js