使用PyQt5编写界面, 使用了QTableView控件, 并使用代理,在TableView的列绑定下拉选择框,问题是,只要同时对两个列绑定了下拉选择框就会异常退出,报(0xC0000005)错误,注销任何一列的下拉代理,就会正常运行,实在找不出哪里问题。
单选下拉框代理类代码:
class SingleSelectDelegate(QStyledItemDelegate): # 导通和断开下拉选择
def __init__(self, items, parent=None): # #######################################################################################################
super().__init__(parent)
self.items = items
self.parent_widget = parent
def createEditor(self, parent, option, index):
try:
editor = QComboBox(parent)
editor.addItems(self.items)
return editor
except Exception as e:
QMessageBox.critical(self.parent_widget, "Error", f"创建编辑器失败: {str(e)}", QMessageBox.Ok)
return None
def setEditorData(self, editor, index):
# value = index.data(Qt.EditRole)
value = index.model().data(index, Qt.EditRole)
idx = editor.findText(value)
if idx >= 0:
editor.setCurrentIndex(idx)
def setModelData(self, editor, model, index):
model.setData(index, editor.currentText(), Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
自定义多选下拉框和下拉框代理类:
```python
class MultiSelectComboBox(QComboBox):
"""支持多选的自定义QComboBox"""
def __init__(self, parent=None):
super().__init__(parent)
self.setEditable(True)
self.lineEdit().setReadOnly(True)
self.setModel(None) # 先清空模型
# 创建列表控件并添加复选框
self.list_widget = QListWidget()
self.setModel(self.list_widget.model())
self.setView(self.list_widget)
# 创建按钮容器
self.button_widget = QWidget()
button_layout = QHBoxLayout(self.button_widget)
button_layout.setContentsMargins(5, 5, 5, 5)
button_layout.setSpacing(5)
# 全选按钮
self.select_all_btn = QPushButton("全选")
self.select_all_btn.setFixedHeight(25)
self.select_all_btn.clicked.connect(self.selectAllItems)
# 清除按钮
self.clear_btn = QPushButton("清除")
self.clear_btn.setFixedHeight(25)
self.clear_btn.clicked.connect(self.clearAllItems)
button_layout.addWidget(self.select_all_btn, alignment=Qt.AlignCenter)
button_layout.addWidget(self.clear_btn, alignment=Qt.AlignCenter)
# 将按钮添加到列表顶部
button_item = QListWidgetItem()
button_item.setSizeHint(QSize(0, 35))
self.list_widget.addItem(button_item)
self.list_widget.setItemWidget(button_item, self.button_widget)
# 默认样式设置
self.setStyleSheet("""
QComboBox {
border: 1px solid #ccc;
border-radius: 3px;
padding: 1px 18px 1px 3px;
min-width: 6em;
}
QComboBox::drop-down {
border: 0px;
width: 20px;
}
QListWidget {
border: 1px solid #ccc;
background: white;
outline: none;
}
QCheckBox {
padding: 3px;
spacing: 5px;
}
QCheckBox::indicator {
width: 16px;
height: 16px;
}
QPushButton {
border: 1px solid #ccc;
border-radius: 3px;
padding: 2px 8px;
background: #f0f0f0;
}
QPushButton:hover {
background: #e0e0e0;
}
""")
# 点击下拉框时不关闭
self.setStyleSheet("QComboBox::drop-down {border: 0px;}")
self.lineEdit().installEventFilter(self)
def selectAllItems(self):
"""全选所有项目"""
for i in range(1, self.list_widget.count()): # 跳过第一个按钮项
item = self.list_widget.item(i)
if item:
widget = self.list_widget.itemWidget(item)
if isinstance(widget, QCheckBox):
widget.setChecked(True)
self.updateText()
def clearAllItems(self):
"""清除所有选择"""
for i in range(1, self.list_widget.count()): # 跳过第一个按钮项
item = self.list_widget.item(i)
if item:
widget = self.list_widget.itemWidget(item)
if isinstance(widget, QCheckBox):
widget.setChecked(False)
self.updateText()
def setComboStyle(self, style_dict):
"""设置组合框样式"""
style_sheet = []
if 'border' in style_dict:
style_sheet.append(f"QComboBox {{ border: {style_dict['border']}; }}")
if 'border_radius' in style_dict:
style_sheet.append(f"QComboBox {{ border-radius: {style_dict['border_radius']}px; }}")
if 'padding' in style_dict:
style_sheet.append(f"QComboBox {{ padding: {style_dict['padding']}; }}")
if 'bg_color' in style_dict:
style_sheet.append(f"QComboBox {{ background-color: {style_dict['bg_color']}; }}")
if 'list_border' in style_dict:
style_sheet.append(f"QListWidget {{ border: {style_dict['list_border']}; }}")
if 'list_bg' in style_dict:
style_sheet.append(f"QListWidget {{ background: {style_dict['list_bg']}; }}")
if 'checkbox_spacing' in style_dict:
style_sheet.append(f"QCheckBox {{ spacing: {style_dict['checkbox_spacing']}px; }}")
self.setStyleSheet("\n".join(style_sheet))
def setItemStyle(self, index, style_dict):
"""设置特定项目的样式"""
if 0 <= index < self.list_widget.count():
item = self.list_widget.item(index)
widget = self.list_widget.itemWidget(item)
if 'color' in style_dict:
widget.setStyleSheet(f"color: {style_dict['color']};")
if 'font_size' in style_dict:
font = widget.font()
font.setPointSize(style_dict['font_size'])
widget.setFont(font)
if 'bg_color' in style_dict:
widget.setStyleSheet(f"background-color: {style_dict['bg_color']};")
def addItems(self, items):
"""添加多选项目"""
for item in items:
self.addItem(item)
def addItem(self, text, style=None):
"""添加单个项目"""
item = QListWidgetItem(self.list_widget)
checkbox = QCheckBox(text)
checkbox.setCheckState(Qt.Unchecked)
self.list_widget.addItem(item)
self.list_widget.setItemWidget(item, checkbox)
if style:
self.setItemStyle(self.list_widget.count() - 1, style)
def selectedItems(self):
"""获取选中的项目"""
selected = []
for i in range(1, self.list_widget.count()): # 跳过第一个按钮
item = self.list_widget.item(i)
widget = self.list_widget.itemWidget(item)
if widget and widget.isChecked():
selected.append(widget.text())
return selected
def setSelectedItems(self, items):
"""设置选中项"""
for i in range(1, self.list_widget.count()): # 跳过第一个按钮
item = self.list_widget.item(i)
widget = self.list_widget.itemWidget(item)
widget.setChecked(widget.text() in items)
self.updateText()
def updateText(self):
"""更新显示文本"""
selected = self.selectedItems()
self.lineEdit().setText(", ".join(selected) if selected else "未选择")
class MultiSelectDelegate(QStyledItemDelegate):
"""多选下拉框的表格列委托"""
def __init__(self, items, parent=None, style=None):
super().__init__(parent)
self.items = items
self.style = style or {}
def createEditor(self, parent, option, index):
"""创建编辑器"""
editor = MultiSelectComboBox(parent)
editor.addItems(self.items)
if self.style: # 设置下来框的样式
editor.setComboStyle(self.style)
return editor
def setEditorData(self, editor, index):
"""从模型设置编辑器数据"""
value = index.model().data(index, Qt.DisplayRole)
if value:
editor.setSelectedItems(value.split(","))
def setModelData(self, editor, model, index):
"""将编辑器数据保存到模型"""
model.setData(index, ",".join(editor.selectedItems()), Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
"""更新编辑器几何形状"""
editor.setGeometry(option.rect)
主程序中的代理加载代码:
```python
# 创建表格模型
self.model = QStandardItemModel()
self.tableView.setModel(self.model)
self.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
# 添加标题行
self.model.setHorizontalHeaderLabels(headers) # 添加列标题
# 允许用户通过右键菜单插入行
combo_style = {
'border': '2px solid #4CAF50',
'border_radius': 5,
'padding': '2px 20px 2px 5px',
'bg_color': '#f8f8f8',
'list_border': '1px solid #4CAF50',
'list_bg': '#f0fff0',
'checkbox_spacing': 8
}
# 为第四列设置代理(索引从0开始)
self.tableView.setItemDelegateForColumn(3, MultiSelectDelegate(switches, style=combo_style))
self.tableView.setItemDelegateForColumn(4, SingleSelectDelegate(data))
self.tableView.horizontalHeader().resizeSection(3, 500) # 设置第四列宽度为500像素
self.tableView.horizontalHeader().resizeSection(4, 100) # 设置第四列宽度为500像素
self.tableView.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.SelectedClicked)