qtloopsqstatemachine

How can I terminate QStateMachine when QDialog is closed?


I have a QDialog and QStateMachine. This loop terminates when the all aplication is closed but i want to terminate loop when Qdialog is closed. How can i do that?

  QStateMachine sm;
  QState s1(&sm), s2(&sm);
  sm.setInitialState(&s1);
  QEventTransition transition(dialog, QEvent::Close);
  s2.addTransition(&transition);
  QEventLoop loop;
  QObject::connect(&s2, &QState::entered, &loop, &QEventLoop::quit);
  sm.start();
  dialog->show();
  loop.exec();

Solution

  • Use QFinalState class for this. At docs example shown usage QPushButton with exit. You just need to connect it with finished() signal for example.

    UPD

    Some usage example:

    MainWinow.h

    class MainWindow : public QMainWindow, private Ui::MainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
    
    private:
        QDialog *dialog;
    private slots:
        void on_pushButton_clicked();
    };
    

    MainWindow.cpp

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent)
    {
        setupUi(this);
    
        dialog = new QDialog;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        // Open dialog after push button was clicked
        if (!dialog)
            dialog = new QDialog;
    
        QEventLoop loop;
        QStateMachine machine;
        QState *s1 = new QState();
    
        QFinalState *s2 = new QFinalState();
        s1->addTransition(dialog, SIGNAL(finished(int)), s2);
    
        connect(&machine, QStateMachine::finished, [&loop]{
            qDebug() << "Finished";
            loop.quit();
        });
    
        machine.addState(s1);
        machine.addState(s2);
        machine.setInitialState(s1);
        machine.start();
    
    
        dialog->show();
        loop.exec();
    
        qDebug() << "Really finished";
    }
    

    So we create QEventLoop, QStateMachine and add states(init state and final state). Then connect QDialog::finished() signal with transition to final state and connect QStateMachine::finished() signal with slot where event loop will be stoped. Then show QDialog and start QStateMachine.

    At console will print:

    Finished

    Realy finished