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. Qt 2D Drawing?
Forum Updated to NodeBB v4.3 + New Features

Qt 2D Drawing?

Scheduled Pinned Locked Moved General and Desktop
18 Posts 5 Posters 7.8k Views 4 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.
  • P Offline
    P Offline
    Pippin
    wrote on last edited by
    #1

    Hello Qt community,

    I would like to use Qt for 2D drawing, but I'm not sure which tutorials I should use. (They all look so, so verbose.)

    Basically, my project consists in drawing ~200 sprites at every frame. I used to do that with the SFML library, so for those of you who are familiar with this library, I have no idea if Qt works similarly or quite differently.

    1. Which class is equivalent to SFML's sf::Sprite ? I can't think of anything better than drawing a Qimage for the time being.

    2. Should I draw all my QImages on a QMainWindow at every frame (SFML-style), or should I use a QPäinter to paint all my QImages on another QImage, then draw the resulting QImage on a QMainWindow?

    Thanks in advance for your help.

    1 Reply Last reply
    0
    • L Offline
      L Offline
      LuGRU
      wrote on last edited by
      #2

      This all depends that You need, is there any kind of interaction with those sprites etc.
      Few approaches can be choses:

      1. QImage as drawing buffer - use QPainter( &QImage) and draw in any function then i.e. call update (if base is QWidget) and in QWidget::paineEvent() draw that image (convert to pixmap first to gain some speed)
      2. Draw directly in paintEvent
      3. use QGraphiscScene approach - scene support several predefined base object types, like pixmaps (images) via QGraphicsPixmapItem, rectangle, paths, etc.

      All of above solution can also be hw accelerated i.e. by applying OGL widget to the Scene, using shaders and bind drawing buffer image,

      But basically drawing 200sprites at same time is not good approach. Use either scene (see graphics view framework http://doc.qt.io/qt-5/graphicsview.html) or write You own method that will update only portion of image buffer (that what has changed) and display it.

      Chip example with 40k sprites: http://doc.qt.io/qt-5/qtwidgets-graphicsview-chip-example.html

      Another approach would be to go with QtQuick - with basically is GraphicsScene + opengl + java script like object declaration.

      1 Reply Last reply
      0
      • P Offline
        P Offline
        Pippin
        wrote on last edited by Pippin
        #3

        Are you saying that drawing 200 QImages directly on the window (2), and painting them all on a QImage through a QPainter, then drawing the result on the window (1), take approximately the same amount of time?

        Basically I would need to be able to scale the QImages I draw (horizontally, vertically) and rotate them. What's the most convenient drawing method for this?

        Also, what's the most convenient method for drawing straight lines?

        Edit: after looking through the descriptions of QPainter and QPixmap, I think I'm going to use the 1st method you listed, with these classes.

        L 1 Reply Last reply
        0
        • JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by
          #4

          @LuGRU said:

          1. QImage as drawing buffer - use QPainter( &QImage) and draw in any function then i.e. call update (if base is QWidget) and in QWidget::paineEvent() draw that image (convert to pixmap first to gain some speed)
          2. Draw directly in paintEvent
          3. use QGraphiscScene approach - scene support several predefined base object types, like pixmaps (images) via QGraphicsPixmapItem, rectangle, paths, etc.

          Option #3 is specifically designed to support drawing many 2D sprites. It also has built-in support for linear transformations (scaling, rotation. etc.)

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          P 1 Reply Last reply
          0
          • P Pippin

            Are you saying that drawing 200 QImages directly on the window (2), and painting them all on a QImage through a QPainter, then drawing the result on the window (1), take approximately the same amount of time?

            Basically I would need to be able to scale the QImages I draw (horizontally, vertically) and rotate them. What's the most convenient drawing method for this?

            Also, what's the most convenient method for drawing straight lines?

            Edit: after looking through the descriptions of QPainter and QPixmap, I think I'm going to use the 1st method you listed, with these classes.

            L Offline
            L Offline
            LuGRU
            wrote on last edited by
            #5

            @Pippin said:

            Are you saying that drawing 200 QImages directly on the window (2), and painting them all on a QImage through a QPainter, then drawing the result on the window (1), take approximately the same amount of time?

            NO it will take longer, but my point here is that:
            create, only once, buffer that holds 200 drawn images - i.e. with all transformations, scalings, etc. Then draw only that buffer image on each paint event, so time looks like this:
            paintEvent -> initial iteration - draw 200 image onto buffer - draw buffer
            paintEvent -> n'th iteration - draw only buffer image
            paintEvent -> n'th + 1 iteration - draw only buffer image
            ...

            Plus You can offload those drawings into separate threads. If those 200 iamges don't use transformation, then prepare buffer image of size that will holds all those images, then start thread and in thread load and then copy image data into buffer image.

            Basically I would need to be able to scale the QImages I draw (horizontally, vertically) and rotate them. What's the most convenient drawing method for this?

            Also, what's the most convenient method for drawing straight lines?

            Edit: after looking through the descriptions of QPainter and QPixmap, I think I'm going to use the 1st method you listed, with these classes.

            QGraphics Framework is for this. See this http://doc.qt.io/qt-4.8/graphicsview.html and 40k chip example: http://doc.qt.io/qt-5/qtwidgets-graphicsview-chip-example.html

            1 Reply Last reply
            0
            • JKSHJ JKSH

              @LuGRU said:

              1. QImage as drawing buffer - use QPainter( &QImage) and draw in any function then i.e. call update (if base is QWidget) and in QWidget::paineEvent() draw that image (convert to pixmap first to gain some speed)
              2. Draw directly in paintEvent
              3. use QGraphiscScene approach - scene support several predefined base object types, like pixmaps (images) via QGraphicsPixmapItem, rectangle, paths, etc.

              Option #3 is specifically designed to support drawing many 2D sprites. It also has built-in support for linear transformations (scaling, rotation. etc.)

              P Offline
              P Offline
              Pippin
              wrote on last edited by
              #6

              @JKSH

              Are you sure, because if you browse QGraphicsScene's page, CTRL+F "QPixmap" doesn't have that many results, also CTRL+F "rotat" has no results :S

              Basically, if you have an std::vector of 10 QPixmaps, an std::vector of 10 angles, an std::vector of 10 horizontal scales, and an std::vector of 10 positions, how would you draw these 10 QPixmaps on the QGraphicsScene, according to the other std::vectors I listed?

              JKSHJ 1 Reply Last reply
              0
              • timdayT Offline
                timdayT Offline
                timday
                wrote on last edited by
                #7

                I see a lot of complicated sounding stuff being talked about here.

                To what extent can QML/QSG meet your needs? OpenGL-powered QSG provides all the rendering power you need; if a pure QML-approach ran out of steam for you, I suspect it'd be because the javascript for whatever sprite behaviour is needed becomes too complex and slow, not the rendering. But more complicated behaviour could be moved into C++ without leaving QML & QSG behind, using the usual QML-C++ interop (properties, invokables etc).

                Complete qmlscene runnable example below (placeholder icons courtesy of lorempixel):

                import QtQuick 2.2
                
                // Silly QML sprites demo; 200 randomly positioned/moving sprites
                // Sprites toggle color when clicked
                
                Rectangle {
                  id: main
                  width: 1024
                  height: 768
                  color: 'black'
                
                  Timer {
                    id: ticker
                    interval: 1000.0/60.0
                    running: true
                    repeat: true
                  }
                
                  Repeater {
                
                    // Number of sprites
                    // Can go up to 1000 happily enough on an old Core2Duo lappy (Intel graphics)
                    // More modern HW probably much more.
                    model: 200
                
                    Item {
                      id: sprite
                
                      x: ox-0.5*width
                      y: oy-0.5*width
                      width: 64
                      height: 64
                      rotation: Math.random()*360.0
                
                      property real ox: main.width*Math.random()
                      property real oy: main.height*Math.random()
                      property real vx: -1.0+2.0*Math.random()
                      property real vy: -1.0+2.0*Math.random()
                      property real vr: -1.0+2.0*Math.random()
                
                      Image {
                        anchors.fill: parent
                        opacity: 0.75
                        source: 'http://www.lorempixum.com/64/64/cats/'+((1+index%10).toString())
                        smooth: true
                      }
                
                      Rectangle {
                        id: highlight
                        anchors.fill: parent
                        visible: opacity!=0.0
                        opacity: 0.0
                        color: 'red'
                        Behavior on opacity {NumberAnimation {duration: 500}}
                      }
                
                      MouseArea {
                        anchors.fill: parent   
                        onClicked: highlight.opacity=1.0-highlight.opacity
                      }
                
                      Connections {
                        target: ticker
                        onTriggered: {
                          ox+=vx
                          if (ox<0.0) {ox=0.0;vx=-vx;} else if (ox>main.width) {ox=main.width;vx=-vx;}
                          oy+=vy
                          if (oy<0.0) {oy=0.0;vy=-vy;} else if (oy>main.height) {oy=main.height;vy=-vy;}
                          rotation+=vr
                        }
                      }
                    }
                  }
                }
                
                1 Reply Last reply
                0
                • P Pippin

                  @JKSH

                  Are you sure, because if you browse QGraphicsScene's page, CTRL+F "QPixmap" doesn't have that many results, also CTRL+F "rotat" has no results :S

                  Basically, if you have an std::vector of 10 QPixmaps, an std::vector of 10 angles, an std::vector of 10 horizontal scales, and an std::vector of 10 positions, how would you draw these 10 QPixmaps on the QGraphicsScene, according to the other std::vectors I listed?

                  JKSHJ Offline
                  JKSHJ Offline
                  JKSH
                  Moderators
                  wrote on last edited by JKSH
                  #8

                  @Pippin said:

                  Are you sure, because if you browse QGraphicsScene's page, CTRL+F "QPixmap" doesn't have that many results, also CTRL+F "rotat" has no results :S

                  Yes, I'm sure.

                  You don't rotate the QGraphicsScene itself. Instead, you rotate the individual items.

                  Basically, if you have an std::vector of 10 QPixmaps, an std::vector of 10 angles, an std::vector of 10 horizontal scales, and an std::vector of 10 positions, how would you draw these 10 QPixmaps on the QGraphicsScene, according to the other std::vectors I listed?

                  1. Wrap each QPixmap inside a QGraphicsPixmapItem (this is a subclass of QGraphicsItem)
                  2. Add your QGraphicsPixmapItems to your QGraphicsScene
                  3. Rotate your items using QGraphicsItem::rotate()
                  4. Move your items using QGraphicsItem::setPos()
                  5. Show your QGraphicsScene using a QGraphicsView

                  EDIT: Note that there are many ways to do what you want in Qt. @LuGRU showed you 3, and @timday showed you another. The QGraphicsScene option requires the least amount of coding, but might not offer the best performance. I suggest you try it first, to familiarize yourself with Qt. If its performance is not satisfactory, then try the other options. Good luck.

                  Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                  1 Reply Last reply
                  1
                  • L Offline
                    L Offline
                    LuGRU
                    wrote on last edited by
                    #9

                    To sum up my post I will share info about performance of Graphics Framework in Qt on project that I'm involved with.
                    Running 25 video items - custom libVlc base QGraphicsItems - that plays videos of 624x352 at 23.976fp hits 50% CPU on i7-4770 in debug mode, all items playback is smooth.
                    For around 230 items, around 1/5 is text with high aliasing rest is, pixmaps, QGraphicsPathItem - panning and zooming view when all those objects are visible - all objects do have transparency - is not smooth, I would say 15fps, going to OGL - smooth.

                    So drawing 200 sprites shouldn't be a big of a problem.

                    Maximizing performance:
                    QtQuick 1 - deprecated - used OGL direct mode - each time frame was repainted scene was uploaded to GPU
                    QtQuick 2 - currently used - uses VBO / IBO - vertex / image buffer object's - sending to GPU new data only when data do change - decrease bandwidth usage increase performance.
                    QGraphicsView + QGLWidget - I'm not sure but suspecting direct OGL mode, this of course can be customized to use VBO / IBO for item data

                    1 Reply Last reply
                    0
                    • P Offline
                      P Offline
                      Pippin
                      wrote on last edited by
                      #10

                      @timday Thank you for your reply but I'm afraid I don't know most of the things you're talking about (QML, QSG...) :S I also don't know in what language the code you wrote is :S

                      @JKSH Thank you for your reply, the point is, I'm going to completely transform my SMFL project into a Qt project (because I can't make Qt and SFML efficiently work together). This is going to take weeks, if not months, so I'd rather not try out each method then choose which one is best. I'm gathering all the information I can find to choose now. Basically, my project draws (rotable, scalable) QPixmaps onto a window, as well as (movable) QPushButtons. These are the two main things it has to draw at each frame. There are other things, like colored circles, rectangles or numbers, but that shouldn't be a problem I think.

                      You said that QGraphicsScene stuff may not offer the best performance, but you also said that it was coded for these things. So, what do you think could offer nice performance?

                      @LuGRU Thank you for your reply, I'm not at all familiar with QtQuick though. I'm not familiar with VBO/IBO either. Actually, I don't even use Qt Creator when I'm coding Qt things. I'm using Ubuntu and am compiling everything through the terminal (qmake, make, ./run).

                      timdayT JKSHJ 2 Replies Last reply
                      0
                      • P Pippin

                        @timday Thank you for your reply but I'm afraid I don't know most of the things you're talking about (QML, QSG...) :S I also don't know in what language the code you wrote is :S

                        @JKSH Thank you for your reply, the point is, I'm going to completely transform my SMFL project into a Qt project (because I can't make Qt and SFML efficiently work together). This is going to take weeks, if not months, so I'd rather not try out each method then choose which one is best. I'm gathering all the information I can find to choose now. Basically, my project draws (rotable, scalable) QPixmaps onto a window, as well as (movable) QPushButtons. These are the two main things it has to draw at each frame. There are other things, like colored circles, rectangles or numbers, but that shouldn't be a problem I think.

                        You said that QGraphicsScene stuff may not offer the best performance, but you also said that it was coded for these things. So, what do you think could offer nice performance?

                        @LuGRU Thank you for your reply, I'm not at all familiar with QtQuick though. I'm not familiar with VBO/IBO either. Actually, I don't even use Qt Creator when I'm coding Qt things. I'm using Ubuntu and am compiling everything through the terminal (qmake, make, ./run).

                        timdayT Offline
                        timdayT Offline
                        timday
                        wrote on last edited by
                        #11

                        @Pippin The language is QML which supposedly stands for Qt Modelling Language or Qt Meta Language. It's part of the QtQuick part of Qt. Basically, instead of writing acres of C++ widget plumbing code, it lets you express UI declaratively with an elegant domain specific language (and the odd bit of javascript where imperative style is needed) and then the only bit of C++ you need is something to create a QQuickView to interpret the QML (and for convenience, the Qt SDKs provide a qmlscene tool which does exactly this). You're missing out on an (increasingly) important - and one of the best - parts of Qt if you're not familiar with QtQuick, IMHO. What sets QtQuick apart from other rapid application development tools is the ease of integration of C++ components into the QML (enabled by the moc-generated metadata) when some heavy lifting is needed (whether specialized OpenGL rendering, or intensive compute which would be too slow in javascript and really needs native code's power).

                        1 Reply Last reply
                        0
                        • P Pippin

                          @timday Thank you for your reply but I'm afraid I don't know most of the things you're talking about (QML, QSG...) :S I also don't know in what language the code you wrote is :S

                          @JKSH Thank you for your reply, the point is, I'm going to completely transform my SMFL project into a Qt project (because I can't make Qt and SFML efficiently work together). This is going to take weeks, if not months, so I'd rather not try out each method then choose which one is best. I'm gathering all the information I can find to choose now. Basically, my project draws (rotable, scalable) QPixmaps onto a window, as well as (movable) QPushButtons. These are the two main things it has to draw at each frame. There are other things, like colored circles, rectangles or numbers, but that shouldn't be a problem I think.

                          You said that QGraphicsScene stuff may not offer the best performance, but you also said that it was coded for these things. So, what do you think could offer nice performance?

                          @LuGRU Thank you for your reply, I'm not at all familiar with QtQuick though. I'm not familiar with VBO/IBO either. Actually, I don't even use Qt Creator when I'm coding Qt things. I'm using Ubuntu and am compiling everything through the terminal (qmake, make, ./run).

                          JKSHJ Offline
                          JKSHJ Offline
                          JKSH
                          Moderators
                          wrote on last edited by JKSH
                          #12

                          @Pippin said:

                          I'm going to completely transform my SMFL project into a Qt project (because I can't make Qt and SFML efficiently work together). This is going to take weeks, if not months, so I'd rather not try out each method then choose which one is best. I'm gathering all the information I can find to choose now.

                          Before you port any large project from one framework to another, it's always wise to spend a few days trying out your target framework. This applies to all frameworks, not just Qt.

                          Follow some tutorials; write a dummy program that animates 200 sprites, using similar sizes and frame rates as your final program. Does it perform well enough? If not, go try a different framework. But if your dummy program performs well enough, make it animate 400 sprites -- if it still works well, then you're fully confident it can handle your final program.

                          When trying to work out what's "best", you also need to consider the effort required to use the technology vs. the benefits you gain.

                          Basically, my project draws (rotable, scalable) QPixmaps onto a window, as well as (movable) QPushButtons. These are the two main things it has to draw at each frame. There are other things, like colored circles, rectangles or numbers, but that shouldn't be a problem I think.

                          What frame rate do you want? Any special effects? How does your user interact with these objects?

                          Note: In the Graphics View Framework or QML/Qt Quick, you don't need to manually manage each frame. Just place your items, tell them how to move, and Qt will take care of the frames for you.

                          You said that QGraphicsScene stuff may not offer the best performance, but you also said that it was coded for these things. So, what do you think could offer nice performance?

                          Yes, the Graphics View Framework was designed for handling lots of 2D sprites. The API is very easy to use, and allows you to do animations, scaling, rotations. In contrast, QPainter was not designed for animating sprites (even though it can do so, if you're persistent). Your code will become a nightmare to maintain; don't use QPainter for your project.

                          The Graphics View Framework performs best when your sprites are made of lines, polygons, arcs, texts, etc. Using custom images/pixmaps will incur an overhead. How much overhead? I don't know, I've never measured. It also really depends on how big your sprites are and what you want them to do -- I'm just giving you the insight you need to measure it yourself. (Alternatively, hire a consultant)

                          QML/Qt Quick was designed for creating fluid, modern, mobile-phone-style GUIs. It's a much newer technology than Graphics View, so it performs better in some cases, thanks to GPU acceleration. Does it perform better for your project? I don't know, I've never measured. Again, it's up to you to measure it if you want to know.

                          The bottom line is: the Graphics View Framework is definitely easier to use, but QML/Qt Quick might perform better (no guarantees), and it requires you to learn a new language. If it were my project, I'd do a quick test on the Graphics View Framework first. If that's not good enough, try QML/Qt Quick. If that's still not good enough, use raw OpenGL. (I'm reasonably confident that Graphics View meets your requirements though)

                          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                          1 Reply Last reply
                          1
                          • P Offline
                            P Offline
                            Pippin
                            wrote on last edited by
                            #13

                            Okay thanks everyone! I'll give the Graphics View Framework a try then. About scaling though, may I ask how one can scale an item horizontally or vertically (not both) ? QGraphicsItem::setScale() seems to scale both dimensions.

                            1 Reply Last reply
                            0
                            • L Offline
                              L Offline
                              LuGRU
                              wrote on last edited by
                              #14

                              Use transformation i.e.:

                                          QGraphicsItem item;
                                          item.setTransform( QTransform().scale( 1., 0.));
                              

                              should do the trick.

                              P 1 Reply Last reply
                              0
                              • L LuGRU

                                Use transformation i.e.:

                                            QGraphicsItem item;
                                            item.setTransform( QTransform().scale( 1., 0.));
                                

                                should do the trick.

                                P Offline
                                P Offline
                                Pippin
                                wrote on last edited by
                                #15

                                @LuGRU Thanks for the tip.

                                Now, about OpenGL acceleration:

                                To enable OpenGL support, you can set a QGLWidget as the viewport by calling QGraphicsView::setViewport().

                                Source: http://doc.qt.io/qt-5/graphicsview.html

                                I'm not sure I understand this correctly. To trigger OpenGL acceleration, I would only have to do something like that?

                                QGLWidget foo;
                                MyQGraphicsView.setViewport(&foo);
                                

                                Or is it more complicated than this?

                                1 Reply Last reply
                                0
                                • P Offline
                                  P Offline
                                  Pippin
                                  wrote on last edited by
                                  #16

                                  Also, how can I re-arrange the order of the QGraphicsItems in my QGraphicsScene? I couldn't find the answer to this question in QGraphicsScene's page, and it's quite important to me. Sorry for making this thread last forever.

                                  mrjjM 1 Reply Last reply
                                  0
                                  • P Pippin

                                    Also, how can I re-arrange the order of the QGraphicsItems in my QGraphicsScene? I couldn't find the answer to this question in QGraphicsScene's page, and it's quite important to me. Sorry for making this thread last forever.

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

                                    @Pippin
                                    Hi
                                    you mean zorder ?
                                    setZValue, isObscured and isObscuredBy
                                    And as side note.
                                    Did you check out the 40000 sample ?

                                    1 Reply Last reply
                                    0
                                    • L Offline
                                      L Offline
                                      LuGRU
                                      wrote on last edited by
                                      #18

                                      @Pippin
                                      OGL - Yes, just make sure QGlWidget don't go out of the scope.
                                      You can also fiddle with ogl format settings, write You own shaders - i.e. as part of pain() in QGraphicsItem etc.

                                      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