首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从另一个线程中引发的Boost信号更新Qt GUI?

如何从另一个线程中引发的Boost信号更新Qt GUI?
EN

Stack Overflow用户
提问于 2015-05-11 08:33:16
回答 2查看 529关注 0票数 1

我有一个普通的C++对象,它在单独的线程中运行数据采集例程,并使用名为acquisitionStageChangedEvent的Boost信号通知进程,该信号的签名如下:boost::signal2::signal<void(const std::string &)>。如何在没有跨线程异常的情况下,在新线程中启动采集并使用此信息更新UI?

EN

回答 2

Stack Overflow用户

发布于 2015-05-11 13:16:50

在信号处理程序中将std::atomic<bool>设置为true,并从QTimer检查该标志。

票数 0
EN

Stack Overflow用户

发布于 2015-05-11 08:33:16

下面是一个关于如何在进度更新期间和任务结束时启动后台线程和更新UI的工作示例:

代码语言:javascript
运行
复制
namespace Ui
{
    class DtacqAcquisitionWidget;
}

class DtacqAcquisitionWidget : public QWidget
{
    Q_OBJECT

public:
    explicit AcquisitionWidget(QWidget *parent = 0);

   ~DtacqAcquisitionWidget();

private slots:

    void on_pushButtonStart_clicked();

    void onDtacqChangeState(const QString &stage);

    /*... Other slots here */
private:
    Ui::AcquisitionWidget *ui;

    QFutureWatcher<void>  *m_future_watcher; // This is to be able to run UI code at the end of the background thread

    anlytcs::Dt100Acq m_dtacq; // The plain C++ object that raises the boost signal 'acquisitionStageChangedEvent'
};

在.cpp文件中:

代码语言:javascript
运行
复制
DtacqAcquisitionWidget::DtacqAcquisitionWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DtacqAcquisitionWidget)
{
    ui->setupUi(this);

    // Run the 'onAcquisitionFinished' slot at the end of the thread
    m_future_watcher = new QFutureWatcher<void>(this);
    connect(m_future_watcher, SIGNAL(finished()), this, SLOT(onAcquisitionFinished()));

    // Acquisition stages update
    m_dtacq.acquisitionStageChangedEvent.connect([this](const std::string &stage)
    {
        this->onDtacqChangeState(QString::fromStdString(stage));
    });
}

void DtacqAcquisitionWidget::on_pushButtonStart_clicked()  // Starting the acquisition
{
    ui->pushButtonStop->setEnabled(true);
    ui->pushButtonStart->setEnabled(false);
    ui->progressBar->setValue(0);

    // Start the acquisition in a new thread
    QFuture<void> f = QtConcurrent::run(this, &DtacqAcquisitionWidget::acquireChannelData);    
    m_future_watcher->setFuture(f);
}

void DtacqAcquisitionWidget::onDtacqChangeState(const QString &stage)
{
    if (thread() != QThread::currentThread())
    {      
        QMetaObject::invokeMethod(this, "onDtacqChangeState", 
            Qt::BlockingQueuedConnection, Q_ARG(QString, stage));
    }
    else
    {
        ui->labelDtacqState->setText(stage);
        ui->progressBar->setValue(ui->progressBar->value() + 40);
    }    
}

void DtacqAcquisitionWidget::onAcquisitionFinished()
{
    // Set what to update here in the GUI here when the acquisition thread finishes     
    ui->labelDtacqState->setText("DONE!");
}

void DtacqAcquisitionWidget::acquireChannelData()
{
    // This is running on a background thread (Non UI thread)
    double time_sec = ui->spinBoxAcqTimeSec->value();
    uint32_t channel_mask = getChannelMask();

    std::string data_path = "C:/Users/pardinad/Desktop/DtacqData/";
    m_dtacq.startAcquisition(time_sec, channel_mask, 250);
    ui->labelDtacqState->setText("Acquisition Started!");

    if(m_dtacq.completeAcquisition())   
    {
        for (auto & dch : m_dtacq.dataChannels())
        {
            std::stringstream ss;
            ss << data_path << std::setw(2) << std::setfill('0') << dch.channelNumber() << ".DAT";
            std::string ch_file = ss.str();
            dch.saveToFile(ch_file);
        }
    }
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30158093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档