10

That's my code for this:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    testApp w;
    w.show();
    TestClass *test = new TestClass;
    QObject::connect(w.ui.pushButton, SIGNAL(clicked()), test, SLOT(something()));
    return a.exec();
}

TestClass.h

class TestClass: public QObject
{
    Q_OBJECT
    public slots:
        void something()
        {
            TestThread *thread = new TestThread;

            thread -> start();
        }

};

TestThread.h

class TestThread: public QThread
{
    Q_OBJECT
protected:
    void run()
    {
        sleep(1000);
        QMessageBox Msgbox;
        Msgbox.setText("Hello!");
        Msgbox.exec();
    }

};

If i'm doing this, i see error

widgets must be created in the gui thread

What am I doing wrong? Please help me. I know that I cant change gui in another thread, but i dont know constuctions in qt for this.

Maxim Makhun
  • 2,197
  • 1
  • 22
  • 26
Alexander Mashin
  • 693
  • 3
  • 14
  • 34
  • 3
    You can use the `signal/slot` mechanism. Create the message box in the main thread and when you want to show a message from a thread, "emit" a signal from it with the message you want to show. Take a look [here](http://qt-project.org/doc/qt-4.8/signalsandslots.html) (it's for the 4.8 version though) – Adri C.S. Jun 02 '14 at 10:19

1 Answers1

9

What you are doing wrong?

You are trying to show widget in non-gui thread.

How to fix?

class TestClass: public QObject
{
    Q_OBJECT
    public slots:
        void something()
        {
            TestThread *thread = new TestThread();

            // Use Qt::BlockingQueuedConnection !!!
            connect( thread, SIGNAL( showMB() ), this, SLOT( showMessageBox() ), Qt::BlockingQueuedConnection ) ;

            thread->start();
        }
        void showMessageBox()
        {
            QMessageBox Msgbox;
            Msgbox.setText("Hello!");
            Msgbox.exec();
        }
};


class TestThread: public QThread
{
    Q_OBJECT
signals:
    void showMB();
protected:
    void run()
    {
        sleep(1);
        emit showMB();
    }

};
phyatt
  • 18,472
  • 5
  • 61
  • 80
Dmitry Sazonov
  • 8,801
  • 1
  • 35
  • 61
  • Can you why `BlockingQueuedConnection` is required? My understanding is that it blocks the emitter and waits while the receiver processes its event queue. This is useful if you want to prevent emitter stack variables from going out of scope while the receiver processes the signal, which is not relevant here. It could also ensure the emitter thread does not end prematurely - is that the motivation here? – Heath Raftery Aug 31 '17 at 01:24
  • 2
    @HeathRaftery `BlockingQueuedConnection` is required by logic. We should not go futher, until user will interact with message box (from GUI thread). – Dmitry Sazonov Aug 31 '17 at 08:11