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 update only some parts of a painter
QtWS25 Last Chance

How to update only some parts of a painter

Scheduled Pinned Locked Moved Unsolved General and Desktop
qpainterpainteventupdate
8 Posts 4 Posters 5.6k Views
  • 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.
  • P Offline
    P Offline
    Peehay
    wrote on last edited by Peehay
    #1

    Hello,

    I'm developing a music software, and I have some troubles in the part where a music sheet is displayed and read.
    The sheet is designed by a QPainter, which updates itself with a paintEvent each some milliseconds (using a QBasicTimer), depending on the bpm (120 bpm will give a 2 ms update). A cursor goes 1 pixel further each 2 ms in this case. So you'll understand that the painter updates itself very frequently, and I can watch the limits when I draw some Pixmap (for the notes) with the painter : some updates are not considered and so there is a gap between cursor position and the timer (whereas it absolutly must match).

    Before, I drew points instead of Pixmaps, so I guess the problem comes from them.

    My question is : how can I "freeze" some parts of the painter, for example Pixmaps that don't need to be updated every 2 ms ? (unless the player stops the music sheet, everything's erased).
    I found the region() function that allow to update only a region, but in my case I especially need to update the cursor (changing its position during each update), and sometimes draw Pixmaps in the painter that will be left until the end of the music.

    I'm available for further explanation.

    Thanks you very much!

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

      Hi and welcome to devnet,

      Not a direct answer but rather than repainting everything why not have your music sheet completely drawn and just move it as needed ?

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

      P 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi and welcome to devnet,

        Not a direct answer but rather than repainting everything why not have your music sheet completely drawn and just move it as needed ?

        P Offline
        P Offline
        Peehay
        wrote on last edited by
        #3

        @SGaist In fact there is a sequence to play in a continuous loop and each loop make a new sheet appear, so the sheet is not frozen all the time
        I'm looking for a way to tell Qt "when update(), only update these parts, or don't reload this part until I say so" or something like that, but I didn't manage to find a way in the doc ...

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

          You could create a QPainter that draws to a QPixmap. You can then update it at any rate you want and any parts of it you want. You would then draw that whole pixmap in a paint event (a single drawPixmap should be pretty fast as it's just a blit).

          But give your updates a little more thought. The paintEvent is not gonna happen every 2ms no matter what you do. Typical displays tick at 60Hz which means a paintEvent every ~16ms. You can't go lower than the display's refresh rate. Using the method above you could update parts of the pixmap every 2ms and only do a blit at the display's rate in the paint event with the current state of it.

          P 1 Reply Last reply
          0
          • H Offline
            H Offline
            hamer
            wrote on last edited by
            #5

            Isn't is possible to redraw just a region ("dirty region")?
            Another option would be to split your design into multiple widgets/elements. The frequent drawing functions are performed on the top element.

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

              By default Qt clears the background before you draw. You can avoid this by setting the WA_NoSystemBackground or WA_OpaquePaintEvent attribute on the widget but this usually entails ugly artifacts to deal with. Using a QPixmap as a "back buffer" is much cleaner solution.

              1 Reply Last reply
              0
              • Chris KawaC Chris Kawa

                You could create a QPainter that draws to a QPixmap. You can then update it at any rate you want and any parts of it you want. You would then draw that whole pixmap in a paint event (a single drawPixmap should be pretty fast as it's just a blit).

                But give your updates a little more thought. The paintEvent is not gonna happen every 2ms no matter what you do. Typical displays tick at 60Hz which means a paintEvent every ~16ms. You can't go lower than the display's refresh rate. Using the method above you could update parts of the pixmap every 2ms and only do a blit at the display's rate in the paint event with the current state of it.

                P Offline
                P Offline
                Peehay
                wrote on last edited by
                #7

                @Chris-Kawa said:

                You could create a QPainter that draws to a QPixmap. You can then update it at any rate you want and any parts of it you want. You would then draw that whole pixmap in a paint event (a single drawPixmap should be pretty fast as it's just a blit).

                That's a good idea, I'll try it and give you feedback, thanks.

                @Chris-Kawa said:

                But give your updates a little more thought. The paintEvent is not gonna happen every 2ms no matter what you do. Typical displays tick at 60Hz which means a paintEvent every ~16ms. You can't go lower than the display's refresh rate. Using the method above you could update parts of the pixmap every 2ms and only do a blit at the display's rate in the paint event with the current state of it.

                I understand that 2ms is to fast. This speed is due to the cursor that moves 1 pixel further every 2 ms (to follow the play on the sheet), so if I prefer 16ms, that will make the cursor move 8 pixels each 16ms, which is maybe too jolting to see ... But anyway it concerns only the cursor among all objects on the sheet

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

                  @Peehay said:

                  so if I prefer 16ms, that will make the cursor move 8 pixels each 16ms, which is maybe too jolting to see ...

                  It's not a question of preference. It's a hardware constraint. paintEvent won't happen more often that the hardware allows. It's not that you shouldn't update more often. It's physically impossible (unless you've got a high-frequency display, which very few people do).

                  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