QGraphicsView render issues when scaling
-
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? :/ -
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);@
-
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/d5d4a8e53bNow 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.
-
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)?
-
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.
-
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.
-
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.
-
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.
-
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.
-