I have a GUI containing a QTableWidget whose rows contain strings. The strings are processed in a separate thread in order to keep the GUI free for providing status by selecting each row as the string in that row is being processed and also to abort the overall processing if desired. My problem is that the GUI's QTableWidget does not show/update row selection for each row until after all the rows have already been processed even though the GUI slot that performs the selectRow is called correctly at the right time. It looks as if the QTableWidget selectRow is queued for later execution after the thread is finished.
I did see one comment which suggested that the problem might be the thread wait executed after the thread start, but without the wait the program crashes with the error that the thread was terminated before processing was complete. What do I need to do to get the GUI to update the row selection on the QTableWidget when I execute the emit from the separate thread?
mainwindow.cpp
***************************************
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <stdexcept>
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnRun_clicked()
{
TestThread testThread(this);
testThread.TestCmds(_testCmds);
testThread.SetStartIndex(0);
connect(&testThread, SIGNAL(stepChanged(int)), this, SLOT(testThreadStepChanged(int)));
connect(&testThread, SIGNAL(finished()), this, SLOT(testThreadFinished()));
testThread.start();
testThread.wait();
}
void MainWindow::testThreadStepChanged(int step)
{
// tblCmds is a QTableWidget with rows of strings
ui->tblCmds->selectRow(step);
ui->tblCmds->repaint();
}
void MainWindow::testThreadFinished()
{
qDebug("Received Thread Finished Signal");
}
mainwindow.h
***************************************
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qthread.h"
#include "qtablewidget.h"
#include "testthread.h"
namespace Ui {
class MainWindow;
}
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
private slots:
void on_btnRun_clicked();
void testThreadStepChanged(int step);
void testThreadFinished();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
testthread.cpp
***************************************
#include "testthread.h"
TestThread
::TestThread(QObject *parent
) :{
}
void TestThread::run()
{
for(int si=_startIndex; si < _testCmds.count(); si++)
{
if(_stopFlag) return;
emit stepChanged(si);
}
}
testthread.h
***************************************
#ifndef TESTTHREAD_H
#define TESTTHREAD_H
#include <QThread>
{
Q_OBJECT
public:
explicit TestThread
(QObject *parent
= 0);
void SetStartIndex(int startIndex);
void Stop();
signals:
void stepChanged(int step);
public slots:
private:
void run();
int _startIndex;
bool _stopFlag;
};
#endif // TESTTHREAD_H
mainwindow.cpp
***************************************
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <stdexcept>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnRun_clicked()
{
TestThread testThread(this);
testThread.TestCmds(_testCmds);
testThread.SetStartIndex(0);
connect(&testThread, SIGNAL(stepChanged(int)), this, SLOT(testThreadStepChanged(int)));
connect(&testThread, SIGNAL(finished()), this, SLOT(testThreadFinished()));
testThread.start();
testThread.wait();
}
void MainWindow::testThreadStepChanged(int step)
{
// tblCmds is a QTableWidget with rows of strings
ui->tblCmds->selectRow(step);
ui->tblCmds->repaint();
}
void MainWindow::testThreadFinished()
{
qDebug("Received Thread Finished Signal");
}
mainwindow.h
***************************************
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qthread.h"
#include "qtablewidget.h"
#include "testthread.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_btnRun_clicked();
void testThreadStepChanged(int step);
void testThreadFinished();
private:
Ui::MainWindow *ui;
QStringList _testCmds;
};
#endif // MAINWINDOW_H
testthread.cpp
***************************************
#include "testthread.h"
TestThread::TestThread(QObject *parent) :
QThread(parent)
{
}
void TestThread::run()
{
for(int si=_startIndex; si < _testCmds.count(); si++)
{
if(_stopFlag) return;
emit stepChanged(si);
}
}
testthread.h
***************************************
#ifndef TESTTHREAD_H
#define TESTTHREAD_H
#include <QThread>
class TestThread : public QThread
{
Q_OBJECT
public:
explicit TestThread(QObject *parent = 0);
void SetStartIndex(int startIndex);
void TestCmds(QStringList testCmds);
void Stop();
signals:
void stepChanged(int step);
public slots:
private:
void run();
QStringList _testCmds;
int _startIndex;
bool _stopFlag;
};
#endif // TESTTHREAD_H
To copy to clipboard, switch view to plain text mode
Bookmarks