首页 > 其他分享 >Pyside6 布局管理器(5)--- QFormLayout的使用

Pyside6 布局管理器(5)--- QFormLayout的使用

时间:2024-10-27 17:17:08浏览次数:3  
标签:控件 QFormLayout 管理器 self None --- lay row

一、QFormLayout的介绍(官翻)

QFormLayout是一个方便的布局类,它以两列的形式布局其子元素。左列由标签组成,右列由“字段”小部件(行编辑器、数字显示框等)组成。
 
传统上,这种两栏布局是通过使用QGridLayout实现的。QFormLayout是一种更高级别的替代方案,具有以下优点:

  • 遵守不同平台的外观和感觉指南。

 
例如,macOS Aqua和KDE指南规定标签应右对齐,而Windows和GNOME应用程序通常使用左对齐。
 

  • 支持包裹长行。

 
对于小显示器的设备,QFormLayout可以设置为换行长行,甚至可以设置为换行所有行。
 

  • 用于创建标签-字段对的便捷API。

 
addRow() 重载接受一个 QString 和一个 QWidget *,在幕后创建一个 QLabel 并自动设置其好友。然后我们可以这样写代码:

formLayout = QFormLayout(self)
formLayout.addRow("Name:", nameLineEdit)
formLayout.addRow("Email:", emailLineEdit)
formLayout.addRow("Age:", ageSpinBox)

与下面的代码进行比较,使用QGridLayout编写:

