Qt : setData method in a QAbstractItemModel

依然范特西╮ 提交于 2019-12-01 17:23:26

To quote from the video tutorial regarding setData:

...this function needs to return true if the operation was successful, or else the view will not update itself.

Strictly speaking, this statement is false. The documentation for QAbstractItemModel only says that setData returns true if the data was set successfully, and false otherwise; it does not mention what the consequences of this might be. Specifically, it does not mention anything about updating the view.

Looking at the Qt source code, the return value of setData does get checked in a few places, and some of those checks can sometimes help trigger an update. But there are literally dozens of things that can trigger an update, so the return value of setData is in no way essential for updating items.

Perhaps it would have been more accurate to say that setData should return true, otherwise the view may not update itself (under certain circumstances).

Am I misunderstanding the return role in the setData method or is it a bug ?

From the Qt documentation:

bool QAbstractItemModel::setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) [virtual]

Sets the role data for the item at index to value.

Returns true if successful; otherwise returns false.

The dataChanged() signal should be emitted if the data was successfully set.

The base class implementation returns false. This function and data() must be reimplemented for editable models.

Yet, you seem to emit the dataChanged() signal even if the data is not successfully set based on the return value. Also, the tutorial you seem to refer to, is using the self.__colors set in your code for the rowCount(), `data(), and other methods. If you would like to avoid the update, you will need to return False before any such statement.

You need to pay attention to these criterias because the signal and the colors are managed internally while the return value is used by the caller to see if the setData() method had been successfully set.

Based on the knowledge above, you should have written this code for your second attempt to make it work as you expect it to:

def setData(self, index, value, role = QtCore.Qt.EditRole):
    if role == QtCore.Qt.EditRole:

        row = index.row()
        color = QtGui.QColor(value)

        if color.isValid():
            return False
    return False

I couldn't find much info on this. That said, this forum post by a "Qt Specialist" suggests that this behavior is a design choice by the Qt developers:

http://qt-project.org/forums/viewthread/31462

More specifically, the views do not lose your input if it gets rejected by the model. This may seem weird in the context of the tutorial you are following (where the color changes out of sync with the model), but in some contexts this might be desirable.

As an example, let's say you have designed a form using QLineEdits and QDataWidgetMapper to map the contents of the form to your model. Let's also suppose that QDataWidgetMapper::SubmitPolicy is set to AutoSubmit. In AutoSubmit mode, every time the QLineEdit is edited and then loses focus, the model is updated. If the model also rejects the change, and the current data (sans change) is repopulated into the QLineEdit, this would have the effect of the user having to start over (rather than fixing up their entry).

The alternative design choice is to allow the view to be out of sync with the model and, if this is undesirable, to push the responsibility to change this behavior onto the programmer.

Two ways that I can think of off-hand to change this behavior would be to:

  1. Create a custom delegate that handles setData -> false by emitting a custom dataRejected signal that the view could connect to and use to update itself.
  2. Create a "stateless" view for your model: force the view to retrieve data from the model any time it updates itself. In this manner, submitting a potential change to the model will not update the view unless that model emits a dataChanged signal, in which case the view will retrieve current state and update itself.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!