【发布时间】:2020-01-17 15:43:25
【问题描述】:
我对更好的选择持开放态度,但我在这里得到的是一个使用绿色和红色颜色代码而不是“已选中”和“未选中”的复选框。
我将它与自定义 QStyledItemDelegate、QTableView 和 QAbstractTableModel 一起使用,目的是存储“复选框”的状态。
问题是鼠标按下时未调用委托 setModelData。 请注意,此问题在我的任何其他自定义小部件(例如自定义 QDateEdit 和 QLineEdit)中都不存在,为此我无需执行任何操作(在小部件代码中)以使 setModelData 调用发生。
这就是为什么我确定问题是我在这个类代码中遗漏了一些东西。我的猜测是在 QToolButton 的代码中默认为无操作的信号或某些方法的实现。不过是哪一个?
编辑:请求的完整示例,相关代码是 ColorCheckBox,其余部分是使其运行所必需的。 当您单击该框时,它应该会打印更改的值,但在开始时会打印两次,它不会。
from PyQt5 import QtCore, QtWidgets
import sys
def validate(value, expected_type):
if type(value) == QtCore.QVariant:
value = None if value.isNull() or not value.isValid() else value.value()
if expected_type is bool and not value:
return False
value = expected_type() if value is None else expected_type(str(value))
return value
class ColorCheckBox(QtWidgets.QToolButton):
def __init__(self, parent=None):
super().__init__(parent)
self.bool = False
self.setStyleSheet("background-color: red")
def data(self):
return self.bool
def set_data(self, value):
self.set_checked(validate(value, bool))
self.update()
def set_checked(self, value):
self.bool = value
if self.bool:
self.setStyleSheet("background-color: green")
else:
self.setStyleSheet("background-color: red")
def mousePressEvent(self, event):
super().mousePressEvent(event)
if event.button() == QtCore.Qt.LeftButton:
self.set_data(not self.bool)
class MyWindow(QtWidgets.QWidget):
def __init__(self, *args):
super().__init__(*args)
tableview = TableView()
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(tableview)
self.setLayout(layout)
class Delegate(QtWidgets.QStyledItemDelegate):
def __init__(self, model):
super().__init__()
self.model = model
def createEditor(self, parent, option, index):
widget = ColorCheckBox(parent)
widget.set_data(False)
return widget
def setModelData(self, widget, model, index):
self.model.setData(index, widget.data())
def setEditorData(self, widget, index):
widget.set_data(index.data())
class Model(QtCore.QAbstractTableModel):
def __init__(self, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent=parent)
def flags(self, index):
return super().flags(index) | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid() or role != QtCore.Qt.DisplayRole:
return QtCore.QVariant()
return QtCore.QVariant('False')
def setData(self, index, value, role=QtCore.Qt.EditRole):
print("data[{}][{}] = {}".format(index.row(), index.column(), value))
return True
def rowCount(self, parent=QtCore.QModelIndex()):
return 1
def columnCount(self, parent=QtCore.QModelIndex()):
return 1
class TableView(QtWidgets.QTableView):
def __init__(self, parent=None):
super().__init__(parent)
self.model = Model(self)
delegate = Delegate(self.model)
self.setItemDelegate(delegate)
self.setEditTriggers(self.CurrentChanged)
self.setModel(self.model)
for row in range(self.model.rowCount()):
for column in range(self.model.columnCount()):
index = self.model.index(row, column)
self.openPersistentEditor(index)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
【问题讨论】:
-
您是否使用 ColorCheckBox 作为代理的编辑器?您能否也为您的委托向我们展示一个可重现的最小代码?
-
@musicamante 我已根据您的要求添加了我的代表。我不确定你的第一个问题是什么。如果你问我是否有委托处理这个小部件,那么答案是肯定的。我要做的就是让 pandas 数据框被可视化和修改,我正在使用自定义 QTableView 和小部件来为数据框提供更好的输入和可视化。
-
@Dirich 我们在问你,因为我也加入了请求,minimal reproducible example 来测试你的代码并分析问题,你的代码不是 MRE,所以如果你需要帮助,请提供你所拥有的要求。
-
我已将代码更改为一个完整的工作示例,这通常意味着失败,包括自定义委托、qtableview 和模型在内的任何内容,即使是极简主义,你最终总是超过 100 行,而人们只是不要不想看那个。