Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Simple state machine class not updating mainwindow
Qt 6.12 LTS is out! See what's new in the release blog

Simple state machine class not updating mainwindow

Scheduled Pinned Locked Moved General and Desktop
7 Posts 2 Posters 3.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #1

    I have two main windows, the first launches the state machine class which creates a second main window.

    The second window then is modified using , for example
    @
    _pushbutton->setVisible(true); // or false
    @
    Each state (corresponds to a method) is generally connected to the next state using slots; the signal comes from the pushbutton of the prior state.

    But my problem is that I do not see updates sometimes, even when I do :

    @ _pushbutton->setVisible(bool);
    _pushbutton->update();

    _lineedit->setVisible(bool);   
    _lineedit->update();
    

    @
    I tried even to create a new MainWindow for every state to no avail. I tried using show()

    @
    _mainwindow->show();
    @

    after every update also. My state machine seems to work for the first few simple states with just changes to a QLabel. Once the lineEdit widget is used, the updates seem to falter. ( I was successful in obtaining the text input however.)

    Also in general am I connecting my states correctly ? (Can this design cause the stack to explode ? There are no cycles here BTW, I swear.) I have two ways to connect, either through a direct call or by a connect:

    @void State::state3()
    {

    ...
    state4(); // direct call
    }

    void State::state4()
    {
    ...
    connect(_pushbutton, SIGNAL(clicked()), this, SLOT(state5())); // by connect
    }
    @

    I had trouble seeing an update esp after a sleep() / Sleep() / usleep() call (I tried all 3) as well.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      I don't understand your need to call update (it should be done for you when you change something like the visibility of a widget) nor the use case of your state machine.

      Could you elaborate on what your state machine should do and with what you implemented it ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • ? Offline
        ? Offline
        A Former User
        wrote on last edited by
        #3

        Hi, I am using 2 QMainWindows; one is the MainWindow class with a small state machine which launches and changes the widget states of a UserWindow (inherits from QMainWindow also) . In this snippet, the part that is killing me is that the QTimer I have created doesn't go away.
        State 3 keeps coming up every 6 seconds and the on-screen debug info shows the timer is still active after I deleted it. I tried disconnecting the slot, but no go.

        I call update() and show() all over because I was desparately trying to get the timing right. Things work as long as I don't use timers !

        Thanks !

        -pheno
        @
        #include <QMainWindow>
        #include <mainwindow.h>
        #include <userwindow.h>
        #include "ui_mainwindow.h"

        namespace Ui {
        class MainWindow;
        }

        class UserWindow : public QmainWindow
        {

        ... // for eg.
        void UserWindow::showPushButton()
        {
        _pushbutton->setVisible(true);
        _pushbutton->update();
        this->show();
        }
        }

        class MainWindow : public QMainWindow
        {
        Q_OBJECT

        public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
        void createTimer();
        void startTimer(int t);
        void killTimer();

        private slots:
        void on_pushButton_a1_clicked();
        void state1();
        void state2();
        void state3();
        void state_final();
        void dotime();

        private:
        Ui::MainWindow *ui;
        UserWindow *_uw; // inherits from QMainWindow, separate file
        QPushButton *_qpb;
        QTimer *_timer;

        };

        MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
        {
        ui->setupUi(this);
        _uw = new UserWindow();
        _timer = NULL;
        }
        void MainWindow::startTimer(int t)
        {
        _timer->start(t);
        }
        void MainWindow::killTimer()
        {
        if (_timer)
        {
        _timer->stop();
        delete _timer;
        }
        if (_func)
        {
        _func = NULL;
        }
        }

        void MainWindow::createTimer()
        {
        killTimer();
        _timer = new QTimer(this);
        _timer->setSingleShot(true);
        }

        void MainWindow::on_pushButton_a1_clicked()
        {
        _qpb = _uw->getPushButton();
        _uw->showFullScreen();
        createTimer();
        connect(_timer, SIGNAL(timeout()), this, SLOT(state1()));
        startTimer(0);}
        }

        void MainWindow::state1()
        {
        killTimer();
        _uw->setScreenTitle("Directions");
        _uw->setScreenText("blah blah");
        _uw->hideTextInput();
        _uw->showPushButton();

        connect(_qpb, SIGNAL(clicked()), this, SLOT(state2()));
        

        }

        void MainWindow::state2()
        {
        _uw->setScreenTitle("stuff");
        _uw->setScreenText("READ THIS ...");
        _uw->hideTextInput();
        _uw->hidePushButton();

        createTimer();
        connect(_qpb, SIGNAL(clicked()), this, SLOT(state3()));
        startTimer(2000);
        

        }
        void MainWindow::state3()
        {
        killTimer();
        _uw->setScreenTitle("yadda");
        _uw->setScreenText("ipsum lorem ");
        _uw->showTextInput();
        _uw->showPushButton();

        if (_timer && _timer->isActive() )
        {
            _uw->setScreenText("Timer is still active !!");
        }
        else
        {
            _uw->setScreenText("Timer is NOT still active ins State 3 !!");
        }
        connect(_qpb, SIGNAL(clicked()), this, SLOT(state4()));
        

        }

        void MainWindow::state4()
        {
        ....
        }
        @

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          You are mixing several concepts and have overloaded some non-virtual functions. If you really need a state machine, have a look a the QStateMachine documentation.

          startTimer is a function of QObject as well as killTimer, so your code might not be doing what you think he should do.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • ? Offline
            ? Offline
            A Former User
            wrote on last edited by
            #5

            I don't have to use a state machine. I just want to instantiate a QMainWindow and have parts of it change in a given series of screens as a user interacts with it. Seemed like a natural fit. I tried to use QStateMachine but I could not get assignproperty to work.

            I just need to conduct a quiz that times the student:
            (pseudocode)

            1. start a QMainWindow; show instructions for 7 seconds
            2. update QMainWindow with a question
            3. wait for user text input (note how long it took, it is part of score)
            4. check answer; say if right/wrong; give a clue; still wrong, show answer for 7 seconds
            5. loop over steps #2,3,4 for N times (N<10).
            6. show conclusion screen

            I have a couple of dozen similar quizzes I need to implement each will launch from the main window; the content is quite trivial.

            I saw writing this in one function but couldn't wrap my head around switching control between user and the event loop.

            showscreen1
            wait for 7 seconds
            showscreen2
            wait for text input; record time
            showscreen2 (same screen; 2nd try)
            wait for text input; record time
            showscreen3
            wait for button click
            showscreen4
            wait for 7 seconds
            show screen5
            ...

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              That sounds more like a QWizard style of application

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • ? Offline
                ? Offline
                A Former User
                wrote on last edited by
                #7

                You were right, I was looking at the wrong end of the mule :)

                I essentially created a small state machine. The only two signals of interest are a push button press and a timer timeout, both of which call a function that figures out which state machine to run (I have two). The state machine is small so I decided to leave it as a switch statement over an enum of possible states. If I have time I might change it to use QObjects, but I also like depending less on QT if I have a choice.

                I needed to have the SLOT function call defined for the two events of interest (pushbutton press and a single-shot timer) to the same place ; they are the entry to the control mechanism for my state machine, besides of course the first entry into the state machine which is from the app and not a event. I am also measuring question response times by calculating the time delta.

                Thanks for the feedback

                Lesson: Don't use slots except for simple GUI stuff until I know this better.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt
                • Unsolved