【发布时间】:2023-03-29 14:20:02
【问题描述】:
在我的应用程序中,线程和 GUI 消息(如 QMessageBox 或新对话框)存在一些问题。为了重现我制作了一个小应用程序来显示问题:
主窗口.cpp
#include <QDebug>
#include "mainwindow.h"
#include "ui_mainwindow.h"
void ThreadAddTree::run() {
//mClass->addTreeEx();
bool b = false;
emit addTree(&b);
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QString path = "";
mThreadAddTree = new ThreadAddTree(this, path);
connect(mThreadAddTree, SIGNAL(addTree(bool*)), this, SLOT(on_add_tree(bool*)), Qt::BlockingQueuedConnection);
//,Qt::DirectConnection
mThreadAddTree->start();
}
void MainWindow::on_add_tree(bool* newData) {
QMessageBox::information(this, tr("Information"),
tr("Button click!"));
*newData = true;
}
void MainWindow::addTreeEx()
{
QMessageBox::information(this, tr("Information"),
tr("Button click!"));
}
主窗口.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtWidgets>
#include <QThread>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class ThreadAddTree : public QThread
{
Q_OBJECT
public:
ThreadAddTree(class MainWindow *nClass, const QString &path) {
mPath = path;
mClass = nClass;
}
signals:
void addTree(bool*);
protected:
void run();
QString mPath;
class MainWindow *mClass;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
friend class ThreadAddTree;
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void addTreeEx();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
protected:
ThreadAddTree *mThreadAddTree;
protected Q_SLOTS:
void on_add_tree(bool* newData);
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
如果我在线程中使用调用:mClass->addTreeEx(); 应用程序将崩溃,以防非主 GUI 线程。明白了。
因此,我将调用与发出消息 emit addTree(&b); 解耦效果很好。显示消息框并且没有崩溃。
但现在对我来说变得复杂了。我需要在我的应用程序中调用mClass->addTreeEx();,因为它会执行一些操作。相同的函数也在附加线程之外使用。
但在一种情况下,在线程内运行的mClass->addTreeEx(); 需要调用Messagebox。
所以我的问题在这里,如何管理,如果从线程调用函数emit addTree(&b);,我可以发出emit addTree(&b);,并且在没有GUI线程的情况下应用程序不会崩溃?
【问题讨论】:
-
我现在添加了一个更详细的问题,还添加了一个最小示例。