从 QThread 影响 QDialog

Posted

技术标签:

【中文标题】从 QThread 影响 QDialog【英文标题】:Affecting a QDialog From A QThread 【发布时间】:2013-02-12 22:57:51 【问题描述】:

我想从一个单独的线程影响一个 QDialog,我必须做两件事:

dialog->show();
dialog->raise();
dialog->activateWindow();

据我了解,这些是事件,因此必须在主线程事件循环中完成。我想我在QThread::run() 中使用QApplication::postEvent 实现了这一点。谁能确认一下?

其次,我想显示在该单独线程中处理的图像。我想我需要子类化我的对话框类并编写一个线程安全的setImage() 函数,然后由paintEvent() 调用......但是,这似乎是不可能的。我不能用QMutex::unlock() 阻止paintEvent?谁能提供一些建议?


QApplication::postEvent(dialog, new QShowEvent()); 不起作用。

这是从单独的线程调用槽(作为函数)的解决方案:

QMetaObject::invokeMethod(dialog, "show", Qt::QueuedConnection);
QMetaObject::invokeMethod(dialog, "raise", Qt::QueuedConnection);

...仍在开发activateWindow()QThread 安全功能。

所以对于QImage,它是一个QPaintDevice。据说它是线程安全的。我的方法是在线程中设置一个类成员QImage。然后再画。

请注意,下面的方法同样好,即使不是更好。

【问题讨论】:

我会避免将对话框指针传递给线程,而是连接来自另一个线程中 QObject 的信号。对于 activateWindow,您需要编写自己的插槽,只调用 activateWindow()。 嘿弗兰克,有什么特别的原因吗?另外,为了确认,您是说在QThread::run() 中使用emit SIGNAL 而不是使用invokeMethod。在 QThread 的构建过程中,SIGNAL 已经正确连接到哪里? 【参考方案1】:

我认为这是一种更清晰的方式来做你想做的事:

class Dialog : public QDialog

    ...
public slots:
    void showImage(QImage img);
    ...


void Dialog::showImage(QImage img);

    setImage(img);
    show();
    raise();
    activateWindow();


class Thread : public QThread

    ...
signals:
    void imageReady(QImage);


void Thread::run()

    QImage img;
    /// image processing stuff

    emit imageReady(img);
    ...



Thread *thread = new Thread;
Dialog *dialog = new Dialog;
connect(thread, SIGNAL(imageReady(QImage)), dialog, SLOT(showImage(QImage)));

thread->start();

【讨论】:

以上是关于从 QThread 影响 QDialog的主要内容,如果未能解决你的问题,请参考以下文章

从多个 QThread 更新 QProgressBar

从 QThread 启动 QProcess [重复]

从继承的 QThread 迁移到 Worker 模型

停止线程的方法是啥(当我直接从 QThread 继承时)?

QT用线程启动定时器

将对象的亲和性从 QThread 更改为主 GUI 线程