PDA

View Full Version : QTreeWidget not updating content...



lni
15th November 2007, 01:23
Hi,

I have a QTreeWidget with several items, and I have a timer running to dynamically change the text of the tree item each few seconds.

I then use QTreeWidgetItem::setText trying to update the content, but nothing changes in the tree display, unless I click a button on the item or change the selection, or cover and window on the tree and then expose it...

How can I force the tree to repaint? I call QTreeWidget::repaint and it crashes, I also try QTreeWidget::update but nothing work, I also use QApplication::sendEvent( myTree, ...), and it does not work either....

Any comments?

Thanks

momesana
15th November 2007, 03:33
Try out this piece of code. For me it works without userinteraction.



#include <QApplication>
#include <QtGui>

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent=0) : QMainWindow(parent)
{
treeWidget = new QTreeWidget;
for (int i = 0; i < 50; ++i)
treeWidget->addTopLevelItem(new QTreeWidgetItem);
doSomething();
setCentralWidget(treeWidget);
startTimer(2000);
}

void timerEvent(QTimerEvent* ) { doSomething(); }
private:
QTreeWidget* treeWidget;
private slots:
void doSomething()
{
static int x = 0;
QTreeWidgetItemIterator iter(treeWidget, QTreeWidgetItemIterator::All);
int i = 0;
while(*iter) {
(*iter)->setText(0, QString("row:%1 - modified: %2 times").arg(i).arg(x));
++i; ++iter;
}
x++;
}
};

#include "main.moc"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow mw;
mw.show();
return app.exec();
}

lni
20th November 2007, 23:22
I was doing the update in a thread, in my app, the fields need to be recalculated, which take several seconds. I hope to use thread so the GUI won't freeze. But then it does not update...



#include <QApplication>
#include <QThread>
#include <QtGui>

#include <iostream>

class MyThread : public QThread {

public:
MyThread( QTreeWidget* w ) : treeWidget( w ) {}

protected:
void run()
{
std::cout << "MyThread::run called" << std::endl;

static int x = 0;
QTreeWidgetItemIterator iter(treeWidget, QTreeWidgetItemIterator::All);
int i = 0;
while(*iter) {
(*iter)->setText(0, QString("row:%1 - modified: %2 times").arg(i).arg(x));
++i; ++iter;
}
x++;
}

private:

QTreeWidget* treeWidget;

};

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent=0) : QMainWindow(parent)
{
treeWidget = new QTreeWidget;
thread = new MyThread( treeWidget );
for (int i = 0; i < 50; ++i)
treeWidget->addTopLevelItem(new QTreeWidgetItem);
setCentralWidget(treeWidget);
QMainWindow::startTimer(2000);
}

void timerEvent(QTimerEvent* ) {
if ( !thread->isRunning() ) thread->start();
}
private:
QTreeWidget* treeWidget;
QThread* thread;
};

#include "main.moc"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow mw;
mw.show();
return app.exec();
}

wysota
20th November 2007, 23:41
You can't update widgets from within threads. Widgets are not thread safe nor even reentrant.

The Storm
20th November 2007, 23:43
The only way to update the GUI interface throuth non-gui thread is to use signals and slots connections, else it can even crash.

Edit: Oops wysota was faster than me. :P

debaspaul
12th October 2009, 13:32
I am dealing with a similar problem, where I try to update my QTreeWidegetItem text (I have only one column) through a signal slot in my QTreeWidget class.

My display for each item is like : <variable> == <value> like "abc = 1 or abc == 0".

The above tree item value gets changed in my signal slot (e.g when I drag a horizontal slider in my widget) and I use setItemDelegate class method paint() to display the same.
This paint functions rightly calculates the string like "abc == 1" for any position of the slider.

1. Now how can I call the ItemDelegate::paint() from my Slot function (when I change the slider position ) ? My purpose is to refresh value in the new slider position. As usual If the hides and comes back into my tree view it shows the correct string.

2. I have tried calling setText(0, str) where str = "abc == 1" but this is not OK as I want to customize my display inside paint() like color/font of the value part etc.


Any idea would be of great help for me.

whyameye
14th August 2010, 16:40
so what is the right way to do this? I have the same problem as the original poster where some calculations take a long time and I can't hold up the GUI during that time. I tried having the non-gui thread call functions in the gui thread that do the updating, but that seems to give inconsistent results (sometimes crash, sometimes not update everything, sometimes work fine.) I didn't understand the explanations of how to solve the problem with slots/signals.

I'm trying having my non-gui thread which does the calculations update variables in the gui thread, then using a timeout in the gui thread to periodically check the variables for changes and update accordingly. I'm not even sure if this solution works...and...I'm guessing there is a better way...

The Storm
14th August 2010, 17:06
Using timer to check your Thread's class for value updates is fine if you are pulling out updates very fast. The only thing that may fail to you now is improper synchronization. You must use QMutex or QReadWriteLock to lock the memory on the places you update and access the shared data. For example if you have some getValue() method in your thread's class, that you call using the timer from your gui thread. You should lock it like that:


Mydata MyThread::getValue()
{
mutex.lock();
MyData data = m_calculatedData; // Copy the shared data
mutex.unlock();

return data;
}


Same goes for the part where you update m_calculatedData (in your run() method perhaps). I.e. whatever you are updating or copying data from m_calculatedData using different threads you should lock it. There is a lot of synchronization classes and helpers in Qt like QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition. The mutex will do the job for almost every task but depending on the situation other locker mechanisms might be better. You have to spend some time in reading the Qt documentation. :)