PyQt6 优化操作:下拉列表框 QcomboBox 支持多选(含全选项)

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博客

博客园这篇文章写的也很好,可作为参考:

https://www.cnblogs.com/TM0831/p/12588841.html

PyQt - Fixed title for combobox - Stack Overflow

  • 30
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值