【PySide6】PySide6 小部件

使用QPushButton, QCheckBox, QComboBox, QLabel, 和 QSlider 小部件

在Qt(和大多数用户界面)中,widget是用户可以与之交互的UI组件的名称。用户界面由多个小部件组成,排列在窗口内。

Qt提供了大量可用的小部件,甚至允许您创建自己的自定义和自定义小部件。

快速演示:PySide6 Widgets

首先,让我们来看一些最常见的 PySide 控件。以下代码创建了一系列 PySide 控件,并将它们添加到窗口布局中,以便你能一起看到它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import sys

from PySide6.QtWidgets import (
QApplication,
QCheckBox,
QComboBox,
QDateEdit,
QDateTimeEdit,
QDial,
QDoubleSpinBox,
QFontComboBox,
QLabel,
QLCDNumber,
QLineEdit,
QMainWindow,
QProgressBar,
QPushButton,
QRadioButton,
QSlider,
QSpinBox,
QTimeEdit,
QVBoxLayout,
QWidget,
)

class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setWindowTitle("Widgets App")

layout = QVBoxLayout()
widgets = [
QCheckBox,
QComboBox,
QDateEdit,
QDateTimeEdit,
QDial,
QDoubleSpinBox,
QFontComboBox,
QLCDNumber,
QLabel,
QLineEdit,
QProgressBar,
QPushButton,
QRadioButton,
QSlider,
QSpinBox,
QTimeEdit,
]

for widget in widgets:
layout.addWidget(widget())

central_widget = QWidget()
central_widget.setLayout(layout)

self.setCentralWidget(central_widget)

app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

运行这段代码! 你将看到一个窗口出现,其中包含我们创建的所有小部件。

widgets-list.webp

让我们从上到下看一下所有的示例小部件:

Widget 功能描述
QCheckbox 一个复选框
QComboBox 下拉列表框
QDateEdit 用于编辑日期和时间
QDateTimeEdit 用于编辑日期和时间
QDial 可旋转的刻度盘
QDoubleSpinBox 用于浮点数的选择器
QFontComboBox 字体列表
QLCDNumber 一个不太美观的 LCD 显示
QLabel 仅是一个标签,非交互式
QLineEdit 输入一行文本
QProgressBar 进度条
QPushButton 按钮
QRadioButton 单选按钮组,仅一项可选
QSlider 滑动条
QSpinBox 整数选择器
QTimeEdit 用于编辑时间

还有更多的小部件,但它们不太适合!您可以通过检查Qt文档来查看它们。

接下来,我们将逐步了解一些最常用的小部件,并更详细地研究它们。为了试验这些小部件,我们需要一个简单的应用程序来放置它们。将下面的代码保存到一个名为app.py的文件中,并运行它以确保它正常工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import sys

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
QApplication,
QCheckBox,
QComboBox,
QDial,
QDoubleSpinBox,
QLabel,
QLineEdit,
QListWidget,
QMainWindow,
QSlider,
QSpinBox,
)

class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()

self.setWindowTitle("My App")

app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

在上面的代码中,我们导入了许多Qt小部件。现在,我们将依次遍历这些小部件,将它们添加到我们的应用程序中,并查看它们的行为。

QLabel

我们将从QLabel开始,它可以说是Qt工具箱中最简单的部件之一。这是一个简单的单行文本,您可以在应用程序中定位它。你可以在创建文本时通过传入一个str来设置文本:

1
label = QLabel("Hello")

或是使用 .setText() 函数:

1
2
label_1 = QLabel("1")  # 标签创建时的内容是数字 1.
label_2.setText("2") # 标签现在显示的内容是数字 2.

您还可以调整字体参数,例如字体大小或小部件中文本的对齐方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()

self.setWindowTitle("My App")

label = QLabel("Hello")
font = label.font()
font.setPointSize(30)
label.setFont(font)
label.setAlignment(
Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter
)

self.setCentralWidget(label)

widgets1.webp

提示:请注意,如果您想要更改小部件字体的属性,通常最好是获取当前字体,更新它,然后再应用它。这确保了字体面与桌面惯例保持一致。

对齐方式是使用命名空间中的标志来指定的Qt.AlignmentFlag。可用于水平对齐的标志包括:

flag 行为
Qt.AlignmentFlag.AlignLeft 与左边缘对齐。
Qt.AlignmentFlag.AlignRight 与右边缘对齐。
Qt.AlignmentFlag.AlignHCenter 在可用空间中水平居中。
Qt.AlignmentFlag.AlignJustify 在可用空间内对齐文本。

