PDA

View Full Version : QTreeView repaint



graeme
2nd May 2006, 20:30
I am updating some data that is displayed in a QTreeView, but the change in the data it is not being displayed. I have tried explicit calls to repaint(), update(), dataChanged(), (on both the QtreeView and the containing window) plus a few others but no joy.

However if I click on any item in the QTreeView, or on another window then the change is updated, so I know that the change is in my model. Does anyone have any ideas on how I can get the QTreeView to automatically display the new state?

thanks.

jacek
2nd May 2006, 20:55
Do you use a custom model with that QTreeView?

graeme
2nd May 2006, 21:15
Yes I do have a custom model.

jacek
2nd May 2006, 21:25
Yes I do have a custom model.
Does it emit dataChanged() signal?


void QAbstractItemModel::dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight ) [signal]
This signal is emitted whenever the data in an existing item changes. The affected items are those between topLeft and bottomRight inclusive (of the same parent).
Note that this signal must be emitted explicitly when reimplementing the setData() function.
See also headerDataChanged(), setData(), and layoutChanged().

graeme
2nd May 2006, 21:26
I do not use the model to change the data. My window has a QTreeView, when an item is selected the details are displayed in a separate area in edit boxes. If these values are changed then the underlying data items are changed. Because the model referes to these via pointers the change is in the model. But I can't get the QTreeView to repaint itself.

jacek
2nd May 2006, 21:29
But does this model emit dataChanged() signal when you change the data?

graeme
2nd May 2006, 21:29
I don't use the setData() because I'm not changing it from within the model but I did try and fire off the dataChanged() from the window but that didn't work. However I can try and see what happens if I do it via the setData.

jpn
2nd May 2006, 21:33
You will have to do the changes through the model, or at least inform the view somehow that the model has been changed. Otherwise the view has no way of knowing about data changes.

Check this thread. (http://www.qtcentre.org/forum/showthread.php?t=978)

graeme
2nd May 2006, 21:38
How do I inform the view that the data has changed?

I've tried repaint(), update(), and dataChanged() but none appear to work. But as soon as I click to another window (even if it doesn't overlap) then the change is reflected.

jacek
2nd May 2006, 21:40
I've tried repaint(), update(), and dataChanged() but none appear to work.
How and when did you try to emit the dataChanged() signal?

graeme
2nd May 2006, 21:59
This is how I sent the signal


wdgt.trvModules->dataChanged(wdgt.trvModules->currentIndex(),wdgt.trvModules->currentIndex());

I had it right at the end of the method that changes the data. I have also added a call to setData in the same place.


wdgt.trvModules->model()->setData(wdgt.trvModules->currentIndex(),classSize);

wdgt.trvModules->dataChanged(wdgt.trvModules->currentIndex(),wdgt.trvModules->currentIndex());

Where wdgt.trvModules is a pointer to teh QTreeView and I'm changing the selected (singular) item.

graeme
2nd May 2006, 22:33
I have also tried the following:


bool RootModel::setData ( const QModelIndex & index, const QVariant & value, int role)
{
if (!index.isValid())
return false;

if (role != Qt::EditRole)
return false;

RootItem *item = getRootItem(index);
item->setData(index.column(),value);
emit dataChanged(index, index);
return true;
}

Where item->setData() changes the value held in the item. Again if I click on an item it will reflect the change (on on another window) but not otherwise.

jacek
2nd May 2006, 22:36
This is how I sent the signal


wdgt.trvModules->dataChanged(wdgt.trvModules->currentIndex(),wdgt.trvModules->currentIndex());
You didn't send the QAbstractItemModel::dataChanged() signal, instead you have invoked the QAbstractItemView::dataChanged() protected slot.

Although it should have a similar effect. Are you sure that wdgt.trvModules->currentIndex() is valid?


I have also added a call to setData in the same place.
Forget about setData() --- it doesn't do anything, if you didn't implement it.

graeme
2nd May 2006, 22:55
Tweeking with the setData I have the following which works...


bool RootModel::setData ( const QModelIndex & index, const QVariant & value, int role)
{
if (!index.isValid())
return false;

if (role != Qt::EditRole)
return false;

beginInsertRows(index.parent(), rowCount(index.parent()), rowCount(index.parent()));
RootItem *item = getRootItem(index);
item->setData(index.column(),value);
emit dataChanged(index, index);
endInsertRows();
return true;
}

By telling it that I am inserting some rows at the end it will then repaint the view. This doesn't look right to me but it does work.

jacek
3rd May 2006, 00:04
emit dataChanged(index, index);
Maybe you should try to emit that signal for the whole row?

Try something like:
emit dataChanged( index( row, 0 ), index( row, nCols-1 ) );

graeme
3rd May 2006, 00:44
I tried that and as many variants that I could think of but no luck.
Finishing with:

emit dataChanged(index( 0, 0, pIndex.parent())
, index( rowCount(), item->columnCount()-1,pIndex.parent() ));

Where pIndex is the index of the selected item.

I'd also tried with the row being pIndex.row(), with and without the last argument to index. But I still can't get it to repaint.

graeme
3rd May 2006, 02:54
Eat my own words...
On the last tests I wasn't actually calling the setData() method. Once I did that it worked. I have now been able to move it back out of the setData() method and just emit the dataChanged() signal via a new method of the model class and it works.

So essentially I needed to call the whole row as part of the dataChanged() signal.

Thank you very much jacek for your assistance.

karenh
13th March 2012, 13:27
you can replace standart model by QSortFilterProxyModel and use public slot QSortFilterProxyModel::invalidate().