开发者

Display a QMessageBox from C code running in a QThread

I have the main (GUI) thread which creates a QThread.

In the QThread, I am calling a C function that needs to display a QMessageBox. So far, I simply used:

void notify(char *str)
{
  QMessageBox::information(0, "", QString(str));
}

in the C++ code and called it from the C code. This worked fine without threads, but now with threads I am getting errors, because one cannot call the GUI functions from another thread.

Usually, this could be circumvented by using signals like the answer to this question suggests; however, I doubt I can do this from the C code.

So, how can I make the C code communicate with the GUI thread and tell it to display a QMessageBox?

Thanks.

P.S.

If possible, I'd like to do this without touching the C code (as of now, there is simply an extern void notify(char *) declaration in the C code's headers, and if possible I'd开发者_C百科 like it to stay at that.


Assuming you have a QWidget or QMainWindow derived class for your GUI, you could add the following to it:

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);
        }
};

Here you have a public function notify() that is a member of the widget class. Calling MyWidget::notify() results in a signal being sent to itself through a queued connection (which will result in the slot being called in the GUI thread). Now the C notify() call just needs to call the widget/window's notify() function. This can be tricky since you don't really have a pointer to the widget available in the C notify() function.

Normally, the C interface would allow the user to pass a void* value in and would then return that value with the notify call. This would allow you to pass in the pointer to MyWidget when the C function is called and then cast it back to MyWidget in the notify() implementation.

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

//...

void notify(char* str, void* userdata)
{
    MyWidget* wid = static_cast<MyWidget*>(userdata);
    wid->notify(QString(str));
}

If you can't change the C interface, you may need to use some kind of global way of getting the widget/window's pointer.

Note that I have not tested any of this code and there may be an easier way to do this.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