Automatically update QTableView when data changes

I wrote a custom data model for display with several QTableViews.

Technically, everything works fine: my views show the changes made from my model. My data model is editable, and the setData() method emits a dataChanged() signal and returns true in a successful release.

However, my problem is that I need to move the mouse over the QTableView so that it displays the actual change, while I would like all the views to display the changes when they were made, without having to interact with the views to update them.

Any idea? Thanks,


It may be worth mentioning that I do not use the default role Qt::EditRole for editing data, but rather a user-defined enumeration value (named ActiveRole ).

Here's what I'm looking for: my data model contains properties on how to display the data used to create the style sheets that are served in viewS.

Thus, when changing the model for each view, all its elements are affected, therefore, the signal dataChanged() sent with indices covering all cells.

I also tried emitting layoutChanged() , but it doesn't seem to change the behavior in my case.

Here is an excerpt from the setData() method:

 bool DataModel::setData(QModelIndex const& idx, QVariant const& value, int role) { if (ActiveRole == role) { // Update data... QModelIndex topLeft = index(0, 0); QModelIndex bottomRight = index(rowCount() - 1, columnCount() - 1); emit dataChanged(topLeft, bottomRight); emit layoutChanged(); return true; } return false; } 

Here is an example of the data() method:

 QVariant DataModel::data(QModelIndex const& idx, int role) const { if (ActiveRole == role) { boost::uuids::uuid id; return qVariantFromValue(id); } return QVariant(); } 

And flags() points to the model being edited:

 Qt::ItemFlags DataModel::flags(QModelIndex const& idx) const { if (false == idx.isValid()) { return Qt::ItemIsEditable; } return QAbstractTableModel::flags(idx) | Qt::ItemIsEditable; } 

I have a user delegate that relies heavily on this SO stream to override the paint and sizeHint for drawing a QTextDocument addition, it provides ActiveRole content ActiveRole editor in setEditorData and calls DataMode::setData in setModelData :

 void DataModelDelegate::setEditorData(QWidget* editor, QModelIndex const& idx) const { auto active = qVariantValue<boost::uuids::uuid>(idx.data(ActiveRole)); static_cast<DataModelEditor*>(editor)->setActive(active); } void DataModelDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, QModelIndex const& idx) const { auto active = static_cast<DataModelEditor*>(editor)->getActive(); model->setData(idx, qVariantFromValue(active), ActiveRole); } 

In createEditor() I connect a signal from the editor to my delegate slot for data transfer:

 QWidget* DataModelDelegate::createEditor(QWidget* parent, QStyleOptionViewItem const& option, QModelIndex const& idx) const { auto editor = new DataModelEditor(parent); connect(editor, SIGNAL(activeItem()), this, SLOT(commitEditorData())); return editor; } 

When you click on an element, the editor fires an activeItem signal; the connected commitEditorData slot in turn triggers a commitData signal with an editor argument.

Thus, all my views use these custom delegation, editor, and data functions. The view I'm interacting with does show changes, but for other views, the mouse needs to vibrate over them to show the changes.

+7
source share
3 answers

I really found the problem that my other view was not properly notified of data changes: in my views each displayed different parts of my data, so the other views needed to be notified of dataChanged() , but for their own, the correct ones , indices.

On the other hand, I also had a problem updating my views, while my Qt application was not an active window in my window manager. The solution was to call repaint() in the main window.

+7
source

I ran into the same problem and let me add a detailed explanation to the piwi answers. If you change the data and that you need to update one or more columns (or rows, depending on your requirements), you must pass the set of indexes for topleft to bottomright. For example, if you have a table as shown below:

enter image description here

and now you have changed some data and want to update the row row 1, column 1-2, after which you should signal dataChange

 emit datachange(index(1,1),index(1,2)); 
+4
source

Do you call setData() ? Is the dataChanged() signal really emitting? Connect some debugging registration slot to it. I dare to suggest that this is very similar to your problem:

http://www.qtcentre.org/threads/18388-Refreshing-a-QTableView-when-QAbstractTableModel-changes?s=fd88b7c4e59f4487a5457db551f3df2c

0
source

Source: https://habr.com/ru/post/1439788/


All Articles