可用于垂直对齐的标志是:

flag 行为
Qt.AlignmentFlag.AlignTop 与顶部对齐。
Qt.AlignmentFlag.AlignBottom 与底部对齐。
Qt.AlignmentFlag.AlignVCenter 在可用空间中垂直居中。

您可以使用管道 ( |) 将标志组合在一起,但请注意,您一次只能使用垂直或水平对齐标志:

1
align_top_left = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop

提示:请注意,您使用OR管道(“|”)将两个标志(不是A & B)组合在一起。这是因为标志是不重叠的位掩码。例如,Qt.AlignmentFlag.AlignLeft具有十六进制值0x0001,而Qt.AlignmentFlag.AlignBottom为0x0040。通过将标志进行 OR 运算,我们得到代表“左下角”的值0x0041。此原则适用于所有其他组合 Qt 标志。如果这对您来说是胡言乱语,请随意忽略它并继续。只需记住使用管道运算符(“|”)。

最后,还有一个可以同时在两个方向上居中的简写标志:

flag 行为
Qt.AlignmentFlag.AlignCenter 水平和垂直居中

“Otje” 猫。

将文件放在与代码相同的文件夹中,然后在窗口中显示它,如下所示:

1
widget.setPixmap(QPixmap('otje.jpg'))

窗口里展示的猫“Otje”

默认情况下,图像会缩放,同时保持其纵横比。如果您希望它拉伸和缩放以完全适合窗口,您可以.setScaledContents(True)在以下位置设置QLabel

1
label.setScaledContents(True)

QCheckBox

下一个要查看的小部件是QCheckBox(),顾名思义,它向用户显示一个可勾选框。但是,与所有 Qt 小部件一样,有许多可配置选项可以更改小部件行为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setWindowTitle("My App")

checkbox = QCheckBox()
checkbox.setCheckState(Qt.CheckState.Checked)

# For tristate: widget.setCheckState(Qt.PartiallyChecked)
# Or: widget.setTriState(True)
checkbox.stateChanged.connect(self.show_state)

self.setCentralWidget(checkbox)

def show_state(self, state):
print(state == Qt.CheckState.Checked.value)
print(state)

Windows、Mac 和 Ubuntu Linux 上的 QCheckBox。

.setChecked()您可以使用或以编程方式设置复选框状态.setCheckState()。前者接受True或 ,False,分别表示选中或未选中。使用.setCheckState(),您还可以使用命名空间指定特定的选中状态Qt.CheckState

flag 行为
Qt.CheckState.Unchecked 该项目未选中
Qt.CheckState.PartiallyChecked 商品已部分托运
Qt.CheckState.Checked 商品已检查

支持部分选中 ( Qt.CheckState.PartiallyChecked) 状态的复选框通常称为三态,这意味着小部件既不打开也不关闭。处于此状态的复选框通常显示为灰色复选框,通常用于分层复选框排列中,其中子项链接到父复选框。

如果将值设置为,Qt.CheckState.PartiallyChecked复选框将变为三态。您还可以将复选框设置为三态,而无需使用以下方法将当前状态设置为部分选中:.setTriState(True)

您可能会注意到,当脚本运行时,当前状态编号显示为带有int checked = 2、 unchecked =0和 partial checked = 的1。您不需要记住这些值,例如Qt.CheckState.Checked命名空间变量 = 2,。这是这些状态各自标志的值。这意味着您可以使用 测试状态state == Qt.CheckState.Checked

QComboBox

QComboBox小部件是一个下拉列表,默认情况下会关闭,并带有一个箭头以将其打开。您可以从列表中选择一个项目,当前选定的项目将显示为小部件上的标签。组合框适合从选项列表中选择选项。

您可能见过在文字处理应用程序中用于选择字体或大小的组合框。尽管 Qt 实际上提供了一个特定的字体选择组合框QFontComboBox。

您可以QComboBox通过将字符串列表传递给 来将项目添加到.addItems()。项目将按照提供的顺序添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setWindowTitle("My App")

combobox = QComboBox()
combobox.addItems(["One", "Two", "Three"])

# The default signal from currentIndexChanged sends the index
combobox.currentIndexChanged.connect(self.index_changed)

# The same signal can send a text string
combobox.currentTextChanged.connect(self.text_changed)

