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. Refresh display of QTableWidget
Forum Updated to NodeBB v4.3 + New Features

Refresh display of QTableWidget

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 5 Posters 8.5k Views 3 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.
  • Chris KawaC Offline
    Chris KawaC Offline
    Chris Kawa
    Lifetime Qt Champion
    wrote on last edited by
    #2

    It's a wrong question to the problem. You don't want to "force" anything. What you want to do is insert an item into the table when a process starts, so focus on doing that. Also, you should use a separate QProcess object for each process you start. The way you use it is not designed to be "fire and forget".

    Here's a sample that doesn't require "forcing" updates:

    for (int i = 0; i<n; ++i)
    {
        auto p = new QProcess();
        connect(p, qOverload<int>(&QProcess::finished), p, &QProcess::deleteLater);
        connect(p, &QProcess::started, [=] {
            auto it = new QTableWidgetItem("text");
            table->insertRow(i);
            table->setItem(i, 0, it);
        });
        p->start("some external pgr called");
    }
    

    You might also want to handle the errorOccurred signal of the process in some way (e.g. add a different item to the table).

    J 1 Reply Last reply
    4
    • Chris KawaC Chris Kawa

      It's a wrong question to the problem. You don't want to "force" anything. What you want to do is insert an item into the table when a process starts, so focus on doing that. Also, you should use a separate QProcess object for each process you start. The way you use it is not designed to be "fire and forget".

      Here's a sample that doesn't require "forcing" updates:

      for (int i = 0; i<n; ++i)
      {
          auto p = new QProcess();
          connect(p, qOverload<int>(&QProcess::finished), p, &QProcess::deleteLater);
          connect(p, &QProcess::started, [=] {
              auto it = new QTableWidgetItem("text");
              table->insertRow(i);
              table->setItem(i, 0, it);
          });
          p->start("some external pgr called");
      }
      

      You might also want to handle the errorOccurred signal of the process in some way (e.g. add a different item to the table).

      J Offline
      J Offline
      jcga
      wrote on last edited by
      #3

      @Chris-Kawa

      Thanks Chris Kawa for your answer. I could not try your suggestions because my version of Qt (5.6.1) apparently do not recognizes qOverload. I'll update it and try.

      mrjjM 1 Reply Last reply
      0
      • J jcga

        @Chris-Kawa

        Thanks Chris Kawa for your answer. I could not try your suggestions because my version of Qt (5.6.1) apparently do not recognizes qOverload. I'll update it and try.

        mrjjM Offline
        mrjjM Offline
        mrjj
        Lifetime Qt Champion
        wrote on last edited by mrjj
        #4

        @jcga said in Refresh display of QTableWidget:

        qOverload

        I thinks its included in 5.7 to help using the new syntax.
        You can just use the old syntax to test.

        https://wiki.qt.io/New_Signal_Slot_Syntax

        1 Reply Last reply
        0
        • Chris KawaC Offline
          Chris KawaC Offline
          Chris Kawa
          Lifetime Qt Champion
          wrote on last edited by
          #5

          qOverload is just a syntax-shortener. You can use the more verbose version if it's not available to you:

          connect(p, static_cast<void(QProcess::*)(int)>(&QProcess::finished), p, &QProcess::deleteLater);
          

          This ugliness is needed because there are two finished signals with different parameters and you need to help compiler choose the right one.
          Hopefully in Qt 6 the overloaded signals will be gone and you'll be able to write just

          connect(p, &QProcess::finished, p, &QProcess::deleteLater);
          
          kshegunovK 1 Reply Last reply
          2
          • Chris KawaC Chris Kawa

            qOverload is just a syntax-shortener. You can use the more verbose version if it's not available to you:

            connect(p, static_cast<void(QProcess::*)(int)>(&QProcess::finished), p, &QProcess::deleteLater);
            

            This ugliness is needed because there are two finished signals with different parameters and you need to help compiler choose the right one.
            Hopefully in Qt 6 the overloaded signals will be gone and you'll be able to write just

            connect(p, &QProcess::finished, p, &QProcess::deleteLater);
            
            kshegunovK Offline
            kshegunovK Offline
            kshegunov
            Moderators
            wrote on last edited by
            #6

            Or directly bypass the cast by explicitly specifying the template arguments, e.g.:

            connect<void(QProcess::*)(int)>(p, &QProcess::finished, p, &QProcess::deleteLater);
            

            Granted it's only marginally shorter, but is a bit more readable in my opinion.

            Read and abide by the Qt Code of Conduct

            1 Reply Last reply
            0
            • Chris KawaC Offline
              Chris KawaC Offline
              Chris Kawa
              Lifetime Qt Champion
              wrote on last edited by
              #7

              @kshegunov To each his own, but without really knowing the template implementation of connect it isn't obvious what the template argument really refers to (at least here, where you've got the same class on sending and receiving end).

              kshegunovK 1 Reply Last reply
              0
              • Chris KawaC Chris Kawa

                @kshegunov To each his own, but without really knowing the template implementation of connect it isn't obvious what the template argument really refers to (at least here, where you've got the same class on sending and receiving end).

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

                Fair enough. But that would be one of the really beautiful things about templates - having a convoluted implementation and terrible binary incompatible interface, wouldn't it ... no wonder the standards committee are pushing them templates so intently ... ;)

                For the record the first template argument refers to the signal prototype, while the second refers to the slot prototype.

                Read and abide by the Qt Code of Conduct

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

                  I tried the solution suggested by Chris Kawa. The program runs correctly, do what it has to do, but the QWidgetTable display is not updated during the for loop, but only after the loop finishes, as before. I think I implemented strictly the code as indicated by Chris, so I do not understand what happens.

                  1 Reply Last reply
                  0
                  • Chris KawaC Offline
                    Chris KawaC Offline
                    Chris Kawa
                    Lifetime Qt Champion
                    wrote on last edited by
                    #10

                    The program runs correctly, do what it has to do, but the QWidgetTable display is not updated during the for loop, but only after the loop finishes, as before.

                    The code I posted wasn't suppose to update inside the loop, because I don't think it really needs to. Body of that loop is almost empty. Enforcing ui update after every iteration would just artificially slow it down. Usually you want to update ui when some state changes. In this case it's when a process is started, and yes, it happens after the execution leaves your code and gets back to the Qt's event loop.

                    There is a way to use your original code and "force" an update, but that's imho a bad design and I won't suggest how to do that unless you sign the fine print saying "I hereby want to willingly shoot myself in the foot".

                    VRoninV 1 Reply Last reply
                    0
                    • Chris KawaC Chris Kawa

                      The program runs correctly, do what it has to do, but the QWidgetTable display is not updated during the for loop, but only after the loop finishes, as before.

                      The code I posted wasn't suppose to update inside the loop, because I don't think it really needs to. Body of that loop is almost empty. Enforcing ui update after every iteration would just artificially slow it down. Usually you want to update ui when some state changes. In this case it's when a process is started, and yes, it happens after the execution leaves your code and gets back to the Qt's event loop.

                      There is a way to use your original code and "force" an update, but that's imho a bad design and I won't suggest how to do that unless you sign the fine print saying "I hereby want to willingly shoot myself in the foot".

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

                      @Chris-Kawa said in Refresh display of QTableWidget:

                      There is a way to use your original code and "force" an update, but that's imho a bad design and I won't suggest how to do that unless you sign the fine print saying "I hereby want to willingly shoot myself in the foot".

                      the way is to add QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); inside the loop but I agree is not the best design

                      "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
                      • J Offline
                        J Offline
                        jcga
                        wrote on last edited by
                        #12

                        Thanks once more for your answers. Let me be a little bit more specific on what I'a trying to do, and why. As indicated in the sample code I provided, my program calls inside a for loop an external program. This exeternal program essentially reads data from a device, format them and save them to files, on file per loop execution. The tablewidget displays information about the file and the data saved. As reading data from the device can be relatively long (tens of seconds to few minutes), I would like the user to have some feedback on the advancement of the process by seeing the rows display progressively on the table. Thats is why I would like that added table rows become visible to the user during the execution of the loop, not only after. Anyway I also tried to add to my widget a QLabel playing the role of a status bar to indicate what the program is currently doing and I have exaclty the same problem, the QLabel do not updated its text inside the loop, but only after the loop is complete.

                        I'll try the solution proposed by VRonin, evec if not "best design", but I'm affraid it can have some undesirable side effects.

                        1 Reply Last reply
                        0
                        • Chris KawaC Offline
                          Chris KawaC Offline
                          Chris Kawa
                          Lifetime Qt Champion
                          wrote on last edited by Chris Kawa
                          #13

                          I wish VRonin haven't suggested that because that's the easy but messy way out. It leads to poor code that doesn't scale. Soon you'll see problems like something that you wouldn' t want to happen during the loop happens because it is processed when some signal fires etc. You'll design locks and flags around the problem, they will keep interfering with each other, you will add more bloat and the code will become unreadable mess. I've seen this all too many times. The problem is in the larger design of that piece of code.

                          You shouldn't do long operations in a loop in the ui thread. The loop should just start the tasks and exit. The tasks can take long time and they should signal you when they are started or done.
                          If the tasks are external programs then it's easy. Just start all the processes and connect to started/finished signals to update your ui to inform the user. If the tasks are some code in your own app that takes time to execute start them in separate threads and signal when they're done (QtConcurrent might be of use to you). There's also a tasking solution - you put tasks into a queue in a loop and resume execution and worker threads pick up the tasks from the queue and signal their progress/state.

                          1 Reply Last reply
                          3
                          • J Offline
                            J Offline
                            jcga
                            wrote on last edited by
                            #14

                            So I have tested VRonin's suggestions. It works, the program reacts as I wanted it to, and for the moment I have not noted any undesirable side-effect, thanks a lot. I would like to tray Chris' suggestion in his last message, but I don't master multithreading programming, so I have not understood how to implement it. If Chris has some time to spent indicating roughly the way to do it (specially, what function to call, or where to start reading the doc), I can try to find the details in the documentation myself.

                            jclaude

                            VRoninV 1 Reply Last reply
                            0
                            • J jcga

                              So I have tested VRonin's suggestions. It works, the program reacts as I wanted it to, and for the moment I have not noted any undesirable side-effect, thanks a lot. I would like to tray Chris' suggestion in his last message, but I don't master multithreading programming, so I have not understood how to implement it. If Chris has some time to spent indicating roughly the way to do it (specially, what function to call, or where to start reading the doc), I can try to find the details in the documentation myself.

                              jclaude

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

                              @jcga This https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ should be a good place to start

                              "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
                              0

                              • Login

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