从在 QThread 中运行的 C 代码显示 QMessageBox

Posted

技术标签:

【中文标题】从在 QThread 中运行的 C 代码显示 QMessageBox【英文标题】:Display a QMessageBox from C code running in a QThread 【发布时间】:2011-01-03 23:16:20 【问题描述】:

我有创建 QThread 的主 (GUI) 线程。

在 QThread 中,我正在调用一个需要显示 QMessageBox 的 C 函数。到目前为止,我只是简单地使用了:

void notify(char *str)

  QMessageBox::information(0, "", QString(str));

在 C++ 代码中并从 C 代码中调用它。这在没有线程的情况下工作得很好,但现在有了线程我得到了错误,因为不能从另一个线程调用 GUI 函数。

通常,这可以通过使用this question 的答案建议的信号来规避;但是,我怀疑我可以从 C 代码中做到这一点。

那么,如何让 C 代码与 GUI 线程通信并告诉它显示 QMessageBox?

谢谢。

附言

如果可能,我想在不接触 C 代码的情况下执行此操作(到目前为止,C 代码的标头中只有一个 extern void notify(char *) 声明,如果可能的话,我希望它保持不变。

【问题讨论】:

【参考方案1】:

假设您的 GUI 有一个 QWidgetQMainWindow 派生类,您可以向其中添加以下内容:

class MyWidget : public QWidget

    Q_OBJECT;
public:    
    MyWidget()
    
        connect(this, SIGNAL(notify_sig(QString)),
                this, SLOT(notify_slot(QString)),
                Qt::QueuedConnection);
    

    void notify(QString str)
    
        emit notify_sig(str);
    

    signals:
        void notify_sig(QString str);

    slots:
        void notify_slot(QString str)
        
            QMessageBox::information(0, "", str);
        
;

这里有一个公共函数notify(),它是小部件类的成员。调用MyWidget::notify() 会导致信号通过排队连接发送给自身(这将导致在GUI 线程中调用槽)。现在C notify() 调用只需要调用小部件/窗口的notify() 函数。这可能很棘手,因为您实际上并没有指向 C notify() 函数中可用的小部件的指针。

通常,C 接口允许用户传入 void* 值,然后通过 notify 调用返回该值。这将允许您在调用 C 函数时传入指向 MyWidget 的指针,然后在 notify() 实现中将其转换回 MyWidget

MyWidget* wid = ...;
C_function(arg1, ..., wid);

//...

void notify(char* str, void* userdata)

    MyWidget* wid = static_cast<MyWidget*>(userdata);
    wid->notify(QString(str));

如果您无法更改 C 接口,则可能需要使用某种全局方式来获取小部件/窗口的指针。

请注意,我没有测试任何代码,可能有更简单的方法。

【讨论】:

非常感谢您的回答!我想你误读了我的答案,或者我解释错了,但notify(非类)函数实际上是在 C++ 代码中(C 代码只调用它)这使它更容易,因为我 可以在您的示例中获取指向MyWidget 的指针。所以,我可以调用我的主窗口类的方法,然后按照你的建议使用信号和插槽。但无论如何,我使用了你的方法,效果很好(除了编译器不喜欢public signals,它只是signals),非常感谢!

以上是关于从在 QThread 中运行的 C 代码显示 QMessageBox的主要内容,如果未能解决你的问题,请参考以下文章

带有 QThread 和线程模块的 Python 多线程

Windows 自动化 - 从在 Windows 中运行的应用程序中获取文本

如何从在android中扩展应用程序的类中显示对话框?

如何从在浏览器上运行的小程序访问计算机驱动器

QT-如何在 QThread 中使用 QWidget?

检测是不是从在 3.5 上运行的 C# 代码安装了 MSBuild/.net 4?