1. 效果展示
<全选>
<取消全选>
<选中部分内容>
2. 知识点
1. Model/View
Model-View-Controller (Model-View-Controller, MVC)是一种源自Smalltalk的设计模式,经常用于构建用户界面;如果 View 和 Controller 对象被组合,结果就是 Model/View 架构。Model负责提供数据,而View负责展示数据,这种分离使得可以在多个不同的View中显示相同的数据,或实现新的View类型,而无需更改底层数据结构。关于Model/View的更多信息可参考下方<参考链接-1>。
2. QComboBox
QComboBox 中的 model 是一个数据模型,它用于存储和管理下拉列表框中的选项数据。在 PyQt 中,QComboBox 的 model 通常是一个 QStandardItemModel 对象,它可以通过 addItem()、addItems()、insertItem()、removeItem() 等方法来添加、删除和修改选项数据。
QComboBox 中的 view 是一个视图,它用于显示下拉列表框中的选项数据。在 PyQt 中,QComboBox 的 view 通常是一个 QListView 对象,它可以通过 setView() 方法来设置。
官方文档:
QComboBox — PyQt Documentation v6.6.0
QAbstractItemModel — PyQt Documentation v6.6.0
3. 代码部分
import sys
from PyQt6.QtWidgets import QComboBox, QMainWindow, QApplication, QToolTip, QLineEdit
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QFont
class CheckableComboBox(QComboBox):
def __init__(self, parent=None):
super(CheckableComboBox, self).__init__(parent)
QToolTip.setFont(QFont('Times New Roman', 15)) # 设置提示框字体和字号
self.setLineEdit(QLineEdit())
self.lineEdit().setReadOnly(True)
self.view().clicked.connect(self.selectItemAction)
self.addCheckableItem('全选')
self.SelectAllStatus = 1
def addCheckableItem(self, text):
super().addItem(text)
item = self.model().item(self.count() - 1, 0)
item.setFlags(Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsEnabled)
item.setCheckState(Qt.CheckState.Unchecked)
item.setToolTip(text)
def addCheckableItems(self, texts):
for text in texts:
self.addCheckableItem(text)
def ifChecked(self, index):
item = self.model().item(index, 0)
return item.checkState() == Qt.CheckState.Checked
def checkedItems(self):
return [self.itemText(i) for i in range(self.count()) if self.ifChecked(i)]
def checkedItemsStr(self):
return ';'.join(self.checkedItems()).strip('全选').strip(';')
def showPopup(self):
self.view().setMinimumWidth(3*self.width()//2) # 下拉列表宽度加大
self.view().setMaximumHeight(200) # 最大高度为200
super().showPopup()
def selectItemAction(self, index):
if index.row() == 0:
for i in range(self.model().rowCount()):
if self.SelectAllStatus:
self.model().item(i).setCheckState(Qt.CheckState.Checked)
else:
self.model().item(i).setCheckState(Qt.CheckState.Unchecked)
self.SelectAllStatus = (self.SelectAllStatus + 1) % 2
self.lineEdit().clear()
self.lineEdit().setText(self.checkedItemsStr())
def clear(self) -> None:
super().clear()
self.addCheckableItem('全选')
def select_all(self):
for i in range(self.model().rowCount()):
self.model().item(i).setCheckState(Qt.CheckState.Checked)
self.lineEdit().setText(self.checkedItemsStr())
class Ui_Study(QMainWindow):
def __init__(self):
super().__init__()
self.resize(500, 500)
self.setMinimumSize(500, 500)
self.combobox = CheckableComboBox(self)
self.combobox.move(20, 20)
self.combobox.resize(200, 30)
self.line_edit = QLineEdit(self)
self.line_edit.move(20, 80)
self.line_edit.resize(300, 30)
self.combobox.addCheckableItems(['sdsfdsf', 'hgjghj', 'reyeyey'])
self.combobox.setCurrentIndex(-1)
self.combobox.lineEdit().textChanged.connect(lambda: self.line_edit.setText(self.combobox.checkedItemsStr()))
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
my_ui = Ui_Study()
a = my_ui.combobox
sys.exit(app.exec())
部分细节优化点说明:
1. 通过setToolTip,给每个项目增加一个提示框,鼠标经过时显示其内容;
2. 重写showPopup函数,让下拉框宽度大于控件原本宽度,可以显示更多内容;
优化前(ComboBox宽度不够,例子略极端哈)
优化后
3. self.combobox.setCurrentIndex(-1),让选项框中不显示任何内容(默认会显示第一项);
4. 参考链接
Hello Qt(三十三)——Model/View官方文档_qt的 model/view框架能离线使用吗-CSDN博客
博客园这篇文章写的也很好,可作为参考: