PySide QTableView setData 用于多个单元格

Posted

技术标签:

【中文标题】PySide QTableView setData 用于多个单元格【英文标题】:PySide QTableView setData for multiple cells 【发布时间】:2016-11-24 09:08:48 【问题描述】:

我正在使用 QTableView 并子分类为 QAbstractTableModel。编辑单元格时,我注意到QAbstractTableModel.setData 只通过最后一个选定的单元格。有没有办法让setData 处理多个(选定的)单元格?

作为使用示例:

从表格中选择四个单元格。 开始编辑一个单元格。 输入一个值并按回车键提交。 让值修改所有四个单元格(目前它只修改最后选择的单元格)

我尝试对closeEditor 进行子类化,然后循环通过selectedIndexes 以使用setData 调用它们,但我不知道如何从closeEditor 获取用户的输入值。

这是我的尝试,差不多了,只需要输入值。

def closeEditor(self, editor, hint):
    is_cancelled = (hint == QtGui.QAbstractItemDelegate.RevertModelCache)

    if not is_cancelled:
        for index in self.selectedIndexes():
            if index == self.currentIndex():
                continue

            input_value = ??? # Don't know how to get this from here!

            self.model().setData(index, input_value, QtCore.Qt.EditRole)

    return QtGui.QTableWidget.closeEditor(self, editor, hint)

【问题讨论】:

【参考方案1】:

closeEditor 信号中的editor 是用于编辑的小部件。

如果是,例如QLineEdit,您可以通过其text 属性读取它的文本。

获取属性值的一种方法是通过 QObject 的属性 API

value = editor.property("text")

【讨论】:

编辑器是QWidget,所以没有text属性。 正如我所写:如果小部件是QLineEdit,那么它有一个文本属性。 IE。这取决于哪个小部件被用作编辑器。默认委托对文本使用行编辑,对数字使用旋转框等 那它使用哪一个呢? editor 的类名是什么? IE。 editor.metaObject().className()的值? editor.metaObject().className()QExpandingLineEdit。虽然type(editor)QWidget,所以我不能像你建议的那样只打电话给editor.text,因为它不存在。 editor().metaObject() 中的值是否填充在某处?我检查了它的文档,但真的找不到方法。 @GreenCell。这里给出的答案在技术上是正确的。 QExpandingLineEdit 是一个内部 Qt 类,它是 QLineEdit 的子类。 PySide 中似乎有一个错误,因为它应该将QLineEdit 的实例传递给closeEditor,而不是QWidget。相同的代码在 PyQt4 中可以正常工作(即它传递了一个QLineEdit)。【参考方案2】:

编辑:我将其用作解决方法,因为 PySide 中有一个错误,其中 editor 仅返回 QWidget。请看 Kevin Krammer 的回答!

虽然这是一个小问题,但到目前为止我的解决方案似乎运行良好。请告诉我是否有更好的方法,这有点啰嗦。

closeEditor 中,我让每个单元格都通过setData,并以None 作为值。

然后在QAbstractTableModel 我有一个变量_input_value 将存储用户的输入以供其余单元格抓取。

class TableView(QtGui.QTableView):

    def __init__(self, parent=None):
        super(TableView, self).__init__(parent)

    def closeEditor(self, editor, hint):
        is_cancelled = (hint == QtGui.QAbstractItemDelegate.RevertModelCache)

        if not is_cancelled:
            for index in self.selectedIndexes():
                if index == self.currentIndex():
                    continue

                # Supply None as the value
                self.model().setData(index, None, QtCore.Qt.EditRole)

        # Reset value for next input
        if self.model()._input_value is not None:
            self.model()._input_value = None

        return QtGui.QTableWidget.closeEditor(self, editor, hint)


class TableModel(QtCore.QAbstractTableModel):

    def __init__(self, parent=None):
        super(TableModel, self).__init__(parent)

        self.main_widget = parent

        self._input_value = None

    def setData(self, index, value, role):
        # Triggers if user cancelled input
        if value is None and self._input_value is None:
            return False

        if self._input_value is None:
            # The last selected cell will pass through here to store the value.
            self._input_value = value
        else:
            # All other cells will pass None, so just grab our stored value.
            value = self._input_value

        # Do whatever you want with value now

        return True

【讨论】:

以上是关于PySide QTableView setData 用于多个单元格的主要内容,如果未能解决你的问题,请参考以下文章

不允许在 pyside 的 QTableView 中复制/粘贴

PySide + SQLAlchemy 中 QTableView 的“模型”设计

如何使用 pyside 在 QtableView 单元格中设置数据

QTableview,PySide2中单元格的背景颜色

QTableView 上的 PySide 委托,带有文本和刻度

PySide2 QListView QTableView 同步问题