Displaying data in QTable Widget using Infinite loop
-
I m a newbie to Qt Development you can even say that i m new to C++ also consider my knowledge as nil before answering
So basically my problem is.From my mainwindow i call a function which is infinitely called for every packet received at a machine and then i read the packet parameters and show it in QTableWidget but as soon as soon as the loop is started the mainwindow freezes and i have to manually kill the process.
My Only question is that is there any way to loop infinitely and display data concurrently in Qtable Widget
Sorry if i am asking something inappropriate here.
-
I think you have to start a new "thread":http://doc.trolltech.com/latest/qthread.html for your infinite loop.
-
@
class MyThread : public QThread
{
public:
void run();
signals:
void updateParameters(QString);
};void MyThread::run()
{
// setup connection to recive packets
while (true){
// read in new info
// if new info recived -> update table
updateParameters(QString);
}
}void MyThread::updateParameters(QString){}
..
// in the main()
MyThread *thread = new MyThread;
QObject::connect(thread, SIGNAL(updateParamters(QString)), yourTableWidget, SLOT(updateValuesInTable(QString)));
thread->start();@
where updateValuesInTable(QString) updates the table with the your new parameters (or you can use a QStringList if you have to many, it's your call)not tested
-
Hi 17mdinesh,
if you want to go with threads, i suggest reading "this":http://developer.qt.nokia.com/wiki/ThreadsEventsQObjects wiki article.
The code HuXiKa has a problem, as the signal/slot connection will be synchronous, which means the UI would be updated inside the thread, which is not allowed. Afaik, this is also described in the wiki article.
You could use a fifth argument: Qt::QueuedConnection, which perhaps solves the problem, but is not a clean design in this issue.
-
It is better to have a worker QObject-derived object inside the worker thread to to the actual work and emit the signals. This should be either created in the run() function of the worker thread or explicitly moveToThread()'d after the thread has started.
Then as Gerolf suggests you should use a Qt::QueuedConnection between signals/slots. In fact with the above setup, the default is to use a queued connection.
-
ZapB,
I hope you don't meant, this:
@
QObject::connect(thread, SIGNAL(updateParamters(QString)), yourTableWidget, SLOT(updateValuesInTable(QString)));
@
with above setup, as it will not create a queued connection (the thread object itself is not part of the thread). Objects, which are created inside the run loop or movedToThread then it is correct.What would be the cleanest sollution from my point:
have a QThread derived class (CMyThread) with signals.
inside the run loop of the thread create QObject derived classes (CMyWorker) who do the work and also have signals
connect the signals of CMyWorker with the signals of CMyThread
use the signals of CMyThread ouside of the thread.
This ensures that
- the outer classes needn't know anything of the inner parts (separation of concerns)
- If you like to move the workinbg logic to another process or whatever, you can do without changing the client logic
-
No, sorry I should have been more explicit. I was referring to my above setup. Namely:
@
class WorkerObject : public QObject
{
Q_OBJECT
public:
WorkerObject( QObject* parent ) : QObject(parent) {}public slots:
void doSomething()
{
...
emit updateParamters(...);
...
}signals:
void updateParamters(QString);
}class WorkerThread : public QThread
{
Q_OBJECT
public:
WorkerThread(QObject* parent) : QThread(parent), m_worker(0) {}WorkerObject* worker() {return m_worker;} void waitForStart( Priority priority ) { qDebug() << "Starting WorkerThread..."; m_mutex.lock(); start( priority ); // Put the calling thread to sleep untill the run() function wakes us up m_waitCondition.wait( &m_mutex ); qDebug() << "Calling thread is now awake"; }
protected:
void run()
{
// Lock the mutex and create worker objects
m_mutex.lock();
m_worker = new WorkerObject;// We are now ready to rock. Wake up the calling thread m_waitCondition.wakeOne(); // Enter the event loop exec(); }
private:
QMutex m_mutex;
QWaitCondition m_waitCondition;
WorkerObject* m_worker;
};...
// Create and start worker thread
WorkerThread* thread = new WorkerThread( this );
thread->waitForStart();// When we reach this point we know that the
// worker object will exist so we can use it in a connect
connect( thread->workerObject(), SIGNAL( updateParamters(QString) ),
this, SLOT( updateValuesInTable(QString) ) );// Make the worker object do something.
// This will use a queued call since workerObject has affinity with
// a different thread.
QMetaObject::invokeMethod( thread->workerObject(), "doSomething" );
@Edit: With this approach the WorkerObject can be reused in any thread you like - even the main GUI thread.
-
If you get a signal for each packet (e.g. by the QNetwork* classes), then you could just forget about the loop. Just connect some handler to the signal, and have it update the QTableWidget whenever it gets the signal. The "infinite looping" is then handled by the event loop inside QApplication.
That approach might be a bit simpler than going multi-threaded and works well if you are just doing straight forward (and fast) operations. If processing the input data into a form that is required for the QTableWidgetItems, then the multi-threaded approach is probably better.