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?

Qt Code:
  1. mainwindow.cpp
  2. ***************************************
  3. #include "mainwindow.h"
  4. #include "ui_mainwindow.h"
  5. #include <stdexcept>
  6.  
  7. MainWindow::MainWindow(QWidget *parent) :
  8. QMainWindow(parent),
  9. ui(new Ui::MainWindow)
  10. {
  11. ui->setupUi(this);
  12. }
  13.  
  14. MainWindow::~MainWindow()
  15. {
  16. delete ui;
  17. }
  18.  
  19. void MainWindow::on_btnRun_clicked()
  20. {
  21. TestThread testThread(this);
  22. testThread.TestCmds(_testCmds);
  23. testThread.SetStartIndex(0);
  24. connect(&testThread, SIGNAL(stepChanged(int)), this, SLOT(testThreadStepChanged(int)));
  25. connect(&testThread, SIGNAL(finished()), this, SLOT(testThreadFinished()));
  26. testThread.start();
  27. testThread.wait();
  28. }
  29.  
  30. void MainWindow::testThreadStepChanged(int step)
  31. {
  32. // tblCmds is a QTableWidget with rows of strings
  33. ui->tblCmds->selectRow(step);
  34. ui->tblCmds->repaint();
  35. }
  36.  
  37. void MainWindow::testThreadFinished()
  38. {
  39. qDebug("Received Thread Finished Signal");
  40. }
  41.  
  42. mainwindow.h
  43. ***************************************
  44. #ifndef MAINWINDOW_H
  45. #define MAINWINDOW_H
  46.  
  47. #include <QMainWindow>
  48. #include "qthread.h"
  49. #include "qtablewidget.h"
  50. #include "testthread.h"
  51.  
  52. namespace Ui {
  53. class MainWindow;
  54. }
  55.  
  56. class MainWindow : public QMainWindow
  57. {
  58. Q_OBJECT
  59.  
  60. public:
  61. explicit MainWindow(QWidget *parent = 0);
  62. ~MainWindow();
  63.  
  64. private slots:
  65. void on_btnRun_clicked();
  66. void testThreadStepChanged(int step);
  67. void testThreadFinished();
  68.  
  69. private:
  70. Ui::MainWindow *ui;
  71. QStringList _testCmds;
  72. };
  73.  
  74. #endif // MAINWINDOW_H
  75.  
  76.  
  77. testthread.cpp
  78. ***************************************
  79. #include "testthread.h"
  80.  
  81. TestThread::TestThread(QObject *parent) :
  82. QThread(parent)
  83. {
  84. }
  85.  
  86. void TestThread::run()
  87. {
  88. for(int si=_startIndex; si < _testCmds.count(); si++)
  89. {
  90. if(_stopFlag) return;
  91. emit stepChanged(si);
  92. }
  93. }
  94.  
  95. testthread.h
  96. ***************************************
  97. #ifndef TESTTHREAD_H
  98. #define TESTTHREAD_H
  99.  
  100. #include <QThread>
  101.  
  102. class TestThread : public QThread
  103. {
  104. Q_OBJECT
  105. public:
  106. explicit TestThread(QObject *parent = 0);
  107.  
  108. void SetStartIndex(int startIndex);
  109. void TestCmds(QStringList testCmds);
  110. void Stop();
  111.  
  112. signals:
  113. void stepChanged(int step);
  114.  
  115. public slots:
  116.  
  117. private:
  118. void run();
  119.  
  120. QStringList _testCmds;
  121. int _startIndex;
  122. bool _stopFlag;
  123. };
  124.  
  125. #endif // TESTTHREAD_H
To copy to clipboard, switch view to plain text mode