gridLayout = QGridLayout(self)
nameLabel = QLabel("Name:")
nameLabel.setBuddy(nameLineEdit)
emailLabel = QLabel("Name:")
emailLabel.setBuddy(emailLineEdit)
ageLabel = QLabel(("Name:")
ageLabel.setBuddy(ageSpinBox)
gridLayout.addWidget(nameLabel, 0, 0)
gridLayout.addWidget(nameLineEdit, 0, 1)
gridLayout.addWidget(emailLabel, 1, 0)
gridLayout.addWidget(emailLineEdit, 1, 1)
gridLayout.addWidget(ageLabel, 2, 0)
gridLayout.addWidget(ageSpinBox, 2, 1)

下表显示了不同样式的默认外观。

通过调用 setLabelAlignment() 、 setFormAlignment() 、 setFieldGrowthPolicy() 和 setRowWrapPolicy() ,也可以单独覆盖表单样式。例如,要在所有平台上模拟QMacStyle的表单布局外观,但标签左对齐,你可以这样写:

formLayout.setRowWrapPolicy(QFormLayout.DontWrapRows)
formLayout.setFieldGrowthPolicy(QFormLayout.FieldsStayAtSizeHint)
formLayout.setFormAlignment(Qt.AlignHCenter | Qt.AlignTop)
formLayout.setLabelAlignment(Qt.AlignLeft)

二、QFormLayout的相关方法

1.QFormLayout的创建及插入行列操作方法

API函数

参数说明

返回值

功能作用

QFormLayout(self, parent)

parent:QWidget

None

创建一个表格布局实例

addRow(self,lab,field)

lab:QWidget

field:QWidget或QLayout

None

按照给定格式内容中的控件和数据项添加行

addRow(self,labText,field)

labText:str

field:QWidget或QLayout

None

按照给定格式内容中的控件和数据项添加行(默认第一个对象为QLabel)

addRow(self,layout)

layout:QLayout

None

添加行,此行为布局项,占两列

addRow(self,widget)

layout:QWidget

None

添加行,此行为控件,占两列

insertRow(self,row,lab,field)

row:int

lab:QWidget

field:QWidget或QLayout

None

在指定索引行,按照给定格式内容中的控件和数据项添加行

insertRow (self, row,labText,field)

row:int

labText:str

field:QWidget或QLayout

None

在指定索引行,按照给定格式内容中的控件和数据项添加行(默认第一个对象为QLabel)

insertRow (self,row,layout)

row:int

layout:QLayout

None

在指定索引行,添加行,此行为布局项,占两列

insertRow(self,row,widget)

row:int

layout:QWidget

None

在指定索引行,添加行,此行为控件,占两列

setWidget (self,row,role,layout)

row:int

role:QFormLayout.Itemrole

layout:QLayout

None

在指定索引行,置入标志项为指定布局

setLayout(self,row,role,widget)

row:int

role:QFormLayout.Itemrole

layout:QWidget

None

在指定索引行,置入标志项为指定控件

QFormLayout布局简化了添加流程,默认为两列控件,左列为标签,右列为字段控件。故,上述方法中的lab参数即指代标签对象,右侧的field则指代字段控件对象。如果相关方法直接填入字符串,则将其默认为标签QLabel对象。如addRow()方法和insertRow()方法。

但是,要说明的是,并不是左列只能添加标签对象,两列可以添加任意继承自QWidget的子类。

上述方法中role参数是一个枚举类:

枚举类

枚举常量

枚举值

功能描述

QFormLayout

LabelRole

0

标签小部件标志

FieldRole

1

数据项小部件标志

SpanningRole

2

跨列的标签或数据项小部件标

role参数各枚举值的含义也很简单,LabelRole就是指左列,Filed指右列,而SpanningRole指的是跨列的项。

from PySide6.QtWidgets import QApplication,QWidget,QPushButton,QLineEdit,QLabel,\
                           QCalendarWidget,QDateEdit,QTextEdit,QHBoxLayout,QFormLayout
from PySide6.QtCore import Qt,QRect
import sys
class MyWindow(QWidget):
   def __init__(self):
      super().__init__()

      # 创建表单布局及布局内控件
      lay = QFormLayout(self)
      btn1 = QPushButton()
      date_edit = QDateEdit()
      line_edit = QLineEdit()
      calendar_1 = QCalendarWidget()

      # 创建水平子布局及子布局内的控件
      child_lay = QHBoxLayout()
      btn_insert = QPushButton("插入行")
      btn_set = QPushButton("修改行")
      # 添加控件至水平子布局
      child_lay.addWidget(btn_insert)
      child_lay.addWidget(btn_set)

      # 将控件与子布局以添加行的方式置入布局内
      lay.addRow(btn1,date_edit)
      lay.addRow("姓名:",line_edit)
      lay.addRow(calendar_1)
      lay.addRow(child_lay)

      # 创建插入和替换控件
      lab = QLabel("年龄:")
      line_edit_2 = QLineEdit()
      self.set_lab = QLabel("个人简历")
      self.text_edit = QTextEdit()

      # 点击按钮在第1行插入行
      btn_insert.clicked.connect(lambda :lay.insertRow(1,lab,line_edit_2))
      # 点击按钮将标签置入第2行的标签位
      btn_set.clicked.connect(self.set_row)

   def set_row(self):
      self.layout().setWidget(2, QFormLayout.ItemRole.LabelRole, self.set_lab)
      #self.layout().setWidget(2, QFormLayout.ItemRole.FieldRole,self.text_edit)

if __name__ == '__main__':
   app = QApplication(sys.argv)
   win = MyWindow()
   win.show()
   sys.exit(app.exec())

运行结果:

使用setLayout()和setWidget()方法时,置入的位置不能被占据,否则界面会出现问题且控制台报错。需要同replace的相关方法,或者删除已占位的控件后再设置。

2.QFormLayout的删除行列操作

API函数

参数说明

返回值

功能作用

removeRow(self, row: int)

row:int

None

移除行并删除控件

removeRow(self, widget)

widget:QWidget

None

移除行并删除控件

removeRow(self, layout)

layout:QLayout

None

移除行并删除控件

takeRow(self, row: int)

row:int

QFormLayout.TakeRowResult

移除行但不删除控件

takeRow(self, widget)

widget:QWidget

QFormLayout.TakeRowResult

移除行但不删除控件

takeRow (self, layout)

layout:QLayout

QFormLayout.TakeRowResult

移除行但不删除控件

setRowVisible(self, row, on)

row:int

on:bool

None

设置行隐藏,Ture显示,Flase隐藏

setRowVisible(self, widget, on)

widget:QWidget

on:bool

None

设置行隐藏,Ture显示,Flase隐藏

setRowVisible(self, layout, on)

layout:QLayout

on:bool

None

设置行隐藏,Ture显示,Flase隐藏

isRowVisible(self, row)

row:int

bool

查看行是否隐藏

isRowVisible(self, row)

widget:QWidget

bool

查看行是否隐藏

isRowVisible(self, row)

layout:QLayout

bool

查看行是否隐藏

count(self)

None

int

获取控件总数

rowCount(self)

None

int

获取行总数

相关方法都很简单,不做过多说明。有一点需要注意,QFormLayout的removeRow()方法和继承自QLayout的removewidget()是不一样的,romoveRow()方法直接删除了控件,而removewidget()只是将控件从布局中移除。setRowVisiable方法与控件的hide()方法一致,但与QGridLayout不同的是,此处在控件的尺寸策略中设置控件隐藏占位,是无效的。

3.QFormLayout的其他相关方法

API函数

参数说明

返回值

功能作用

getLayoutPosition(self, layout)

layout: QLayout

tuple(int, QFormLayout.ItemRole

)

获取子布局位置及数据项信息的元组

getWidgetPosition(self, widget)

widget: QWidget

tuple(int, QFormLayout.

ItemRole

获取子布局位置及数据项信息的元组

setFormAlignment(self, alignment)

alignment:

Qt.AlignmentFlag

None

设置表单的对其方式

formAlignment(self)

None

Qt.AlignmentFlag

返回表单的对其方式

setLabelAlignment(self, alignment)

alignment:

Qt.AlignmentFlag

None

设置标签的对其方式

labelAlignment(self)

None

Qt.AlignmentFlag

返回标签的对其方式

labelForField(self, field)

field: QWidget

QWidget

通过右侧子布局获取左侧标签项

labelForField(self, field)

field: QLayout

QWidget

通过右侧控件获取左侧标签项

setSpacing(self, arg__1)

arg_1:int

None

设置表单布局的水平和竖向间距

spacing(self)

None

int

获取表单布局的水平和竖向间距

setHorizontalSpacing(self, spacing)

spacing:int

None

设置水平间距

horizontalSpacing(self)

None

spacing:int

获取水平间距

setVerticalSpacing(self, spacing)

spacing:int

None

设置竖向间距

verticalSpacing(self)

None

spacing:int

获取竖向间距

setRowWrapPolicy(self, policy)

policy: QFormLayout.

RowWrapPolicy

None

设置行包装策略

rowWrapPolicy(self)

None

QFormLayout.

RowWrapPolicy

获取行包装策略

setFieldGrowthPolicy(self, policy)

policy: QFormLayout

.FieldGrowthPolicy

None

设置数据项增长策略

fieldGrowthPolicy(self)

None

QFormLayout.

RowWrapPolicy

获取数据项增长策略

这里重点说一下相关尺寸策略的问题,主要涉及行和字段控件部分的尺寸策略。如setRowWrapPolicy(self, policy),他的参数不是QSizePolicy类,而是QFormLayout的一个枚举类。

枚举类

枚举常量

枚举值

功能描述

QFormLayout.RowWrapPolicy

DontWrapRows

0

数据项始终位于其标签旁边。  (即使父控件挤压至最小,他还是会在一行)

WrapLongRows

1

标签具有足够的水平空间以适合最宽的标签,其余空间则分配给数据项。如果数据项对应的最小大小大于可用空间,则该字段将换行到下一行。

(如果父控件挤压至最小,字段控件会挪至下一行)

WrapAllRows

2

字段始终布置在其标签下方。

QFormLayout.FieldGrowthPolicy

FieldsStayAtSizeHint

0

字段永远不会超出其有效大小提示。

(不会随父控件大小变化而变化)

ExpandingFieldsGrow

1

水平尺寸策略为“扩展”或“最小扩展”的字段将增长以填充可用空间。  其他字段将不会超出其有效大小提示。

(只有策略为Expanding和MinimumExpanding才增长)

AllNonFixedFieldsGrow

2

具有允许其增长的大小策略的所有字段都将增长以填充可用空间。

(除Maximum,Fixed以外的策略都能增长

这个枚举类的值相当于方便的为我们提供了lab项和field项的尺寸策略的设置,而不需要我们单独对控件进行尺寸策略的设置。但另一方面,使用setRowWrapPolicy(self, policy)和setFieldGrowthPolicy(self, policy)方法就统一了一行或者字段列的整体尺寸策略,对于有不同需要的控件就进行了限制。

同时,对于扩展至存在于水平方向,竖向还是需要通过控件的尺寸策略进行设置。

from PySide6.QtWidgets import QApplication,QWidget,QPushButton,QLineEdit,\
                           QCalendarWidget,QLabel,QDateEdit,QHBoxLayout,QFormLayout
from PySide6.QtCore import Qt
import sys
class MyWindow(QWidget):
   def __init__(self):
      super().__init__()

      # 创建总表单布局设置给父窗口
      all_lay = QFormLayout(self)

      # 创建子表单布局和相关控件
      lay = QFormLayout()
      lab = QLabel("日期信息:")
      date_edit = QDateEdit()
      line_edit = QLineEdit()
      calendar_1 = QCalendarWidget()

      # 创建水平子布局及子布局内的控件
      child_lay = QHBoxLayout()
      btn2 = QPushButton("设置表单右对齐")
      btn3 = QPushButton("设置标签右对齐")
      # 添加控件至水平子布局
      child_lay.addWidget(btn2)
      child_lay.addWidget(btn3)

      # 将控件与子布局以添加行的方式置入布局内
      lay.addRow(lab,date_edit)
      lay.addRow("年龄:",line_edit)

      # 将lay、calendar_1和child_lay添加至总布局中
      all_lay.addRow(lay)
      all_lay.addRow(calendar_1)
      all_lay.addRow(child_lay)

      # 设置控件的水平间距和竖向间距
      all_lay.setHorizontalSpacing(10)
      all_lay.setVerticalSpacing(20)

      # 设置lay布局中行的包装策略
      lay.setRowWrapPolicy(QFormLayout.RowWrapPolicy.WrapAllRows)
      # 设置lay布局中的数据项的增长策略
      lay.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
      # 获取calendar_1的布局位置及数据项信息
      print(all_lay.getWidgetPosition(calendar_1))

      btn2.clicked.connect(lambda :lay.setFormAlignment(Qt.AlignmentFlag.AlignRight))
      btn3.clicked.connect(lambda :lay.setLabelAlignment(Qt.AlignmentFlag.AlignRight))

if __name__ == '__main__':
   app = QApplication(sys.argv)
   win = MyWindow()
   win.show()
   sys.exit(app.exec())


运行结果:

标签:控件,QFormLayout,管理器,self,None,---,lay,row
From: https://blog.csdn.net/love_songming/article/details/143270650

相关文章

  • DRF-Permission组件源码分析及改编源码
    1.权限组件源码分析PS:下列源码为了方便理解都进行了简化,只保留了权限相关的代码由于视图函数中继承了APIView,因此permission_classes可在视图类中进行重写。注意点:执行权限校验前,已执行了认证流程。因此此时可通过self.user获取用户对象(认证通过的情况)2.实践:编写一......
  • 学习笔记(六):ArkUi-线性布局 (Row/Column)常用属性
    一、space属性设置排列方向上子元素的间距,使各子元素在排列方向上有等间距效果。 二、alignItems属性设置子元素在交叉轴(排列方向的垂直方向)上的对齐方式。且在各类尺寸屏幕中,表现一致。其中,交叉轴为垂直方向时,取值为VerticalAlign类型,水平方向取值为HorizontalAlign类型。......
  • leetCode-深度优先遍历
    岛屿数量深度优先遍历classSolution{publicintnumIslands(char[][]grid){intxlen=grid[0].length;intylen=grid.length;intcount=0;for(intx=0;x<xlen;x++){for(inty=0;y<ylen;y++){......
  • client-go DiscoveryClient和ClientSet长连接数
    packagemainimport( "context" "test/signals" "time" core_v1"k8s.io/api/core/v1" metav1"k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/discovery" "k8s.io/client-go/kuber......
  • Wi-Fi 6和Wi-Fi 5在速度和覆盖范围上有什么提升_1
    Wi-Fi6与Wi-Fi5在无线网络技术方面的主要提升包括:1.速度提升;2.覆盖范围增加;3.设备连接能力增强;4.能效优化;5.安全性增强。Wi-Fi6的最大特点是提供更高的数据传输速度,同时支持更多设备的连接,且在大型网络环境下表现更为稳定。此外,Wi-Fi6在能效方面进行了优化,有助于减少电池消耗......
  • JAVA学习笔记--面向对象_面向对象思想介绍
    面向对象的介绍 1.面向过程:自己的事情自己干,代表语言C语言     洗衣服:每一步自己要亲力亲为->找个盆,放点水,找个搓衣板,搓搓搓2.面向对象:自己的事情别人帮忙去干,代表语言Java语言       洗衣服:自己的事情别人干->全自动洗衣机如果......
  • JAVA学习笔记--方法篇
    一,形式参数和实际参数区别1.形式参数(形参):在定义方法的时候形式上定义的参数,此参数还没有值2.实际参数(实参):在调用方法的时候给形参赋予的具体的值publicclassDemo04method{publicstaticvoidmain(String[]args){intsum=sum(34,65);......
  • 实验干货|电流型霍尔传感器采样设计03-信号调理
    在前两篇博客中,将霍尔输出的电流信号转换成了有正有负的电压信号,但是DSP需要采集0~3V的电压信号,因此需要对信号缩放并抬升至全部为正的信号。常见的方法是,通过比例放大(缩小)电路对信号进行放缩,通过加法电路抬升基准电平。这里分为两步,首先设计基准电平。设计基准电平DSP的A......
  • Python装饰器 - 具体讲解
    Python装饰器是一种非常有用的功能,它允许我们以不修改原有函数代码的方式,扩展或增强函数的行为。装饰器本质上是一个函数,它接收一个函数作为参数并返回一个新的函数。下面我将详细讲解Python装饰器的概念、用法和实现。1.装饰器的基本概念装饰器的基本语法如下:defdecor......
  • 2024-2025-1(20241321)《计算机基础与程序设计》第五周学习总结
    这个作业属于哪个课程<班级的链接>(2024-2025-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(2024-2025-1计算机基础与程序设计第一周作业)这个作业的目标<了解并学习AI功能,回顾一周课程心得>作业正文...本博客链接https://www.cnblogs.com/guchua......