how to update widget in main ui from future work?
Opened this issue · 3 comments
I have a test , but got some errors.
TaskCenter.h TaskCenter.cpp
#include "asyncfuture.h"
#include "automator.h"
SnapshotWidget snapshotwidget;
QFuture<void> m_subscribeFuture;
QFuture<void> m_doWorkFuture;
int m_count = 0;
TaskCenter::TaskCenter(){}
void TaskCenter::realtime_snapshot_update(int interval) {
if(m_doWorkFuture.isRunning() || m_doWorkFuture.isStarted()) {
m_doWorkFuture.cancel();
}
QFuture<void> runFuture;
for (int i = 0 ; i < 50000;i++) {
runFuture = QtConcurrent::run(&this->snapshotwidget, static_cast<void(SnapshotWidget::*)()>(&SnapshotWidget::dynamic_update_snapshot));
m_doWorkFuture = runFuture;
m_subscribeFuture = AsyncFuture::observe(m_doWorkFuture).subscribe([this](){
qDebug() << "m_count: " << m_count;
m_count++;
},
[this](){
//
}).future();
Automator::wait(interval * 1000);
}
return;
}
SnapshotWidget.h SnapshotWidget.cpp
QWidget* anotherwdt = new QWidget();
void SnapshotWidget::dynamic_update_snapshot()
{
if(!ui->onewdt->layout()){
FlowLayout *anotherwdtlay = new FlowLayout();
anotherwdt->setLayout(anotherwdtlay);
QScrollArea *scrollarea = new QScrollArea();
scrollarea->setWidget(anotherwdt);
QVBoxLayout* onewdtlay = new QVBoxLayout();
ui->onewdt->setLayout(onewdtlay);
ui->onewdt->layout()->addWidget(scrollarea);
}
QLayout* anotherwdtlay = anotherwdt->layout();
qDeleteAll(anotherwdt->findChildren<QCustomPlot *>(QString()));
QCustomPlot* plot = new QCustomPlot();
...
...
anotherwdtlay->addWidget(plot);
return;
}
the error messages are in dynamic_update_snapshot:
QObject::setParent: Cannot set parent, new parent is in a different thread
and the child widgets din't change.
please help me how to modify the codes?
thanks!
I guess you could do this but I would suggest allocating QWidgets on the main thread instead. It seems inefficient and odd that you're creating and using 50000 plots. Also accessing ui isn't thread safe and you'll likely have undefined behaviour.
QObjects have thread affinity. For you code to work you need to push the newly created QWidgets to the main thread QObject::moveToThread(QCoreApplication::instance()->thread()). Then you need to call anotherwdtlay->addWidget(plot) in the main thread.
I guess you could do this but I would suggest allocating QWidgets on the main thread instead. It seems inefficient and odd that you're creating and using 50000 plots. Also accessing ui isn't thread safe and you'll likely have undefined behaviour.
QObjects have thread affinity. For you code to work you need to push the newly created QWidgets to the main thread QObject::moveToThread(QCoreApplication::instance()->thread()). Then you need to call anotherwdtlay->addWidget(plot) in the main thread.
I have payed two week to understand your answer. you are very right, I am now try to do as you said!
thank you very much!