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. QGraphicsView render issues when scaling

QGraphicsView render issues when scaling

Scheduled Pinned Locked Moved General and Desktop
17 Posts 4 Posters 7.3k 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.
  • E Offline
    E Offline
    euchkatzl
    wrote on last edited by
    #2

    Don't know if this is really the solution.
    But you can try to use qreal instead of int with your screen variables

    @qreal screenWidth = 640;
    qreal screenHeight = 480;@

    Using integer values will cause that in that line :
    @setFixedSize(screenWidth*_scaleFactor, screenHeight*_scaleFactor);@
    values will be casted to integer values.

    1 Reply Last reply
    0
    • A Offline
      A Offline
      Asperamanca
      wrote on last edited by
      #3

      Can you post your painting code?

      1 Reply Last reply
      0
      • T Offline
        T Offline
        Tectu
        wrote on last edited by
        #4

        @euchkatzl: I casted the values as you suggested but that didn't make the issue go away. And from my understanding they should if anything be casted to a qreal anyway as this is the type which provides more accuracy than the integer.

        @asperamanca: Here's my full paint() routine for the slider that you can see in the images above: http://paste.ugfx.org/show/3eefb77194

        1 Reply Last reply
        0
        • R Offline
          R Offline
          Rondog
          wrote on last edited by
          #5

          You should check the member functions (this->rect() in particular). This probably returns QRect and not QRectF. I can't tell by looking at the code.

          @
          // Create the active area rectangle
          QRectF activeRect = rect();
          activeRect.setX(rectanglePen.width());
          activeRect.setY(rectanglePen.width());
          activeRect.setHeight(rect().height() - rectanglePen.width());
          activeRect.setWidth(knobPos);
          @

          Integer rounding (or lack thereof) will cause this kind of problem.

          1 Reply Last reply
          0
          • T Offline
            T Offline
            Tectu
            wrote on last edited by
            #6

            Thank you very much for your suggestion. My UGfxSlider is derived from QGraphicsRectItem. QGraphicsRectItem::rect() returns a QRectF.

            I have checked the other stuff as well and everything looks fine from that point of view.

            I don't understand why this only happens after setting the scale factor etc. as shown above. The default scale factor is 1.0 and when I don't change it it is fine. But when I manually set it to 1.0 it shows the problems.

            1 Reply Last reply
            0
            • E Offline
              E Offline
              euchkatzl
              wrote on last edited by
              #7

              Could you try to use use widthF of QPen instead of width.

              http://doc-snapshot.qt-project.org/qt5-5.4/qpen.html#widthF

              1 Reply Last reply
              0
              • T Offline
                T Offline
                Tectu
                wrote on last edited by
                #8

                Thank you very much for your suggestion. I have modified the code to use QPen::widthF() but the result is exactly the same.
                @
                QRectF activeRect = rect();
                activeRect.setX(rectanglePen.widthF());
                activeRect.setY(rectanglePen.widthF());
                activeRect.setHeight(rect().height() - rectanglePen.widthF());
                activeRect.setWidth((qreal)knobPos);
                @
                Any other ideas? :/

                1 Reply Last reply
                0
                • E Offline
                  E Offline
                  euchkatzl
                  wrote on last edited by
                  #9

                  Try this in your paint and look if there are still problems. That code works for me. It a simplified version of yours without text an knob.

                  When it works as aspected you could use it to fix your code. I think there a several problems with pen width handling.

                  @painter->setRenderHint(QPainter::Antialiasing,true);
                  painter->save();
                  QPen rectanglePen;
                  rectanglePen.setColor(Qt::blue);
                  rectanglePen.setWidthF(1.0);
                  rectanglePen.setJoinStyle(Qt::MiterJoin);
                  rectanglePen.setCapStyle(Qt::FlatCap);

                  QBrush rectangleBrush;
                  rectangleBrush.setStyle(Qt::SolidPattern);
                  rectangleBrush.setColor(Qt::red);

                  painter->setPen(QPen(Qt::blue,1.0));
                  painter->setBrush(rectangleBrush);
                  painter->drawRect(rect());

                  painter->restore();

                  QRectF activeRect = rect().adjusted(rectanglePen.widthF() / 2.0,
                  rectanglePen.widthF() / 2.0,
                  -rectanglePen.widthF() / 2.0,
                  -rectanglePen.widthF() / 2.0);
                  activeRect.setWidth(30);

                  painter->fillRect(activeRect, Qt::green);@

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    Tectu
                    wrote on last edited by
                    #10

                    I took your code and replaced my paint() routine with it. Sadly I still observe the same issues.

                    I'm really lost... Here is the full code of my QGraphicsView and QGraphicsScene derived classes:

                    mygraphicsview.h: http://paste.ugfx.org/show/e98773b84a
                    mygraphicsview.cpp: http://paste.ugfx.org/show/14e15a6d66
                    mygraphicsscene.h: http://paste.ugfx.org/show/450f49bc5e
                    mygraphicsscene.cpp: http://paste.ugfx.org/show/d5d4a8e53b

                    Now that I am pasting this, might it be related to _MyGraphicsScene::drawBackground() _?

                    Edit: I just removed my MyGraphicsScene::drawBackground() implementation and used the default one from QGraphicsScene and the issues remain.

                    1 Reply Last reply
                    0
                    • R Offline
                      R Offline
                      Rondog
                      wrote on last edited by
                      #11

                      I noticed in your code you have this:

                      @
                      // Actually modify the possition
                      float pos = selectedWindows.first()->y() + selectedWindows.first()->rect().height();
                      for (int i = 1; i < selectedWindows.count(); i++) {
                      pos += spaceBetweenItems;
                      selectedWindows.at(i)->setY((int)(pos + 0.5));
                      pos += selectedWindows.at(i)->rect().height();
                      }
                      @

                      This would set the Y position of each window rounded to the nearest integer value. Your screen shot shows the green rect offset from the frame by 1 pixel in the Y axis.

                      Does each object 'UGfxSlider' contain its own drawing code (dependent, i.e. upper left = 0,0) or are you drawing the position based on its calculated position (drawing independent of each item)?

                      1 Reply Last reply
                      0
                      • T Offline
                        T Offline
                        Tectu
                        wrote on last edited by
                        #12

                        That code is only executed when the user clicks the alignment (in this case vertical distribution) button. It is not relevant to my problem as I get the issues by just moving the item around in the scene without using any of the alignment or distribution function in MyGraphicsScene.

                        Also, please note that those functions work just fine as long as I don't execute the MyGraphicsView::updateScale(). I get the artefacts as soon as I execute that code (although my _scaleFactor is set to 1.0).

                        Each slider does contain it's own drawing code. I simply implemented the QGraphicsRectItem::paint() routine. You can see my implementation at line 133 in this file: http://paste.ugfx.org/show/ded30acd54

                        Note that I have this "off by one pixel" issue with other QGraphicsRectItem based classes too.

                        Also, the "off by one pixel" changes by moving the item across the scene. Sometimes it's right and sometimes it shows the errror. So it's definitely a rounding issue.

                        1 Reply Last reply
                        0
                        • R Offline
                          R Offline
                          Rondog
                          wrote on last edited by
                          #13

                          Ok. I figured it out.

                          I ran some tests on a project I have and saw the exact same thing you described using a subclass of QGraphicsItem. I didn't have anything other then two rect()'s drawn.

                          I found that by adding the following in the constructor of the QGraphicsView it solved this problem:

                          @
                          this->setRenderHints(QPainter::Antialiasing);
                          @

                          At some point in the drawing process only one pixel of the display is lit up (this is where the truncating occurs) . Antialiasing is a trick to fool your eye so that the apparent position appears somewhere between pixels.

                          1 Reply Last reply
                          0
                          • T Offline
                            T Offline
                            Tectu
                            wrote on last edited by
                            #14

                            I did see that the problem becomes less visible when enabling Anti-Aliasing when I tested your code. However, as you said you are still missing one of the pixel lines sometimes. This is way less visible but in my case I can't / don't want to use anti-aliasing.

                            The application I am writing is a drag'n'drop GUI designer for an embedded GUI library that targets VERY low resolution displays. If you have a resolution of just 320 x 240 pixels and a 150 x 30 pixels slider and you turn on anti-aliasing you see a big difference between the QGraphicsView rendering and the actual result (after generating the resulting code).
                            The preview that the user sees in the QGraphicsView should be as close to the actual result afterwards as possible.

                            The issue is clearly somewhere in the scaling and I hope that it can be fixed or at least workaround-ed.

                            Thank you very much for your endurance. It is appreciated a lot.

                            1 Reply Last reply
                            0
                            • R Offline
                              R Offline
                              Rondog
                              wrote on last edited by
                              #15

                              The way I did this was to draw to a QPixmap. I draw the pixmap and create or update the associated QGraphicsPixmapItem each time there is a change. I didn't even see your problem until I tested it using the QGraphicsItem.

                              If you try the QPixmap method you would have to re-draw the QGraphicsPixmapItems when the contents or the scale changes. I don't know if this a performance hit or not. It is easier to copy the contents of a bitmap then to draw directly so it should be better from that point of view at least.

                              Maybe separating the QGraphicsItem from the QGraphicsView might be the answer. You can use setFlag(QGraphicsItem::ItemIgnoresTransformations) to do this. You will have to manage the size and position of the control yourself but at least you have some control.

                              I don't know. I am beginning to think this is more internal to QGraphicsView/QGraphicsScene then anything else.

                              1 Reply Last reply
                              0
                              • R Offline
                                R Offline
                                Rondog
                                wrote on last edited by
                                #16

                                I have one more idea. I didn't try it but it might be worth investigating.

                                What if you limit your scale values to those that only increase the size by 1 pixel for each QGraphicItem that you have?

                                For example, if the QGraphicItem height is 100 pixels then make sure your scale value is restricted to 1.000, 1.0100, 1.0200 and so on. Part of the problem may be that scale values that are between even pixel sizes cause something, somewhere, to shift position.

                                You can do this independently for both axis. This assumes your QGraphicItems are not mixed sizes.

                                1 Reply Last reply
                                0
                                • R Offline
                                  R Offline
                                  Rondog
                                  wrote on last edited by
                                  #17

                                  I have another idea.

                                  If you change the order you draw the control items this would hide the problem.

                                  • Draw the knob 'green' rect first. Don't reduce the size.
                                  • Draw the frame and other items over top.

                                  This should work without needing to add anything weird.

                                  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