Из контекста потока слота в моем приложении QT GUI (после нажатия кнопки) я пытаюсь запустить рабочий поток, чтобы обновить другую другую часть GUI с результатами интенсивных вычислений ЦП - эти результаты будут обновленытаблица или виджет карты, похожий на google - так должно происходить в главном потоке приложения QT, где можно безопасно обновлять эти виджеты.
У меня проблема в том, что слот updateGUIWidget
никогда не вызывается, если я не изменяю тип соединения на Qt::DirectConnection
- в этом случае он вызывается в рабочем потоке (где небезопасно обновлять графический интерфейс).Я проверил результаты каждого из вызовов подключения, и они в порядке, кажется, что где-то есть проблема с циклом событий.Я не уверен, нужно ли мне выделять поток и рабочие объекты в качестве членов основного окна, или это нормально делать из переменных стека в слоте.
void
mainwindow::on_importSimulatedFlight_clicked()
{
// experimental worker thread model adapted from YouTube tutorial
// by Giuseppe di Angelo https://www.youtube.com/watch?v=BgqT6SIeRn4
// auto thread = new QThread;
// note worker created in gui thread here - we will move its thread
// affinity to 'thread' below before starting it.
auto thread = new QThread;
auto worker = new Worker;
connect(thread, &QThread::started, worker, &Worker::doWork);
// connect(worker, &Worker::progressUpdate, this, &mainwindow::updateGUIWidget, Qt::DirectConnection);
connect(worker, &Worker::progressUpdate, this, &mainwindow::updateGUIWidget, Qt::QueuedConnection);
connect(worker, &Worker::workDone, thread, &QThread::quit);
connect(thread, &QThread::finished, worker, &Worker::deleteLater);
// move worker to separate thread
worker->moveToThread(thread);
thread->start();
}
В главном окне объявлены слотыв mainwindow.h следующим образом:
class mainwindow : public QMainWindow
{
Q_OBJECT
public:
explicit mainwindow(QWidget *parent = Q_NULLPTR);
~mainwindow();
...
public slots:
void on_importSimulatedFlight_clicked();
void updateGUIWidget(const param& rParam);
...
}
и реализован в mainwindow.cpp следующим образом:
void
mainwindow::updateGUIWidget(const param& rParam)
{
... update widget components with rParam partial result here
}
, и мой рабочий выглядит следующим образом:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork() {
const QString result;
for (int i=0; i<5; i++) {
const MMRTimedRecord foo;
// QThread::sleep(1);
emit progressUpdate(foo);
}
emit workDone(result);
}
signals:
void progressUpdate(const MMRTimedRecord&);
void workDone(const QString &result);
};