【问题标题】:PushButton in Qt Model/View TableQt 模型/视图表中的按钮
【发布时间】:2020-02-27 04:16:00
【问题描述】:

我正在 PyQt5 中编写自定义 TableModel,继承自 QtCore.QAbstractTableModel。我希望我的表格有一列只有 CheckBoxes,没有文本,每行有一列有一个 PushButton。

我尝试在data 方法中为Qt.Display 角色返回一个QPushButton 对象,但显然这是不可能的。

所以我的问题是:我可以在模型本身中实现它为某些单元格返回某些小部件吗?在我看来,这就是模型的工作,但我该如何实现呢?

我的第二个问题是我必须如何分配插槽,以便我知道从哪个按钮(从哪一行)发生了操作?

【问题讨论】:

    标签: python pyqt pyqt5 qtableview qabstracttablemodel


    【解决方案1】:

    解释:

    我可以在模型本身中实现它为某些单元格返回某些小部件吗?在我看来,这是模型的工作,但我该如何实现呢?

    可能是模型提供了小部件,但并不常见。一般来说,模型提供的信息会通过委托来展示,是可以提供小部件的委托。也可以使用 setIndexWidget 方法在模型的未链接视图上设置小部件。

    考虑第一种情况,解决方案是实现委托。

    我必须如何分配插槽,以便我知道从哪个按钮(从哪一行)发生了操作?

    一般来说,用作编辑器的小部件,因此您必须更新模型,然后模型可以通过 dataChanged 信号通知其他元素,例如,如果用户编写了文本或更改了复选框的状态,但在单击的情况不会通知永久更改,而是暂时的。考虑到这一点,代表可以提出一个信号。

    解决办法:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class PushButtonDelegate(QtWidgets.QStyledItemDelegate):
        clicked = QtCore.pyqtSignal(QtCore.QModelIndex)
    
        def paint(self, painter, option, index):
            if (
                isinstance(self.parent(), QtWidgets.QAbstractItemView)
                and self.parent().model() is index.model()
            ):
                self.parent().openPersistentEditor(index)
    
        def createEditor(self, parent, option, index):
            button = QtWidgets.QPushButton(parent)
            button.clicked.connect(lambda *args, ix=index: self.clicked.emit(ix))
            return button
    
        def setEditorData(self, editor, index):
            editor.setText(index.data(QtCore.Qt.DisplayRole))
    
        def setModelData(self, editor, model, index):
            pass
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
    
        w = QtWidgets.QTableView()
        model = QtGui.QStandardItemModel(0, 2)
        for i in range(10):
            it1 = QtGui.QStandardItem()
            it1.setData(QtCore.Qt.Checked, QtCore.Qt.CheckStateRole)
            it1.setFlags(it1.flags() | QtCore.Qt.ItemIsUserCheckable)
            it2 = QtGui.QStandardItem()
            it2.setData("text-{}".format(i), QtCore.Qt.DisplayRole)
            model.appendRow([it1, it2])
    
        # pass the view as parent
        delegate = PushButtonDelegate(w)
        w.setItemDelegateForColumn(1, delegate)
    
        def on_clicked(index):
            print(index.data())
    
        delegate.clicked.connect(on_clicked)
    
        w.setModel(model)
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 非常感谢,这对我很有帮助,我想我现在明白如何使用 Delegate 了。我已将此解决方案应用于另一列,我希望在其中拥有QDoubleSpinBoxes。但是当表格打开时,它们都选择了它们的内容(蓝色)。你有什么提示我可以避免这种情况吗?我已经尝试过doubleSpinBox.clearFocus()doubleSpinBox.lineEdit().deselect(),但没有帮助。
    猜你喜欢
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    相关资源
    最近更新 更多