行业资讯

PYQT:使用QComboBox做一个可以多选的下拉列表框

发布时间:2026/7/8 2:29:33
PYQT:使用QComboBox做一个可以多选的下拉列表框 一、功能背景在传统桌面应用开发中Qcomboxox默认设计只支持单项选择。但是在实际业务系统中经常存在多条件筛选需求,要实现此功能需要创建多个部件或使用弹窗来实现因此实现一个支持下拉展开多选复选框全选/取消全选半选状态显示当前选择结果回显的自定义ComboBox控件可以有效提升用户体验。二、整体设计思路使用 QComboBox 作为外层容器将内部下拉列表替换为 QListWidget并在 QListWidget 每一项中嵌入 QCheckBox。实现结构如下ComboCheckBox(QComboBox)|---- QLineEdit|---- QListWidget|-- QListWidgetItem|-- QCheckBox|-- QCheckBox|-- QCheckBox三、核心实现原理1. 重写 QComboBox 下拉内容因为QT的默认显示行为仅支持显示文本因此我们要替换默认的部件self.list_widget QListWidget()在设定显示内容时将显示模型替换self.setModel(self.list_widget.model())self.setView(self.list_widget)2.代码实现其他部分的代码我直接贴上可以自行查阅class ComboCheckBox(QComboBox): 带有下拉列表的 QComboBox使用 set_items 传入列表通过 get_selected_list 获取值 signal Signal(list) def __init__(self,borderTrue, edit_nameNone): super().__init__() # 选择行的数量 self.edit_name edit_name self.selected_row_num 0 self.checkboxes [] self.show_items [] self.line_edit QLineEdit() self.line_edit.setReadOnly(True) self.list_widget QListWidget() self.setObjectName(ComboBox) self.setStyleSheet(self._build_qss(border)) def _build_qss(self, border: bool): base_border 1px solid #C0C0C0 if border else none padding_left 10px if border else 5px return f #ComboBox {{ height: 25px; border: {base_border}; border-radius: 4px; padding-left: {padding_left}; background-color: white; }} /* hover状态 */ #ComboBox:hover {{ border: 1px solid #409EFF; }} /* 下拉按钮区域 */ #ComboBox::drop-down {{ subcontrol-origin: padding; subcontrol-position: top right; width: 20px; border: none; }} /* 箭头 */ #ComboBox::down-arrow {{ image: url(app//assets//icon//down.png); width: 10px; height: 10px; margin-right: 5px; }} #ComboBox::down-arrow:on {{ top: 1px; left: 1px; }} /* 下拉列表 */ QComboBox QAbstractItemView {{ border: 1px solid #E4E7ED; selection-background-color: #409EFF; selection-color: white; outline: none; }} def set_items(self, show_items: list): 设置要展示的数据 :param show_items: 展示列表 # 清除之前的复选框 self.checkboxes.clear() self.show_items [全部] show_items show_items_len len(self.show_items) for i in range(show_items_len): checkbox self.add_checkbox(self.show_items[i]) if i 0: checkbox.stateChanged.connect(self.handle_all_checkbox) else: checkbox.stateChanged.connect(self.update_display) self.setModel(self.list_widget.model()) self.setView(self.list_widget) self.setLineEdit(self.line_edit) self.setMaxVisibleItems(100) def add_checkbox(self, text): 向 QListWidget 添加复选框并将对象添加到复选框列表中 :param text: 复选框显示的文本 :return: 添加的复选框对象 self.checkbox QCheckBox() self.checkbox.setText(text) item QListWidgetItem(self.list_widget) self.list_widget.setItemWidget(item, self.checkbox) self.checkboxes.append(self.checkbox) return self.checkbox def update_display(self): 更新显示的选中项文本并发射信号 selected_items self.get_selected_list() display_text ;.join(selected_items) self.line_edit.clear() self.line_edit.setText(display_text) self.selected_row_num len(selected_items) if self.selected_row_num 0: self.checkboxes[0].setCheckState(Qt.Unchecked) elif self.selected_row_num len(self.show_items) - 1: self.checkboxes[0].setCheckState(Qt.Checked) else: self.checkboxes[0].setCheckState(Qt.PartiallyChecked) def get_selected_list(self): 返回选中的复选框的文本列表修改 selected_row_num 的值 :return: 选中项的文本列表 selected [] for checkbox in self.checkboxes[1:]: try: if checkbox.isChecked(): selected.append(checkbox.text()) except RuntimeError: # 对象已被删除 continue return selected def handle_all_checkbox(self, state): 全选的复选框有三种状态选中自动选中所有未选中清除所有半选中判断选中的选项的长度若为 0 那么全选否则不变 :param state: 全选复选框的状态 if state 2: for checkbox in self.checkboxes[1:]: checkbox.setChecked(True) elif state 0: self.clear_selection() elif state 1 and self.selected_row_num 0: self.checkboxes[0].setCheckState(Qt.Checked) def clear_selection(self): 清除选择框体的内容 for checkbox in self.checkboxes: checkbox.setChecked(False)