self.setCentralWidget(combobox)

def index_changed(self, index): # index is an int starting from 0
print(index)

def text_changed(self, text): # text is a str
print(text)

Windows、Mac 和 Ubuntu Linux 上的 QComboBox。

当当前选定项更新时触发信号.currentIndexChanged,默认情况下传递列表中选定项的索引。还有一个.currentTextChanged信号,它提供当前选定项的标签。这种信号通常更有用。

QComboBox也可以是可编辑的,允许用户输入列表中当前没有的值,并将其插入或仅用作值。要使框可编辑:

1
combobox.setEditable(True)

您还可以设置一个标志来确定如何处理插入。这些标志存储在QComboBox类本身中,如下所示:

要使用这些,请按如下方式应用标志:

1
combobox.setInsertPolicy(QComboBox.InsertPolicy.InsertAlphabetically)

您还可以使用下列方法限制箱子中允许的物品数量.setMaxCount()

1
combobox.setMaxCount(10)

要更深入了解,QComboBox请查看QComboBox 文档。

QListWidget

接下来是QListWidget。它与 非常相似QComboBox,主要区别在于可用的信号和屏幕外观。这是一个带有选项列表的框,而不是下拉列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setWindowTitle("My App")

listwidget = QListWidget()
listwidget.addItems(["One", "Two", "Three"])

# In QListWidget there are two separate signals for the item, and the str
listwidget.currentItemChanged.connect(self.index_changed)
listwidget.currentTextChanged.connect(self.text_changed)

self.setCentralWidget(listwidget)

def index_changed(self, index): # Not an index, index is a QListWidgetItem
print(index.text())

def text_changed(self, text): # text is a str
print(text)

Windows、Mac 和 Ubuntu Linux 上的 QListWidget。

QListWidget提供currentItemChanged发送QListWidgetItem(列表框的元素)的信号,以及currentTextChanged发送项目文本的信号。

QLineEdit

QLineEdit小部件是一个简单的单行文本编辑框,用户可以在其中输入内容。它们用于表单字段或没有有效输入限制列表的设置。例如,输入电子邮件地址或计算机名称时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setWindowTitle("My App")

self.lineedit = QLineEdit()
self.lineedit.setMaxLength(10)
self.lineedit.setPlaceholderText("Enter your text")

# widget.setReadOnly(True) # uncomment this to make readonly

self.lineedit.returnPressed.connect(self.return_pressed)
self.lineedit.selectionChanged.connect(self.selection_changed)
self.lineedit.textChanged.connect(self.text_changed)
self.lineedit.textEdited.connect(self.text_edited)

self.setCentralWidget(self.lineedit)

def return_pressed(self):
print("Return pressed!")
self.lineedit.setText("BOOM!")

def selection_changed(self):
print("Selection changed")
print(self.lineedit.selectedText())

def text_changed(self, text):
print("Text changed...")
print(text)

def text_edited(self, text):
print("Text edited...")
print(text)

Windows、Mac 和 Ubuntu Linux 上的 QLineEdit。

如上面的代码所示,您可以设置行编辑中文本的最大长度。

QLineEdit许多信号可用于不同的编辑事件,包括用户按下Enter键时以及用户选择发生更改时。还有两个编辑信号,一个用于框中的文本已被编辑时,另一个用于框中的文本已被更改时。这里的区别在于用户编辑和程序更改。textEdited仅当用户编辑文本时才会发送信号。

此外,可以使用输入掩码执行输入验证,以定义支持哪些字符以及在哪里支持。这可以按如下方式应用于字段:

1
lineedit.setInputMask('000.000.000.000;_')

QSpinBox和QDoubleSpinBox

QSpinBox提供一个带有箭头的小型数字输入框来增加和减少值。QSpinBox支持整数,而相关的小部件QDoubleSpinBox支持浮点数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setWindowTitle("My App")

spinbox = QSpinBox()
# Or: doublespinbox = QDoubleSpinBox()

spinbox.setMinimum(-10)
spinbox.setMaximum(3)
# Or: doublespinbox.setRange(-10, 3)

spinbox.setPrefix("$")
spinbox.setSuffix("c")
spinbox.setSingleStep(3) # Or e.g. 0.5 for QDoubleSpinBox
spinbox.valueChanged.connect(self.value_changed)
spinbox.textChanged.connect(self.value_changed_str)

self.setCentralWidget(spinbox)

def value_changed(self, value):
print(value)

