-1

I have this very simple Qt code:

void thread_func()
{
    int a1 = 1;
    const char* a2[] = { "dummy_param" };
    QApplication app(a1, (char**)a2);

    QMessageBox msg(QMessageBox::NoIcon, "MyTitle", "Foo bar Foo bar", QMessageBox::Ok);
    msg.exec();
}

If I call the above function from my main in a std::thread, it brings up the dialog:

int main()
{
    std::thread t(thread_func);
    t.join();
}

...but when I close it, I get the warning message:

QObject::~QObject: Timers cannot be stopped from another thread

I've checked that the thread affinity of both QApplication instance and msg is the same. Calling the thread_func function directly from my main() (without creating a std::thread) removes that message.

I am using Qt 5.15.1 on Windows 10.

What am I missing here? Thanks

linuxfever
  • 3,763
  • 2
  • 19
  • 43
  • 4
    You can't create GUI elements (e.g. `QMessageBox`) on any thread other than that on which `main` is running. It's just not supported. – G.M. Sep 27 '20 at 19:43
  • @G.M. I thought it can work, at least on windows as posted here : https://stackoverflow.com/questions/22289423/how-to-avoid-qt-app-exec-blocking-main-thread – linuxfever Sep 27 '20 at 19:51

2 Answers2

1

It's not allowed to operate Qt GUI directly outside the main thread(GUI thead). You can emit signals.

Allen ZHU
  • 690
  • 5
  • 14
0

The warning message says it all. Use a signal/slot mechanism to accomplish the same thing.

#include <QApplication>
#include <QMessageBox>
#include <QObject>
#include <QThread>
#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(){}
public slots:
    void displayMessageBox()
    {
        QMessageBox msg(QMessageBox::NoIcon, "MyTitle", "Foo bar Foo bar", QMessageBox::Ok);
        msg.exec();
        this->close();
    }
};

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker() {}
    void start() { emit askForMessageBox(); }
signals:
    void askForMessageBox();
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget *widget;
    Worker *worker;
    QThread *thread(nullptr);

    widget = new Widget();
    worker = new Worker();
    thread = new QThread(nullptr);

    QObject::connect(worker, &Worker::askForMessageBox, widget, &Widget::displayMessageBox);
    QObject::connect(thread, &QThread::started, worker, &Worker::start);

    widget->show();
    worker->moveToThread(thread);
    thread->start();

    return a.exec();
}
mzimmers
  • 857
  • 7
  • 17