PyQt5是一个流行的Python GUI库,它包括了丰富的UI组件。三态复选框是其中一种常用的控件之一。本文将针对Python的PyQt5库的三态复选框进行详细讲解。
PyQt5中的三态复选框
三态复选框是一种多选框控件,它有三种状态:未选中,选中和半选中。半选中状态表示其相关联的子选项只有一部分选中。在PyQt5中,三态复选框组件常用于实现复杂的多选数据筛选或数据分类。
PyQt5中三态复选框的创建
对于一个三态复选框,我们需要创建一个QCheckBox对象并将其设置为三态复选框模式。
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QCheckBox, QVBoxLayout
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
vbox = QVBoxLayout()
# 创建一个QCheckBox对象,设置为三态复选框模式
self.checkbox = QCheckBox('三态复选框', self)
self.checkbox.setTristate(True)
vbox.addWidget(self.checkbox)
self.setLayout(vbox)
self.show()
在这个例子中,我们创建了一个QWidget实例,并在其中创建了一个QCheckBox对象。我们将setTristate()方法用于设置复选框为三态复选框模式。最终的结果是我们得到了一个基本的三态复选框控件。
三态复选框的状态和检测
一旦我们创建了一个三态复选框,我们需要检测其被选中的状态。
def initUI(self):
vbox = QVBoxLayout()
self.checkbox = QCheckBox('三态复选框', self)
self.checkbox.setTristate(True)
vbox.addWidget(self.checkbox)
# 增加一个按钮,并用于检测并打印复选框的状态
from PyQt5.QtWidgets import QPushButton
btn = QPushButton('获取复选框状态', self)
btn.clicked.connect(self.print_state)
vbox.addWidget(btn)
self.setLayout(vbox)
self.show()
def print_state(self):
if self.checkbox.isChecked():
print("选中状态")
elif self.checkbox.checkState() == Qt.PartiallyChecked:
print("半选中状态")
else:
print("未选中状态")
这个例子中我们添加了一个按钮,用于检测三态复选框的状态。打印不同状态的伪代码被放在print_state()方法中。我们可以通过isChecked()方法检查是否选中,通过checkState()方法检查复选框状态是否是部分选中。
三态复选框的事件
在PyQt5中,我们可以监听三态复选框的CheckedChanged事件。每当复选框的状态改变时,我们就会调用相应的槽函数。这样我们可以获得复选框的新状态并做相应处理。
def initUI(self):
vbox = QVBoxLayout()
self.checkbox = QCheckBox('三态复选框', self)
self.checkbox.setTristate(True)
vbox.addWidget(self.checkbox)
btn = QPushButton('获取复选框状态', self)
btn.clicked.connect(self.print_state)
vbox.addWidget(btn)
# 监听复选框的CheckedChanged事件
self.checkbox.stateChanged.connect(self.checkbox_changed)
self.setLayout(vbox)
self.show()
def checkbox_changed(self):
if self.checkbox.isChecked():
print("选中状态")
elif self.checkbox.checkState() == Qt.PartiallyChecked:
print("半选中状态")
else:
print("未选中状态")
在这个例子中,我们添加了一个槽函数checkbox_changed()。我们使用stateChanged信号将其连接到三态复选框。checkbox_changed()方法将根据新状态执行相应的代码。
示例1:在QTreeView中使用三态复选框
在这个示例中,我们演示如何使用三态复选框在QTreeView中选择和展开项目。
import sys
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QTreeView, QWidget, QVBoxLayout, QCheckBox, QApplication
class TreeViewExample(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
vbox = QVBoxLayout()
# 为treeview创建一个model
self.model = QStandardItemModel()
self.treeView = QTreeView()
self.treeView.setModel(self.model)
vbox.addWidget(self.treeView)
# 添加根节点
root = QStandardItem('示例')
root.setCheckable(True)
root.setTristate(True)
self.model.invisibleRootItem().appendRow(root)
# 为根节点添加子节点
for i in range(5):
child_node = QStandardItem(f'子节点{i}')
child_node.setCheckable(True)
root.appendRow(child_node)
self.setLayout(vbox)
self.show()
# 监听复选框的CheckedChanged事件
self.model.itemChanged.connect(self.treeItemChanged)
def treeItemChanged(self, item: QStandardItem):
# 检查复选框状态的改变
if item.checkState() == Qt.Checked:
print(item.text() + " 选中")
elif item.checkState() == Qt.Unchecked:
print(item.text() + " 未选中")
else:
print(item.text() + " 半选中")
# 延展或折叠节点
if item.checkState() != Qt.PartiallyChecked:
rows = []
topLevel = item.parent()
if topLevel is None:
rows = [self.model.indexFromItem(item), ]
else:
for i in range(topLevel.rowCount()):
child = topLevel.child(i, 0)
if child.checkState() == Qt.Checked:
rows.append(self.model.indexFromItem(child))
for row in rows:
self.treeView.setExpanded(row, item.checkState() == Qt.Checked)
if __name__ == '__main__':
app = QApplication(sys.argv)
treeview = TreeViewExample()
sys.exit(app.exec_())
在这个示例中,我们在QTreeView控件中使用了三态复选框,用于选择和拓展子节点。我们创建了一个QStandardItemModel,并在其上创建了根节点和5个子节点。每个子节点都是可选的并可以处于三态复选框状态。我们通过传递itemChanged信号连接树的事件来检测负责节点的复选框状态。
示例2:在多个三态复选框中选择员工
在这个示例中,我们演示了如何使用多个三态复选框,根据不同的员工属性筛选和分类员工。
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QTreeView, QLineEdit, QPushButton, QVBoxLayout, QWidget
class Employee:
def __init__(self, first, last, department, salary, city, state):
self.firstName = first
self.lastName = last
self.department = department
self.salary = salary
self.city = city
self.state = state
class EmployeesModel(QStandardItemModel):
def __init__(self, employees):
super().__init__()
self.setHorizontalHeaderLabels(['员工', '部门', '工资', '城市', '州'])
for emp in employees:
emp_item = QStandardItem(f'{emp.firstName} {emp.lastName}')
emp_item.setEditable(False)
self.appendRow([emp_item, QStandardItem(emp.department), QStandardItem(str(emp.salary)), QStandardItem(emp.city), QStandardItem(emp.state)])
class EmployeeListExample(QWidget):
def __init__(self):
super().__init__()
self.employees = [
Employee('John', 'Smith', '销售', 65000, '纽约市', '纽约州'),
Employee('Jane', 'Doe', '销售', 65000, '纽约市', '纽约州'),
Employee('Joe', 'Johnson', '制造', 80000, '迈阿密', '佛罗里达州'),
Employee('Mary', 'Smith', '制造', 80000, '迈阿密', '佛罗里达州'),
Employee('Tom', 'Jones', 'IT', 90000, '旧金山', '加利福尼亚州'),
Employee('Harry', 'Garcia', 'IT', 90000, '旧金山', '加利福尼亚州')
]
self.initUI()
def initUI(self):
vbox = QVBoxLayout()
# 创建一个model
self.model = EmployeesModel(self.employees)
# 创建treeview
self.treeView = QTreeView()
self.treeView.setModel(self.model)
vbox.addWidget(self.treeView)
# 创建筛选框
self.filterLineEdit = QLineEdit(self)
self.filterLineEdit.setPlaceholderText("搜索关键字")
vbox.addWidget(self.filterLineEdit)
# 向UI中添加员工属性筛选框
dept_checkbox = self.create_checkbox("部门")
dept_checkbox.stateChanged.connect(self.filter)
city_checkbox = self.create_checkbox("城市")
city_checkbox.stateChanged.connect(self.filter)
state_checkbox = self.create_checkbox("州")
state_checkbox.stateChanged.connect(self.filter)
vbox.addStretch(1)
self.setLayout(vbox)
self.show()
def create_checkbox(self, text):
checkbox = QCheckBox(text, self)
checkbox.setCheckState(Qt.Checked)
checkbox.setTristate(False)
self.layout().addWidget(checkbox)
return checkbox
def filter(self):
filters = []
if self.filterLineEdit.text():
filters.append(self.filterLineEdit.text())
for i in range(self.layout().count()):
widget = self.layout().itemAt(i).widget()
if isinstance(widget, QCheckBox) and widget.checkState() == Qt.Checked:
filters.append(widget.text())
self.model.setRowCount(0)
for emp in self.employees:
if all(f.lower() in str(emp.__dict__.values()).lower()
for f in filters):
self.model.appendRow([QStandardItem(f'{emp.firstName} {emp.lastName}'),
QStandardItem(emp.department),
QStandardItem(str(emp.salary)),
QStandardItem(emp.city),
QStandardItem(emp.state)])
if __name__ == '__main__':
app = QApplication(sys.argv)
employeeList = EmployeeListExample()
sys.exit(app.exec_())
在这个示例中,我们将三态复选框用于筛选员工数据。我们首先创建了一个名为 Employee 的类,该类表示员工的属性和统计数据。接下来,我们将Employee作为一个数组放入QStandardItemModel。之后,我们根据Employee属性添加三个复选框,以便可以按部门、城市或州过滤数据。
在筛选框中,我们可以同时输入搜索关键字和选择筛选属性。我们使用all()对每一行数据进行比较,以确认它是否满足给定的筛选条件。最后,只有符合条件的行才会在UI中呈现。