def value_changed_str(self, str_value):
print(str_value)

运行它,你会看到一个数字输入框。该值显示前后修正单位,并且限制在 +3 到 -10 的范围内。

Windows、Mac 和 Ubuntu Linux 上的 QSpinBox。

上面的演示代码展示了该小部件可用的各种功能。

要设置可接受值的范围,可以使用.setMinimum().setMaximum()。您也可以使用.setRange()同时设置两者。值类型的注释支持前缀和后缀,可以将其添加到数字中,例如分别使用.setPrefix()和表示货币标记或单位.setSuffix()

单击小部件上的向上和向下箭头将增加或减少小部件中的值,该值可以使用来设置.setSingleStep()。请注意,这对小部件可接受的值没有影响。

QSpinBox都有QDoubleSpinBox一个.valueChanged信号,当它们的值改变时,该信号就会触发。原始.valueChanged信号发送数值(一个int或一个float),而.textChanged将值作为字符串发送,包括前缀和后缀字符。

您可以选择禁用旋转框行编辑上的文本输入,方法是将其设置为只读。使用此设置,只能使用控件更改值。这还具有禁用闪烁光标的作用:

1
spinbox.lineEdit().setReadOnly(True)

QSlider

QSlider提供滑动条小部件,其内部工作原理与 非常相似QDoubleSpinBox。滑块不是以数字方式显示当前值,而是通过其手柄沿小部件长度的位置来定义其值。这通常在提供两个极端之间的调整时很有用,但不需要绝对准确。这种类型的小部件最常见的用途是用于音量控制。

.sliderMoved每当滑块移动位置时都会触发一个附加信号,.sliderPressed每当滑块被单击时都会发出一个信号:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setWindowTitle("My App")

slider = QSlider()

slider.setMinimum(-10)
slider.setMaximum(3)
# Or: widget.setRange(-10,3)

slider.setSingleStep(3)

slider.valueChanged.connect(self.value_changed)
slider.sliderMoved.connect(self.slider_position)
slider.sliderPressed.connect(self.slider_pressed)
slider.sliderReleased.connect(self.slider_released)

self.setCentralWidget(slider)

def value_changed(self, value):
print(value)

def slider_position(self, position):
print("position", position)

def slider_pressed(self):
print("Pressed!")

def slider_released(self):
print("Released")

运行此程序,您将在屏幕上看到一个滑块小部件。拖动滑块可更改其值。

Windows、Mac 和 Ubuntu Linux 上的 QSlider。

您还可以通过在创建滑块时传入方向来构建具有垂直或水平方向的滑块。方向标志在Qt.Orientation命名空间中定义。例如:

1
slider = QSlider(Qt.Orientation.Vertical)

1
slider = QSlider(Qt.Orientation.Horizontal)

QDial

最后,QDial是一个可旋转的小部件,其工作方式与滑块相同,但显示为模拟表盘。这看起来不错,但从 UI 角度来看并不是特别用户友好。然而,它们经常在音频应用程序中用作真实世界模拟表盘的模拟:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setWindowTitle("My App")

dial = QDial()
dial.setRange(-10, 100)
dial.setSingleStep(1)

dial.valueChanged.connect(self.value_changed)
dial.sliderMoved.connect(self.dial_position)
dial.sliderPressed.connect(self.dial_pressed)
dial.sliderReleased.connect(self.dial_released)

self.setCentralWidget(dial)

def value_changed(self, value):
print(value)

def dial_position(self, position):
print("position", position)

def dial_pressed(self):
print("Pressed!")

def dial_released(self):
print("Released")

运行这个,你会看到一个圆形刻度盘,旋转它可以从范围中选择一个数字。

Windows、Mac 和 Ubuntu Linux 上的 QDial。

这些信号与 相同QSlider,并保留相同的名称(例如.sliderMoved)。

总结

至此,我们对 PySide6 应用程序中使用的常见小部件进行了简要介绍。要查看可用小部件的完整列表(包括其所有信号和属性),请查看Qt 文档

如需更深入了解小部件,请查看QComboBox 文档 QComboBox 文档。

原文信息:《PySide6 Widgets》
原作者:Martin Fitzpatrick
出处:https://www.pythonguis.com/tutorials/pyside6-widgets/
免责声明:本翻译内容仅代表翻译者的个人观点与理解,原作者对此翻译版本并未进行认可,翻译过程中可能存在误差,读者应自行核实原文内容。