Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. GUI blocking...
Forum Updated to NodeBB v4.3 + New Features

GUI blocking...

Scheduled Pinned Locked Moved Unsolved General and Desktop
25 Posts 6 Posters 9.0k Views 2 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.
  • A Offline
    A Offline
    Aesgarth
    wrote on last edited by
    #1

    This is my code so far.....

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <wiringPi.h>
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    //frame1
    void MainWindow::on_pushButton_clicked(bool checked)
    {
        wiringPiSetup();
        pinMode (0, OUTPUT);
        digitalWrite (0, HIGH);
    }
    
    void MainWindow::on_pushButton_2_clicked(bool checked)
    {
        wiringPiSetup();
        pinMode (0, OUTPUT);
        digitalWrite (0, LOW);
    }
    
    void MainWindow::on_pushButton_3_clicked(bool checked)
    {
        wiringPiSetup();
        pinMode (0, OUTPUT);
        digitalWrite (0, HIGH); delay(750);
        digitalWrite (0, LOW); delay(750);
    }
    
    void MainWindow::on_pushButton_4_clicked(bool checked)
    {
        wiringPiSetup();
        pinMode (0, OUTPUT);
        digitalWrite (0, HIGH); delay(7200000);
        digitalWrite (0, LOW); delay(1080000);
    }
    //frame2
    void MainWindow::on_pushButton_5_clicked(bool checked)
    {
        wiringPiSetup();
        pinMode (2, OUTPUT);
        digitalWrite (2, HIGH);
    }
    
    void MainWindow::on_pushButton_6_clicked(bool checked)
    {
        wiringPiSetup();
        pinMode (2, OUTPUT);
        digitalWrite (2, LOW);
    }
    
    void MainWindow::on_pushButton_7_clicked(bool checked)
    {
        wiringPiSetup();
        pinMode (0, OUTPUT);
        digitalWrite (2, HIGH); delay(750);
        digitalWrite (2, LOW); delay(750);
    }
    
    void MainWindow::on_pushButton_8_clicked(bool checked)
    {
        wiringPiSetup();
        pinMode (0, OUTPUT);
        digitalWrite (2, HIGH); delay(7200000);
        digitalWrite (2, LOW); delay(1080000);
    }
    

    pushButton, pushButton_2, pushButton_5 and pushButton_6 work as i want them to, but i've tried various methods and can't get the others to work - They perform their tasks correctly, but obviously block the gui for quite a while when operating. what i want them to do is operate continuously in a loop while the button is pressed (buttons are checkable) but stop when the button is unchecked - and i'd like the GUI to be functional while doing it...

    I've tried to use threading to achieve this but i just can't get it to work. Any suggestions how i should go about this? - for someone who only has a very basic understanding of what they're doing...

    joeQJ jsulmJ 2 Replies Last reply
    0
    • A Aesgarth

      This is my code so far.....

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      #include <wiringPi.h>
      MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      //frame1
      void MainWindow::on_pushButton_clicked(bool checked)
      {
          wiringPiSetup();
          pinMode (0, OUTPUT);
          digitalWrite (0, HIGH);
      }
      
      void MainWindow::on_pushButton_2_clicked(bool checked)
      {
          wiringPiSetup();
          pinMode (0, OUTPUT);
          digitalWrite (0, LOW);
      }
      
      void MainWindow::on_pushButton_3_clicked(bool checked)
      {
          wiringPiSetup();
          pinMode (0, OUTPUT);
          digitalWrite (0, HIGH); delay(750);
          digitalWrite (0, LOW); delay(750);
      }
      
      void MainWindow::on_pushButton_4_clicked(bool checked)
      {
          wiringPiSetup();
          pinMode (0, OUTPUT);
          digitalWrite (0, HIGH); delay(7200000);
          digitalWrite (0, LOW); delay(1080000);
      }
      //frame2
      void MainWindow::on_pushButton_5_clicked(bool checked)
      {
          wiringPiSetup();
          pinMode (2, OUTPUT);
          digitalWrite (2, HIGH);
      }
      
      void MainWindow::on_pushButton_6_clicked(bool checked)
      {
          wiringPiSetup();
          pinMode (2, OUTPUT);
          digitalWrite (2, LOW);
      }
      
      void MainWindow::on_pushButton_7_clicked(bool checked)
      {
          wiringPiSetup();
          pinMode (0, OUTPUT);
          digitalWrite (2, HIGH); delay(750);
          digitalWrite (2, LOW); delay(750);
      }
      
      void MainWindow::on_pushButton_8_clicked(bool checked)
      {
          wiringPiSetup();
          pinMode (0, OUTPUT);
          digitalWrite (2, HIGH); delay(7200000);
          digitalWrite (2, LOW); delay(1080000);
      }
      

      pushButton, pushButton_2, pushButton_5 and pushButton_6 work as i want them to, but i've tried various methods and can't get the others to work - They perform their tasks correctly, but obviously block the gui for quite a while when operating. what i want them to do is operate continuously in a loop while the button is pressed (buttons are checkable) but stop when the button is unchecked - and i'd like the GUI to be functional while doing it...

      I've tried to use threading to achieve this but i just can't get it to work. Any suggestions how i should go about this? - for someone who only has a very basic understanding of what they're doing...

      joeQJ Offline
      joeQJ Offline
      joeQ
      wrote on last edited by
      #2

      @Aesgarth hi,friend.welcome.

      In the function of button_ 3,4,7 and 8. you have delay ... operates. They make the GUI block some time.

      Yes, you are right when we have some tasks of should to use long time, we should to use thread. what's problem when you used thread ?

      what you want is when one button pressed(checked), the back running one task in thread, when button(unchecked), the task to stop ,it means stop thread. is it?

      Just do it!

      A 1 Reply Last reply
      3
      • A Aesgarth

        This is my code so far.....

        #include "mainwindow.h"
        #include "ui_mainwindow.h"
        #include <wiringPi.h>
        MainWindow::MainWindow(QWidget *parent) :
            QMainWindow(parent),
            ui(new Ui::MainWindow)
        {
            ui->setupUi(this);
        }
        
        MainWindow::~MainWindow()
        {
            delete ui;
        }
        //frame1
        void MainWindow::on_pushButton_clicked(bool checked)
        {
            wiringPiSetup();
            pinMode (0, OUTPUT);
            digitalWrite (0, HIGH);
        }
        
        void MainWindow::on_pushButton_2_clicked(bool checked)
        {
            wiringPiSetup();
            pinMode (0, OUTPUT);
            digitalWrite (0, LOW);
        }
        
        void MainWindow::on_pushButton_3_clicked(bool checked)
        {
            wiringPiSetup();
            pinMode (0, OUTPUT);
            digitalWrite (0, HIGH); delay(750);
            digitalWrite (0, LOW); delay(750);
        }
        
        void MainWindow::on_pushButton_4_clicked(bool checked)
        {
            wiringPiSetup();
            pinMode (0, OUTPUT);
            digitalWrite (0, HIGH); delay(7200000);
            digitalWrite (0, LOW); delay(1080000);
        }
        //frame2
        void MainWindow::on_pushButton_5_clicked(bool checked)
        {
            wiringPiSetup();
            pinMode (2, OUTPUT);
            digitalWrite (2, HIGH);
        }
        
        void MainWindow::on_pushButton_6_clicked(bool checked)
        {
            wiringPiSetup();
            pinMode (2, OUTPUT);
            digitalWrite (2, LOW);
        }
        
        void MainWindow::on_pushButton_7_clicked(bool checked)
        {
            wiringPiSetup();
            pinMode (0, OUTPUT);
            digitalWrite (2, HIGH); delay(750);
            digitalWrite (2, LOW); delay(750);
        }
        
        void MainWindow::on_pushButton_8_clicked(bool checked)
        {
            wiringPiSetup();
            pinMode (0, OUTPUT);
            digitalWrite (2, HIGH); delay(7200000);
            digitalWrite (2, LOW); delay(1080000);
        }
        

        pushButton, pushButton_2, pushButton_5 and pushButton_6 work as i want them to, but i've tried various methods and can't get the others to work - They perform their tasks correctly, but obviously block the gui for quite a while when operating. what i want them to do is operate continuously in a loop while the button is pressed (buttons are checkable) but stop when the button is unchecked - and i'd like the GUI to be functional while doing it...

        I've tried to use threading to achieve this but i just can't get it to work. Any suggestions how i should go about this? - for someone who only has a very basic understanding of what they're doing...

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @Aesgarth Instead of using threads you can use QTimer:

        void MainWindow::on_pushButton_4_clicked(bool checked)
        {
            wiringPiSetup();
            pinMode (0, OUTPUT);
            digitalWrite (0, HIGH);
            QTimer::singleShot(7200, SLOT(sendLow()));
        }
        
        void MainWindow::sendLow()
        {
            digitalWrite (0, LOW);
        }
        

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        2
        • joeQJ joeQ

          @Aesgarth hi,friend.welcome.

          In the function of button_ 3,4,7 and 8. you have delay ... operates. They make the GUI block some time.

          Yes, you are right when we have some tasks of should to use long time, we should to use thread. what's problem when you used thread ?

          what you want is when one button pressed(checked), the back running one task in thread, when button(unchecked), the task to stop ,it means stop thread. is it?

          A Offline
          A Offline
          Aesgarth
          wrote on last edited by Aesgarth
          #4

          Thanks for the help!

          @joeQ I don't have the code any more as i started from scratch, but when running, clicking the button that should start a thread crashed the program. I think threads are probably the answer but I don't understand how they work. Pretty confident i'm the problem here. I understand that delay is what is blocking the GUI but i need it -or an alternative. the button is turning a physical relay on and off at fixed intervals.

          @jsulm I'll give that a try, will that still work OK built into a loop - so the task repeats as long as the button is checked?

          jsulmJ 1 Reply Last reply
          0
          • A Aesgarth

            Thanks for the help!

            @joeQ I don't have the code any more as i started from scratch, but when running, clicking the button that should start a thread crashed the program. I think threads are probably the answer but I don't understand how they work. Pretty confident i'm the problem here. I understand that delay is what is blocking the GUI but i need it -or an alternative. the button is turning a physical relay on and off at fixed intervals.

            @jsulm I'll give that a try, will that still work OK built into a loop - so the task repeats as long as the button is checked?

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @Aesgarth If you do not want to block your UI then avoid long lasting or endless loops. You can simply check the checked status of the button and continue only if it is checked.

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            A 1 Reply Last reply
            1
            • Pablo J. RoginaP Offline
              Pablo J. RoginaP Offline
              Pablo J. Rogina
              wrote on last edited by Pablo J. Rogina
              #6

              @Aesgarth loops related to GUI/user events in Qt applications are not a good idea... that's why Qt's provide its own event loop and the magic of signals.

              I assume that the QPushButtons you're using are checkable, and you may want to pay attention to the toggled(bool checked) signal so you can react to the button state changes (checked or unchecked).

              the button is turning a physical relay on and off at fixed intervals.

              I guess you're not stated your requirements well. Let's assume that if I click/check button for relay #1 it will be on for M seconds, then off for N seconds, then on for M seconds again and so on.
              So I'd use the suggestion from jsulm of using QTimer but in this case I'd use 2 timers: one with the duration of on period, and when this timer is off, the off timer is fired; and then the process will alternate until the button is unchecked where everything will stop.

              wiringPiSetup();       // only call once in the application
              QTimer timerRelay4On = new QTimer(this);
              timerRelay4On->setInterval(relay4IntervalOn);
              timerRelay4On->setSingleShot(true);
              connect(timerRelay4On, SLOT(sendLow(pin)));
              
              QTimer timerRelay4Off = new QTimer(this);
              timerRelay4Off->setInterval(relay4IntervalOff);
              timerRelay4Off->setSingleShot(true);
              connect(timerRelay4Off, SLOT(sendHigh(pin)));
              
              void MainWindow::on_pushButton_4_toggled(bool checked)
              {
                  pinMode(0, OUTPUT);
                  if (checked) {
                      // button initially checked
                      // make the ball roll... on -> off -> on -> off -> etc
                      sendHigh(0);
                  } else {
                      // button unchecked
                      // everything must stop
                      sendLow(0);
                      timerReleay4Off->stop();
                      timerReleay4On->stop();
                  }
              }
              
              void MainWindow::sendHigh(int pin)
              {
                  digitalWrite(pin, HIGH);
                  timerRelay4Off->start();
              }
              
              void MainWindow::sendLow(int pin)
              {
                  digitalWrite(pin, LOW);
                  timerRelay4On->start();
              }
              

              Spoiler alert: code was written directly in post, it might not compile as is.
              For better code standards, you may want to use meaningful constants for pin values, i.e.

              sendHigh(PIN0_RELAY_BEDROOM_LIGHT);
              

              instead of

              sendHigh(0);
              

              Happy relay control!

              Upvote the answer(s) that helped you solve the issue
              Use "Topic Tools" button to mark your post as Solved
              Add screenshots via postimage.org
              Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

              A 1 Reply Last reply
              1
              • jsulmJ jsulm

                @Aesgarth If you do not want to block your UI then avoid long lasting or endless loops. You can simply check the checked status of the button and continue only if it is checked.

                A Offline
                A Offline
                Aesgarth
                wrote on last edited by Aesgarth
                #7

                Thanks again for the help...

                @jsulm
                I can't get that to work, getting the error:
                error: no matching function
                for call to ‘QTimer::singleShot(int, const char*)’
                QTimer::singleShot(7200, SLOT(sendLow()));
                Using it on pushButton_7 - simply as that's the pin i have the multimeter currently connected to...
                have tidied my code a bit:

                #include "mainwindow.h"
                #include "ui_mainwindow.h"
                #include <wiringPi.h>
                #include <QTimer>
                MainWindow::MainWindow(QWidget *parent) :
                    QMainWindow(parent),
                    ui(new Ui::MainWindow)
                {
                    ui->setupUi(this);
                }
                MainWindow::~MainWindow()
                {
                    //wiringPi pin setup
                    wiringPiSetup();
                    pinMode (0, OUTPUT); //relay pin 1
                    pinMode (2, OUTPUT); //relay pin 2
                    delete ui;
                }
                //
                void MainWindow::sendLow()
                {
                    digitalWrite (2, LOW);
                }
                //frame1
                //
                //Turn relay 1 on
                void MainWindow::on_pushButton_clicked(bool checked)
                {
                    digitalWrite (0, HIGH);
                }
                //Turn relay 1 off
                void MainWindow::on_pushButton_2_clicked(bool checked)
                {
                    digitalWrite (0, LOW);
                }
                //Cycle relay 1 off/on at given interval
                void MainWindow::on_pushButton_3_clicked(bool checked)
                {
                    digitalWrite (0, HIGH); delay(750);
                    digitalWrite (0, LOW); delay(750);
                }
                //Cycle relay 1 off/on at given interval
                void MainWindow::on_pushButton_4_clicked(bool checked)
                {
                    digitalWrite (0, HIGH); delay(7200000);
                    digitalWrite (0, LOW); delay(1080000);
                }
                //
                //frame2
                //
                //Turn relay 2 on 
                void MainWindow::on_pushButton_5_clicked(bool checked)
                {
                    digitalWrite (2, HIGH);
                }
                //Turn relay 2 off 
                void MainWindow::on_pushButton_6_clicked(bool checked)
                {
                    digitalWrite (2, LOW);
                }
                //cycle relay 2 off/on at given interval 
                void MainWindow::on_pushButton_7_clicked(bool checked)
                {
                    digitalWrite (2, HIGH);
                    QTimer::singleShot(7200, SLOT(sendLow()));
                }
                //cycle relay 2 off/on at given interval
                void MainWindow::on_pushButton_8_clicked(bool checked)
                {
                    digitalWrite (2, HIGH); delay(7200000);
                    digitalWrite (2, LOW); delay(1080000);
                }
                
                

                the error occurs on line 65.

                @Pablo-J-Rogina
                I think that looks like exactly what i want to do, but i'm struggling with correct implementation. Clearly my C++ is VERY rusty.

                jsulmJ 1 Reply Last reply
                1
                • A Aesgarth

                  Thanks again for the help...

                  @jsulm
                  I can't get that to work, getting the error:
                  error: no matching function
                  for call to ‘QTimer::singleShot(int, const char*)’
                  QTimer::singleShot(7200, SLOT(sendLow()));
                  Using it on pushButton_7 - simply as that's the pin i have the multimeter currently connected to...
                  have tidied my code a bit:

                  #include "mainwindow.h"
                  #include "ui_mainwindow.h"
                  #include <wiringPi.h>
                  #include <QTimer>
                  MainWindow::MainWindow(QWidget *parent) :
                      QMainWindow(parent),
                      ui(new Ui::MainWindow)
                  {
                      ui->setupUi(this);
                  }
                  MainWindow::~MainWindow()
                  {
                      //wiringPi pin setup
                      wiringPiSetup();
                      pinMode (0, OUTPUT); //relay pin 1
                      pinMode (2, OUTPUT); //relay pin 2
                      delete ui;
                  }
                  //
                  void MainWindow::sendLow()
                  {
                      digitalWrite (2, LOW);
                  }
                  //frame1
                  //
                  //Turn relay 1 on
                  void MainWindow::on_pushButton_clicked(bool checked)
                  {
                      digitalWrite (0, HIGH);
                  }
                  //Turn relay 1 off
                  void MainWindow::on_pushButton_2_clicked(bool checked)
                  {
                      digitalWrite (0, LOW);
                  }
                  //Cycle relay 1 off/on at given interval
                  void MainWindow::on_pushButton_3_clicked(bool checked)
                  {
                      digitalWrite (0, HIGH); delay(750);
                      digitalWrite (0, LOW); delay(750);
                  }
                  //Cycle relay 1 off/on at given interval
                  void MainWindow::on_pushButton_4_clicked(bool checked)
                  {
                      digitalWrite (0, HIGH); delay(7200000);
                      digitalWrite (0, LOW); delay(1080000);
                  }
                  //
                  //frame2
                  //
                  //Turn relay 2 on 
                  void MainWindow::on_pushButton_5_clicked(bool checked)
                  {
                      digitalWrite (2, HIGH);
                  }
                  //Turn relay 2 off 
                  void MainWindow::on_pushButton_6_clicked(bool checked)
                  {
                      digitalWrite (2, LOW);
                  }
                  //cycle relay 2 off/on at given interval 
                  void MainWindow::on_pushButton_7_clicked(bool checked)
                  {
                      digitalWrite (2, HIGH);
                      QTimer::singleShot(7200, SLOT(sendLow()));
                  }
                  //cycle relay 2 off/on at given interval
                  void MainWindow::on_pushButton_8_clicked(bool checked)
                  {
                      digitalWrite (2, HIGH); delay(7200000);
                      digitalWrite (2, LOW); delay(1080000);
                  }
                  
                  

                  the error occurs on line 65.

                  @Pablo-J-Rogina
                  I think that looks like exactly what i want to do, but i'm struggling with correct implementation. Clearly my C++ is VERY rusty.

                  jsulmJ Offline
                  jsulmJ Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @Aesgarth said in GUI blocking...:

                  QTimer::singleShot(7200, SLOT(sendLow()));

                  Well, you need to provide the receiver of the signal as well, forgot this in my untested example (see http://doc.qt.io/qt-5/qtimer.html#singleShot-1):

                  QTimer::singleShot(7200, this, SLOT(sendLow()));
                  

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  JonBJ 1 Reply Last reply
                  1
                  • jsulmJ jsulm

                    @Aesgarth said in GUI blocking...:

                    QTimer::singleShot(7200, SLOT(sendLow()));

                    Well, you need to provide the receiver of the signal as well, forgot this in my untested example (see http://doc.qt.io/qt-5/qtimer.html#singleShot-1):

                    QTimer::singleShot(7200, this, SLOT(sendLow()));
                    
                    JonBJ Online
                    JonBJ Online
                    JonB
                    wrote on last edited by JonB
                    #9

                    @jsulm
                    Just so I understand. OP reported error message:

                    for call to ‘QTimer::singleShot(int, const char*)’
                    QTimer::singleShot(7200, SLOT(sendLow()));
                    

                    I don't have/use C++, does your SLOT() macro(?) really return const char *, I assumed it would resolve to some sort of function argument?

                    Also, while I'm here, I'm always surprised to see it's SLOT(sendlow()) which would seem to call sendLow() at this point in code, I would have thought it would be more like SLOT(sendlow) ? [EDIT: Ah, is SLOT perchance some kind of nasty "lambda" (or whatever you call it in C++) expansion?]

                    jsulmJ 1 Reply Last reply
                    0
                    • JonBJ JonB

                      @jsulm
                      Just so I understand. OP reported error message:

                      for call to ‘QTimer::singleShot(int, const char*)’
                      QTimer::singleShot(7200, SLOT(sendLow()));
                      

                      I don't have/use C++, does your SLOT() macro(?) really return const char *, I assumed it would resolve to some sort of function argument?

                      Also, while I'm here, I'm always surprised to see it's SLOT(sendlow()) which would seem to call sendLow() at this point in code, I would have thought it would be more like SLOT(sendlow) ? [EDIT: Ah, is SLOT perchance some kind of nasty "lambda" (or whatever you call it in C++) expansion?]

                      jsulmJ Offline
                      jsulmJ Offline
                      jsulm
                      Lifetime Qt Champion
                      wrote on last edited by jsulm
                      #10

                      @JNBarchan said in GUI blocking...:

                      does your SLOT() macro(?) really return const char *

                      Yes, it does

                      "I'm always surprised to see it's SLOT(sendlow()) which would seem to call sendLow() at this point in code" - this is wrong. sendLow() is not called at that time because SLOT() is a macro and macros are handled by preprocessor before compiling and not at runtime. Preprocessor is simply a tool which replaces text. Take a look at SLOT macro implementation to see what its output will be or use -E parameter for GCC to tell it to stop after preprocessing step to see what preprocessor did with SLOT().

                      With Qt5 it is better to use the new connect syntax based on function pointers. This way, if you try to connect incompatible or even not existing signals/slots you will get a compiler error instead of a warning in the console at runtime.

                      https://forum.qt.io/topic/113070/qt-code-of-conduct

                      JonBJ 1 Reply Last reply
                      1
                      • jsulmJ jsulm

                        @JNBarchan said in GUI blocking...:

                        does your SLOT() macro(?) really return const char *

                        Yes, it does

                        "I'm always surprised to see it's SLOT(sendlow()) which would seem to call sendLow() at this point in code" - this is wrong. sendLow() is not called at that time because SLOT() is a macro and macros are handled by preprocessor before compiling and not at runtime. Preprocessor is simply a tool which replaces text. Take a look at SLOT macro implementation to see what its output will be or use -E parameter for GCC to tell it to stop after preprocessing step to see what preprocessor did with SLOT().

                        With Qt5 it is better to use the new connect syntax based on function pointers. This way, if you try to connect incompatible or even not existing signals/slots you will get a compiler error instead of a warning in the console at runtime.

                        JonBJ Online
                        JonBJ Online
                        JonB
                        wrote on last edited by JonB
                        #11

                        @jsulm said in GUI blocking...:

                        because SLOT() is a macro and macros are handled by preprocessor before compiling and not at runtime

                        Yes I am well aware.

                        Take a look at SLOT macro implementation to see what its output will be or use -E parameter for GCC to tell it to stop after preprocessing step to see what preprocessor did with SLOT().

                        As I said: "I don't have/use C++" [for Qt], I didn't even know for sure that it's a macro rather than, say, in-line function, I only code from Python/PyQt, which handles it quite differently. None of your comments about syntax, compilation etc. apply to Python/PyQt. I'm requesting whether you might be kind enough to paste the C++ SLOT macro code precisely so I can have a look at it to understand.

                        kshegunovK 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @jsulm said in GUI blocking...:

                          because SLOT() is a macro and macros are handled by preprocessor before compiling and not at runtime

                          Yes I am well aware.

                          Take a look at SLOT macro implementation to see what its output will be or use -E parameter for GCC to tell it to stop after preprocessing step to see what preprocessor did with SLOT().

                          As I said: "I don't have/use C++" [for Qt], I didn't even know for sure that it's a macro rather than, say, in-line function, I only code from Python/PyQt, which handles it quite differently. None of your comments about syntax, compilation etc. apply to Python/PyQt. I'm requesting whether you might be kind enough to paste the C++ SLOT macro code precisely so I can have a look at it to understand.

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by kshegunov
                          #12
                          #define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__)
                          #define METHOD(a)   qFlagLocation("0"#a QLOCATION)
                          #define SLOT(a)     qFlagLocation("1"#a QLOCATION)
                          #define SIGNAL(a)   qFlagLocation("2"#a QLOCATION)
                          

                          However the process is rather complicated. qFlagLocation here is a function, but that's beyond the point as it's not really needed for the resolution. The macro converts the method's signature to a string, which string is then used by the Qt meta-object system to retrieve the exact function address/signal index by means of the data generated by the meta-object compiler (moc). Then Qt can call the needed method based on that string with argument type checking and such. The arguments for the slots are packed through a special utility class (e.g. see Q_ARG macro in the docs and QGenericArgument).

                          Read and abide by the Qt Code of Conduct

                          JonBJ 1 Reply Last reply
                          2
                          • kshegunovK kshegunov
                            #define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__)
                            #define METHOD(a)   qFlagLocation("0"#a QLOCATION)
                            #define SLOT(a)     qFlagLocation("1"#a QLOCATION)
                            #define SIGNAL(a)   qFlagLocation("2"#a QLOCATION)
                            

                            However the process is rather complicated. qFlagLocation here is a function, but that's beyond the point as it's not really needed for the resolution. The macro converts the method's signature to a string, which string is then used by the Qt meta-object system to retrieve the exact function address/signal index by means of the data generated by the meta-object compiler (moc). Then Qt can call the needed method based on that string with argument type checking and such. The arguments for the slots are packed through a special utility class (e.g. see Q_ARG macro in the docs and QGenericArgument).

                            JonBJ Online
                            JonBJ Online
                            JonB
                            wrote on last edited by kshegunov
                            #13

                            @kshegunov
                            [You don't show the definition of the SLOT() macro too?]
                            Edit: Yeah, sorry, I've added it to the post ~kshegunov

                            Ah, that is very interesting indeed, thank you.

                            Note that it looks quite different from what I am writing in my code from Python/PyQt, e.g.:
                            self.btnDelete.clicked.connect(self.deletePayment)

                            Note how the slot-handling function is written as func not func() (i.e. function reference not call), which is much more what I expected.

                            kshegunovK 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @kshegunov
                              [You don't show the definition of the SLOT() macro too?]
                              Edit: Yeah, sorry, I've added it to the post ~kshegunov

                              Ah, that is very interesting indeed, thank you.

                              Note that it looks quite different from what I am writing in my code from Python/PyQt, e.g.:
                              self.btnDelete.clicked.connect(self.deletePayment)

                              Note how the slot-handling function is written as func not func() (i.e. function reference not call), which is much more what I expected.

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by
                              #14

                              @JNBarchan said in GUI blocking...:

                              i.e. function reference not call

                              In C++ that would not be a call, but rather the signature (the declaration). It's needed to know by the meta-object system so the magic of finding the correct overloads and the correct arguments, and name to be found in the generated by moc data. The resolution to a pointer to the function is done in runtime. In Qt 5 however, a pointer-to-member should be passed (thus resolution to a an address is at compile time) and there is some very different template magic at work in that case.

                              Read and abide by the Qt Code of Conduct

                              JonBJ 1 Reply Last reply
                              1
                              • kshegunovK kshegunov

                                @JNBarchan said in GUI blocking...:

                                i.e. function reference not call

                                In C++ that would not be a call, but rather the signature (the declaration). It's needed to know by the meta-object system so the magic of finding the correct overloads and the correct arguments, and name to be found in the generated by moc data. The resolution to a pointer to the function is done in runtime. In Qt 5 however, a pointer-to-member should be passed (thus resolution to a an address is at compile time) and there is some very different template magic at work in that case.

                                JonBJ Online
                                JonBJ Online
                                JonB
                                wrote on last edited by
                                #15

                                @kshegunov said in GUI blocking...:

                                In Qt 5 however, a pointer-to-member should be passed (thus resolution to a an address is at compile time) and there is some very different template magic at work in that case.

                                Yes indeed, and this seems to be what the inherited Python/PyQt code I have uses (and that used to work in that code in Qt4/PyQt4 too).

                                It's clearly a lot more efficient to pass a direct function address at "compile" time than to look up strings of names at runtime.

                                P.S.
                                Sorry if I have hijacked this thread. If you feel you want to move your exchange with me from here to its own thread I would quite understand.

                                A 1 Reply Last reply
                                0
                                • JonBJ JonB

                                  @kshegunov said in GUI blocking...:

                                  In Qt 5 however, a pointer-to-member should be passed (thus resolution to a an address is at compile time) and there is some very different template magic at work in that case.

                                  Yes indeed, and this seems to be what the inherited Python/PyQt code I have uses (and that used to work in that code in Qt4/PyQt4 too).

                                  It's clearly a lot more efficient to pass a direct function address at "compile" time than to look up strings of names at runtime.

                                  P.S.
                                  Sorry if I have hijacked this thread. If you feel you want to move your exchange with me from here to its own thread I would quite understand.

                                  A Offline
                                  A Offline
                                  Aesgarth
                                  wrote on last edited by
                                  #16

                                  @JNBarchan said in GUI blocking...:

                                  P.S.
                                  Sorry if I have hijacked this thread. If you feel you want to move your exchange with me from here to its own thread I would quite understand.

                                  Feel free to carry on here, i might just learn something...

                                  1 Reply Last reply
                                  1
                                  • Pablo J. RoginaP Offline
                                    Pablo J. RoginaP Offline
                                    Pablo J. Rogina
                                    wrote on last edited by
                                    #17

                                    Feel free to carry on here, i might just learn something...

                                    Guys, please respect the forum etiquette. It's not good to hijack threads :-)

                                    Feell free to start another post for this ongoing exchange about a topic different from the original post. Thank you.

                                    Upvote the answer(s) that helped you solve the issue
                                    Use "Topic Tools" button to mark your post as Solved
                                    Add screenshots via postimage.org
                                    Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

                                    1 Reply Last reply
                                    2
                                    • Pablo J. RoginaP Pablo J. Rogina

                                      @Aesgarth loops related to GUI/user events in Qt applications are not a good idea... that's why Qt's provide its own event loop and the magic of signals.

                                      I assume that the QPushButtons you're using are checkable, and you may want to pay attention to the toggled(bool checked) signal so you can react to the button state changes (checked or unchecked).

                                      the button is turning a physical relay on and off at fixed intervals.

                                      I guess you're not stated your requirements well. Let's assume that if I click/check button for relay #1 it will be on for M seconds, then off for N seconds, then on for M seconds again and so on.
                                      So I'd use the suggestion from jsulm of using QTimer but in this case I'd use 2 timers: one with the duration of on period, and when this timer is off, the off timer is fired; and then the process will alternate until the button is unchecked where everything will stop.

                                      wiringPiSetup();       // only call once in the application
                                      QTimer timerRelay4On = new QTimer(this);
                                      timerRelay4On->setInterval(relay4IntervalOn);
                                      timerRelay4On->setSingleShot(true);
                                      connect(timerRelay4On, SLOT(sendLow(pin)));
                                      
                                      QTimer timerRelay4Off = new QTimer(this);
                                      timerRelay4Off->setInterval(relay4IntervalOff);
                                      timerRelay4Off->setSingleShot(true);
                                      connect(timerRelay4Off, SLOT(sendHigh(pin)));
                                      
                                      void MainWindow::on_pushButton_4_toggled(bool checked)
                                      {
                                          pinMode(0, OUTPUT);
                                          if (checked) {
                                              // button initially checked
                                              // make the ball roll... on -> off -> on -> off -> etc
                                              sendHigh(0);
                                          } else {
                                              // button unchecked
                                              // everything must stop
                                              sendLow(0);
                                              timerReleay4Off->stop();
                                              timerReleay4On->stop();
                                          }
                                      }
                                      
                                      void MainWindow::sendHigh(int pin)
                                      {
                                          digitalWrite(pin, HIGH);
                                          timerRelay4Off->start();
                                      }
                                      
                                      void MainWindow::sendLow(int pin)
                                      {
                                          digitalWrite(pin, LOW);
                                          timerRelay4On->start();
                                      }
                                      

                                      Spoiler alert: code was written directly in post, it might not compile as is.
                                      For better code standards, you may want to use meaningful constants for pin values, i.e.

                                      sendHigh(PIN0_RELAY_BEDROOM_LIGHT);
                                      

                                      instead of

                                      sendHigh(0);
                                      

                                      Happy relay control!

                                      A Offline
                                      A Offline
                                      Aesgarth
                                      wrote on last edited by
                                      #18

                                      @Pablo-J.-Rogina

                                      Can you explain to me what this is doing, as if explaining to a very small child...

                                      wiringPiSetup();       // only call once in the application
                                      QTimer timerRelay4On = new QTimer(this);
                                      timerRelay4On->setInterval(relay4IntervalOn);
                                      timerRelay4On->setSingleShot(true);
                                      connect(timerRelay4On, SLOT(sendLow(pin)));
                                      
                                      QTimer timerRelay4Off = new QTimer(this);
                                      timerRelay4Off->setInterval(relay4IntervalOff);
                                      timerRelay4Off->setSingleShot(true);
                                      connect(timerRelay4Off, SLOT(sendHigh(pin)));
                                      

                                      thanks.

                                      jsulmJ 1 Reply Last reply
                                      0
                                      • A Aesgarth

                                        @Pablo-J.-Rogina

                                        Can you explain to me what this is doing, as if explaining to a very small child...

                                        wiringPiSetup();       // only call once in the application
                                        QTimer timerRelay4On = new QTimer(this);
                                        timerRelay4On->setInterval(relay4IntervalOn);
                                        timerRelay4On->setSingleShot(true);
                                        connect(timerRelay4On, SLOT(sendLow(pin)));
                                        
                                        QTimer timerRelay4Off = new QTimer(this);
                                        timerRelay4Off->setInterval(relay4IntervalOff);
                                        timerRelay4Off->setSingleShot(true);
                                        connect(timerRelay4Off, SLOT(sendHigh(pin)));
                                        

                                        thanks.

                                        jsulmJ Offline
                                        jsulmJ Offline
                                        jsulm
                                        Lifetime Qt Champion
                                        wrote on last edited by jsulm
                                        #19

                                        @Aesgarth This code will not work.
                                        First:

                                        QTimer *timerRelay4On = new QTimer(this); // timerRelay4On needs to be pointer else it will not even compile
                                        

                                        Second:

                                        connect(timerRelay4On, SLOT(sendLow(pin)));
                                        connect(timerRelay4Off, SLOT(sendHigh(pin)));
                                        

                                        both connects are wrong: where are signal and pointer to receiver object? Check documentation for proper connect usage. The slots used require a parameter (pin) which cannot be passed from the timer (QTimer does not know anything about pins) - so, signal and slot will not match.
                                        This code can be simplified using static http://doc.qt.io/qt-5/qtimer.html#singleShot method (no need to create an instance of QTimer).

                                        What the source code will do after the issues were fixed: after some time (defined by relay4IntervalOn) sendLow() will be called, after some time (defined by relay4IntervalOff) sendHigh() will be called.

                                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                                        A 1 Reply Last reply
                                        0
                                        • Pablo J. RoginaP Offline
                                          Pablo J. RoginaP Offline
                                          Pablo J. Rogina
                                          wrote on last edited by
                                          #20

                                          To all, as previously pointed out, my code was not tested just provided as a guideline of what might be a possible approach to your requirements. Here you have the snippet of a working example for a checkable button starting the process and the ON/OFF cycle running on intervals of 3 secs ON and 1 sec OFF until the button is unchecked again when the timers are stopped. References to wiringPi library's functions are commented out since I'm not using it for this example, but for reference where they should be. No more code examples will be provided from my side. Thank you.

                                          ...
                                          MainWindow::MainWindow(QWidget *parent) :
                                              QMainWindow(parent),
                                              ui(new Ui::MainWindow)
                                          {
                                              ui->setupUi(this);
                                          
                                              timerRelay1On = new QTimer(this);
                                              timerRelay1On->setInterval(3000);
                                              timerRelay1On->setSingleShot(true);
                                              connect(timerRelay1On, SIGNAL(timeout()), this, SLOT(sendLow()));
                                          
                                              timerRelay1Off = new QTimer(this);
                                              timerRelay1Off->setInterval(1000);
                                              timerRelay1Off->setSingleShot(true);
                                              connect(timerRelay1Off, SIGNAL(timeout()), this, SLOT(sendHigh()));
                                          }
                                          
                                          MainWindow::~MainWindow()
                                          {
                                              delete ui;
                                          }
                                          
                                          void MainWindow::on_btnRelay1_toggled() {
                                              pin = 0;
                                          //    pinMode(pin, OUTPUT);
                                              if (ui->btnRelay1->isChecked()) {
                                                  // button initially checked
                                                  // make the ball roll... on -> off -> on -> off -> etc
                                                  sendHigh();
                                              } else {
                                                  // button unchecked
                                                  // everything must stop
                                                  timerRelay1Off->stop();
                                                  timerRelay1On->stop();
                                                  qDebug() << "Everything stopped!";
                                              }
                                          }
                                          
                                          void MainWindow::sendHigh()
                                          {
                                          //    digitalWrite(pin, HIGH);
                                              qDebug() << "Pin " << pin << " HIGH";
                                              timerRelay1On->start();
                                              qDebug() << QDateTime::currentDateTime() << ": Timer ON started";
                                          }
                                          
                                          void MainWindow::sendLow()
                                          {
                                          //    digitalWrite(pin, LOW);
                                              qDebug() << "Pin " << pin << " LOW";
                                              timerRelay1Off->start();
                                              qDebug() << QDateTime::currentDateTime() << ": Timer OFF started";
                                          }
                                          

                                          Upvote the answer(s) that helped you solve the issue
                                          Use "Topic Tools" button to mark your post as Solved
                                          Add screenshots via postimage.org
                                          Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

                                          A 1 Reply Last reply
                                          1

                                          • Login

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