Skip to content
This repository has been archived by the owner on Dec 12, 2023. It is now read-only.

how to update widget in main ui from future work? #41

Open
xkungfu opened this issue Feb 14, 2022 · 3 comments
Open

how to update widget in main ui from future work? #41

xkungfu opened this issue Feb 14, 2022 · 3 comments

Comments

@xkungfu
Copy link

xkungfu commented Feb 14, 2022

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!

@vpicaver
Copy link
Contributor

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.

@xkungfu
Copy link
Author

xkungfu commented Mar 3, 2022

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!

@vpicaver
Copy link
Contributor

@xkungfu you should close this issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants