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. QThread example to run a function in MainWindow on button click
Qt 6.11 is out! See what's new in the release blog

QThread example to run a function in MainWindow on button click

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 5 Posters 7.2k 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.
  • J Offline
    J Offline
    JSher
    wrote on last edited by
    #1

    Hello,

    I am trying to wrap my head around QThread and how it relates to MainWindow functions(NOT Main).

    I have a QT Application that has a MainWindow:

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    }
    

    It has a button signal:

    void MainWindow::on_buttonRun_clicked()
    {
              startTheRun();   
    }
    
    

    That calls a function:

    void MainWindow::startTheRun(){
    //does stuff, gets information from ui like this:
    QString something = ui->textbox->text();
    )
    

    I want to run this function on a separate thread and still have access to the ui.

    Can someone point me to an example that does not us the Main.cpp but the MainWindow.cpp?

    I have found examples of this but none seem to have access to the MainWindow functions/objects from their 'run' methods. Clearly I am missing a link somewhere but just cannot wrap my head around it.

    Thanks,
    --James

    JonBJ 1 Reply Last reply
    0
    • J JSher

      Hello,

      I am trying to wrap my head around QThread and how it relates to MainWindow functions(NOT Main).

      I have a QT Application that has a MainWindow:

      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
      }
      

      It has a button signal:

      void MainWindow::on_buttonRun_clicked()
      {
                startTheRun();   
      }
      
      

      That calls a function:

      void MainWindow::startTheRun(){
      //does stuff, gets information from ui like this:
      QString something = ui->textbox->text();
      )
      

      I want to run this function on a separate thread and still have access to the ui.

      Can someone point me to an example that does not us the Main.cpp but the MainWindow.cpp?

      I have found examples of this but none seem to have access to the MainWindow functions/objects from their 'run' methods. Clearly I am missing a link somewhere but just cannot wrap my head around it.

      Thanks,
      --James

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @JSher
      That's because you are not allowed to do this in Qt! Your main UI thread only can access UI objects, any other threads must not. You must use signals/slots as required to communicate between UI thread and other threads. For example, a worker thread could emit() a signal when something happens, and the UI thread could have a slot connected to the signal so that it (the UI thread) can do whatever to update the UI.

      1 Reply Last reply
      2
      • J Offline
        J Offline
        JSher
        wrote on last edited by
        #3

        @JonB

        So I created a big elaborate function that runs based off user input from the ui and in order to change it to a thread I have to write it all in the run() function and pass signals back and forth to get the information from the ui?

        Hmm this does not make sense to me.

        Is it possible to have the thread emit a signal to then run the function I have created?

        --James

        jsulmJ 1 Reply Last reply
        0
        • J JSher

          @JonB

          So I created a big elaborate function that runs based off user input from the ui and in order to change it to a thread I have to write it all in the run() function and pass signals back and forth to get the information from the ui?

          Hmm this does not make sense to me.

          Is it possible to have the thread emit a signal to then run the function I have created?

          --James

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

          @JSher Do you have to pass user input all the time to your function?
          Usually you would do it once when starting the function. So, I don't see how it does not make sense. To my knowledge most GUI frameworks do not allow changes to GUI from other threads than main (GUI) thread, not only Qt.

          Yes, threads can emit signals too.

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

          1 Reply Last reply
          3
          • J Offline
            J Offline
            JSher
            wrote on last edited by
            #5

            No I do not pass user input other than the initial start but I get paramaters from the ui such as ui->comboBox->currentText() all through the function

            --James

            1 Reply Last reply
            0
            • J Offline
              J Offline
              JSher
              wrote on last edited by
              #6

              For instance in Java using Swing I just create a class in my MainGUI class like this:

              class MASummaryTask extends SwingWorker<Void, Void> {
              }
              

              It has full access to the GUI members etc. I just start it from the push button method like this:

              summaryTask = new MASummaryTask();
              summaryTask.addPropertyChangeListener(this);
              summaryTask.execute();
              

              So when I needed to go multithreaded I just run that function from the doInBackground() method of the thread class
              --James

              jsulmJ 1 Reply Last reply
              0
              • J JSher

                For instance in Java using Swing I just create a class in my MainGUI class like this:

                class MASummaryTask extends SwingWorker<Void, Void> {
                }
                

                It has full access to the GUI members etc. I just start it from the push button method like this:

                summaryTask = new MASummaryTask();
                summaryTask.addPropertyChangeListener(this);
                summaryTask.execute();
                

                So when I needed to go multithreaded I just run that function from the doInBackground() method of the thread class
                --James

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

                @JSher I still don't see the problem. Before starting this function collect all needed information from the UI elements and pass it as parameters to your function.

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

                1 Reply Last reply
                0
                • J Offline
                  J Offline
                  JSher
                  wrote on last edited by
                  #8

                  I was hoping to avoid this as it is a great deal of clean up as there is 30+ paramaters mostly pulled from the UI. Was hoping to just be able to run that function in a thread:)

                  Thanks,
                  --James

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    JSher
                    wrote on last edited by
                    #9

                    Ok so I can create threads and emit information back to the main GUI that can then use that information to update a vector or something of that nature to keep track of the work the threads are doing.

                    What I cannot figure out is how to pass the information to the worker thread IE

                    mThread = new MyThread(this);
                    connect(mThread, SIGNAL(runThread()),this,SLOT(onRunThread()));
                    mThread->start();
                    

                    In this code if I put paramaters for runThread(thread class) and same paramaters in onRunThread(gui class), the paramaters will be available to the main gui.

                    So how do I pass paramaters to the thread worker? Here is the thread header:

                    #ifndef MYTHREAD_H
                    #define MYTHREAD_H
                    
                    #include <QThread>
                    
                    class MyThread : public QThread
                    {
                        Q_OBJECT
                    public:
                        explicit MyThread(QObject *parent = 0);
                        void run();
                    signals:
                        void runThread();
                    
                    public slots:
                    
                    };
                    
                    #endif // MYTHREAD_H
                    

                    Thanks,
                    --James

                    1 Reply Last reply
                    0
                    • VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by VRonin
                      #10
                      1. What was said above about ui in a secondary thread is correct and it's a limitation of some OSs, not of Qt. Having said that, however, getters like ui->comboBox->currentText() do not change the UI so they can be called in a secondary thread. The problem remains, however, of how do you prevent race conditions if you access the ui directly (what stops the user to change the index of ui->comboBox while the code is running?)
                      2. if you just need to run a function in a different thread you don't need anything fancy coming from Qt, std::async does that
                      3. QThread is not the thread, it's a container of the actual thread that lives on the tread that spawns it. this means emitting a signal of MyThread in the secondary thread is a race condition and slots of MyThread will be executed in the main thread, not the one it spawns. See this article for an explanation on how to use signals and slots in a secondary thread

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      1 Reply Last reply
                      2
                      • J Offline
                        J Offline
                        JSher
                        wrote on last edited by
                        #11

                        @VRonin I want to run the function in another thread because I want to run the function across several threads(concurrently) and return a results vector to then be used to produce a spreadsheet once all the threads have finished.

                        I can find no examples of pushing a button in a GUI, sending information to a thread function to run and then returning that information to the main thread.....

                        Thanks,
                        --James

                        VRoninV 1 Reply Last reply
                        0
                        • J JSher

                          @VRonin I want to run the function in another thread because I want to run the function across several threads(concurrently) and return a results vector to then be used to produce a spreadsheet once all the threads have finished.

                          I can find no examples of pushing a button in a GUI, sending information to a thread function to run and then returning that information to the main thread.....

                          Thanks,
                          --James

                          VRoninV Offline
                          VRoninV Offline
                          VRonin
                          wrote on last edited by
                          #12

                          @JSher said in QThread example to run a function in MainWindow on button click:

                          sending information to a thread function to run and then returning that information to the main thread

                          This is literally what std::async of vanilla C++ does, otherwise you can use QtConcurrent. You can just google examples of std::async

                          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                          ~Napoleon Bonaparte

                          On a crusade to banish setIndexWidget() from the holy land of Qt

                          1 Reply Last reply
                          1
                          • S Offline
                            S Offline
                            SimonSchroeder
                            wrote on last edited by
                            #13

                            @JSher said in QThread example to run a function in MainWindow on button click:

                            @VRonin I want to run the function in another thread because I want to run the function across several threads(concurrently) and return a results vector to then be used to produce a spreadsheet once all the threads have finished.

                            This sounds like you want something like the functions in QtConcurrent. There is a difference between launching a single thread to do work asynchronously and using multiple threads to split the work. For the latter it makes sense to use a thread pool so you don't have to manage the number of threads yourself. QtConcurrent will use a thread pool internally which automatically adapts to the number of cores available. Probably, you want something like QtConcurrent::map or QtConcurrent::filter. These will give back a QFuture object. Which in turn can be handed to a QFutureWatcher so that you can connect signals from QFutureWatcher to update your GUI once the work is finished.

                            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