在PyQt的QAbstractTableModel中编辑表格而不删除内容

3

到目前为止我做了什么:

我正在实现一个自定义的QAbstractTableModel(在QTableView小部件中使用),其中包含可编辑单元格。这些单元格的属性在我的flags()方法中指定,如下所示:

def flags(self, index):  # Qt was imported from PyQt4.QtCore
    if index.column() < 2:
        return Qt.ItemIsEditable | Qt.ItemIsEnabled | \
               Qt.ItemIsSelectable
    else:
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable

第一列和第二列的单元格已经被标记为可编辑,就像我想要的那样。

我的需求:

然而,当双击单元格以触发编辑时,其中的文本会被删除,留下一个空白字段。

Example of editing a cell

但是,我不想删除和替换包含的文本,因为包含的文本可能非常长,不应该重新输入。我只想编辑已经包含的内容。当双击单元格时,应该可以编辑先前包含的文本(可能已经被选中)。

问题:

如何实现这种行为?我需要编辑我的标志方法并为这些单元格指定不同的属性吗?

2个回答

4
你有几个选项。
在编辑期间单元格中没有数据显示,这是因为你可能没有为模型中的每个项目设置任何数据,需要在 Qt.EditRole 上设置数据。默认情况下,QTableWidget 会自动执行此操作。
另一种方法是使用 QItemDelegate。这将允许你手动创建编辑器部件,并在它出现在 QTableView 中之前进行初始化。如果编辑文本尚未填充,可以使用显示角色文本。
class MyDelegate(QtGui.QItemDelegate):

    def createEditor(self, parent, option, index):
        if index.column() == 2:
            return super(MyDelegate, self).createEditor(parent, option, index)
        return None

    def setEditorData(self, editor, index):
        if index.column() == 2:
            # Gets display text if edit data hasn't been set.
            text = index.data(Qt.EditRole) or index.data(Qt.DisplayRole)
            editor.setText(text)         

delegate = MyDelegate()
tableview.setItemDelegate(delegate)

1
我认为你不需要在你的模型中做任何事情。但是,为什么你需要创建一个自定义模型还有待商榷。QStandardItemModel不能满足你的需求吗?如果你只想控制标志,你可以在创建项目时设置它们。这不必是模型上的动态函数。 - Brendan Abel
1
此外,除非您知道需要哪种模型,否则项目小部件类(QTreeWidgetQTableWidget等)通常就足够了,而且通常编码和创建速度更快,代码也更简单。 - Brendan Abel
嘿,我想要完全相反的效果。我有一个自定义的QListWidget,当我单击项目以重命名它时,我只能看到旧名称,即使我开始输入也无法删除它,当我按Enter键时,它会消失并得到新的名称,但这很烦人,我希望按Enter键时它能像应该做的那样表现!请帮帮我。 - Nestor Colt
@NestorColt 欢迎!您应该提交一个新问题来描述您的问题。评论并不是回答新问题的好地方。 - Brendan Abel
1
@user118967 Qt和PySide的文档非常好,详细介绍了大部分内容。此外,如果下载带Creator或Designer的PySide或Qt,它们将包含各种小部件类型的示例。 - Brendan Abel
显示剩余3条评论

2
如Brendan Abel所说,编辑时单元格中没有显示任何数据,因为您可能没有在模型中的每个项目上设置Qt.EditRole的数据。
在这种情况下,为了在双击单元格后显示先前的数据,需要将data()作为EditRole访问,因此您应该在继承的模型类中实现data()方法,例如:
def data(self, index, role=None):
    ...
    if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
        item = index.internalPointer()
        return item.data[index.column()]
    ...

模型视图编程的官方文档中也提到了这一点。


index.internalPointer() 在 PyQt5 中返回 None。 - Ciasto piekarz
@Ciastopiekarz doc 上说它返回一个指向内部数据的指针,在我的应用程序中,只要索引有效,它确实会返回一个数据对象,而不是 None。 - Claude C
我感谢关于包含EditRole条件的信息。然而,这个答案建议获取QTableView的“index”对象数据。这似乎与整个模型-视图概念相矛盾,即数据(模型)应该与视图分离。返回值可以从模型用于存储其数据的任何自定义数据结构中计算或读取,而不一定是从index.internalPointer中。实际上,OP可能已经有了一个执行“data”的实现,只需要添加条件“role == QtCore.Qt.EditRole”。 - user118967
1
@user118967 谢谢您的建议。我只是简单地遵循了官方的模型视图示例 源代码。在代码中,data(..)(第143行)调用 getItem(..)(第159行),最终调用 index.internalPointer()(第161行)。我认为这应该是无害的,因为 index 是由模型类中的 index(..) 产生的模型索引对象,而不是由视图产生的。 - Claude C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接