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.
精彩评论