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. How to efficiently display almost real-time text (logging) without freezing an ui?

How to efficiently display almost real-time text (logging) without freezing an ui?

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 4 Posters 9.4k 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.
  • F Offline
    F Offline
    flashmozzg
    wrote on last edited by flashmozzg
    #1

    Currently I'm using QPlainTextEdit with addPlainText but it doesn't work really well.
    For example if I have something like

    for (int i = 0; i < n; i++) {
        display i in textedit
    }
    

    For n < 1e5 it work ok. But for>1e5 it starts freezing the UI. I tried adding some sort of buffering to the logging widget: i.e. store incoming strings in a QQueue and each 250ms or so (using timer) display them all at once, but it didn't solve the problem. As well as just concatenating strings together instead of a queue.
    Also, I tried displaying only fixed amount of messages(about 50) per 200ms but that, although improved situation a bit, still didn't solve the issue completely.
    The problem appears to be in appendPlainText invocation which always freezes GUI for a bit.
    (btw, I tried replacing it with insertPlainText but didn't see much difference and doc didn't help to clear up what the difference is).

    A 1 Reply Last reply
    0
    • F flashmozzg

      Currently I'm using QPlainTextEdit with addPlainText but it doesn't work really well.
      For example if I have something like

      for (int i = 0; i < n; i++) {
          display i in textedit
      }
      

      For n < 1e5 it work ok. But for>1e5 it starts freezing the UI. I tried adding some sort of buffering to the logging widget: i.e. store incoming strings in a QQueue and each 250ms or so (using timer) display them all at once, but it didn't solve the problem. As well as just concatenating strings together instead of a queue.
      Also, I tried displaying only fixed amount of messages(about 50) per 200ms but that, although improved situation a bit, still didn't solve the issue completely.
      The problem appears to be in appendPlainText invocation which always freezes GUI for a bit.
      (btw, I tried replacing it with insertPlainText but didn't see much difference and doc didn't help to clear up what the difference is).

      A Offline
      A Offline
      ambershark
      wrote on last edited by
      #2

      @flashmozzg The problem here is constantly updating the textedit without allowing the system to do anything else (because you're in the for loop).

      So basically, build up the data you want to display and update the text edit once, like so:

      QString myStr;
      for (auto i=0;i<n;++i)
      {
         myStr += myNewData;
      }
      
      textedit->setPlainText(myStr);
      

      If you need to constantly deliver updates then you should do it via a signal/slot type mechanism and not in a for loop like that. Any loop will hang a thread until it's done. So if you had to have the loop you would again build the data in a loop outside the GUI thread, and deliver the updates via a signal to your GUI thread that updates the textedit.

      Also if you make the data in a textedit huge it will not perform well. You may need to use a faster view to display it.

      My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

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

        Hi,

        To add to @ambershark, one alternative could be to use a QListView and a QStringListModel rather than a QTextEdit. That way you optimise things a bit more for displaying and scrolling.

        Hope it helps

        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
        1
        • A ambershark

          @flashmozzg The problem here is constantly updating the textedit without allowing the system to do anything else (because you're in the for loop).

          So basically, build up the data you want to display and update the text edit once, like so:

          QString myStr;
          for (auto i=0;i<n;++i)
          {
             myStr += myNewData;
          }
          
          textedit->setPlainText(myStr);
          

          If you need to constantly deliver updates then you should do it via a signal/slot type mechanism and not in a for loop like that. Any loop will hang a thread until it's done. So if you had to have the loop you would again build the data in a loop outside the GUI thread, and deliver the updates via a signal to your GUI thread that updates the textedit.

          Also if you make the data in a textedit huge it will not perform well. You may need to use a faster view to display it.

          F Offline
          F Offline
          flashmozzg
          wrote on last edited by
          #4

          @ambershark
          Sorry, I realize that my example was a bit misleading.
          The loop is happening in another (non-GUI) thread and it sends a signal to display some text (like text representation of i) in the QPlainTextEdit.

          Btw, I tried keeping a queue of incoming messages and then show them one by one, or just appending everything to one big string and then showing it, but I didn't really see much performance difference.

          Anyway, I was somewhat able to overcome this annoyance by finding the right values n and m for the number of msgs (n) in the queue processed every m milliseconds. That way at least it doesn't freeze the gui, though the backlog becomes massive.

          A 1 Reply Last reply
          0
          • F flashmozzg

            @ambershark
            Sorry, I realize that my example was a bit misleading.
            The loop is happening in another (non-GUI) thread and it sends a signal to display some text (like text representation of i) in the QPlainTextEdit.

            Btw, I tried keeping a queue of incoming messages and then show them one by one, or just appending everything to one big string and then showing it, but I didn't really see much performance difference.

            Anyway, I was somewhat able to overcome this annoyance by finding the right values n and m for the number of msgs (n) in the queue processed every m milliseconds. That way at least it doesn't freeze the gui, though the backlog becomes massive.

            A Offline
            A Offline
            ambershark
            wrote on last edited by
            #5

            @flashmozzg What kind of data is this? That seems like a lot of data to be sending to a GUI control. They really aren't designed for that level of updates.

            Like @SGaist said though you need to use a more optimized widget than a QTextEdit. You may even need to look into using QGraphicsView or something to utilize the graphics card for rendering on a component like that. However I would just do the view/model and control what the user actually sees. That should be nice and fast, especially compared to a QTextEdit which was never intended for the use you using it for.

            My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

            F 1 Reply Last reply
            0
            • A ambershark

              @flashmozzg What kind of data is this? That seems like a lot of data to be sending to a GUI control. They really aren't designed for that level of updates.

              Like @SGaist said though you need to use a more optimized widget than a QTextEdit. You may even need to look into using QGraphicsView or something to utilize the graphics card for rendering on a component like that. However I would just do the view/model and control what the user actually sees. That should be nice and fast, especially compared to a QTextEdit which was never intended for the use you using it for.

              F Offline
              F Offline
              flashmozzg
              wrote on last edited by flashmozzg
              #6

              @ambershark said in How to efficiently display almost real-time text (logging) without freezing an ui?:

              What kind of data is this? That seems like a lot of data to be sending to a GUI control. They really aren't designed for that level of updates.

              Just some logging from some interpretation/evaluation running in another thread.
              QPlainTexEdit seems to be barely enough with new added changes so I'll keep that for now, it's rather simple for what it's worth and I was able to push about 200 messages every 50 milliseconds, so it's OK.for now. The problem was that some pathological case like fast evaluation of while(true) {send signal to print something} would make application unresponsive and would require a restart, potentially losing some data. Now it's enough for the most common case.
              Though I'd still would like to know if there are some easy performance optimizations without switching to the whole new and different model.

              jsulmJ 1 Reply Last reply
              0
              • F flashmozzg

                @ambershark said in How to efficiently display almost real-time text (logging) without freezing an ui?:

                What kind of data is this? That seems like a lot of data to be sending to a GUI control. They really aren't designed for that level of updates.

                Just some logging from some interpretation/evaluation running in another thread.
                QPlainTexEdit seems to be barely enough with new added changes so I'll keep that for now, it's rather simple for what it's worth and I was able to push about 200 messages every 50 milliseconds, so it's OK.for now. The problem was that some pathological case like fast evaluation of while(true) {send signal to print something} would make application unresponsive and would require a restart, potentially losing some data. Now it's enough for the most common case.
                Though I'd still would like to know if there are some easy performance optimizations without switching to the whole new and different model.

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

                @flashmozzg One optimization would be to buffer the log messages and when the buffer reaches some defined size then send it to the QPlainTextEdit. In other words: do not send each and every message but groups of messages. I don't think any human would recognize any difference at that speed.

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

                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