Usage of QPen which is cosmetic but not width zero - qt

I have recently migrated an application from Qt 4 to Qt 5. I used to use a default QPen() with width zero which was therefore cosmetic. After migration I couldn't leave it as default (the default pen has changed to be of width 1 and therefore not cosmetic). So I simply added a call to setCosmetic(True) so my pens were cosmetic but width 1.
However, this led to some unexpected (to me) behaviour. In particular I had some QGraphicsEllipseItem objects which were giving incorrect selection behaviour: specifically, a very small ellipse, scaled up to a large size, would have a much larger shape() than it was being drawn. It was being drawn with a cosmetic (1 pixel) pen but the shape was calculated as if the pen was of size 1 scaled up.
This is easily fixed: I simply set the QPen width to 0. But it raised a question in my mind.
What is the intended semantics of a cosmetic pen with non-zero width? Is this behaviour of the QGraphicsEllipseItem intended, and with useful application, or is it unexpected?

See the documentation for QGraphicsItem::paint():
QGraphicsItem does not support use of cosmetic pens with a non-zero width.

Related

Grid Layout Widget Sizing Problems

I use a Grid Layout inside my app. The grid layout I set to some fixed sizes.
myBootGridLayout->setContentsMargins(3,0,0,0);
myBootGridLayout->setRowMinimumHeight(0,25);
myBootGridLayout->setRowMinimumHeight(1,25);
myBootGridLayout->setRowMinimumHeight(2,25);
wdgBootFeatues->setFixedHeight(80);
For the QPushButton I use a size rule:
btnSelBootImagePath->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
But as you can see on the image, the ComboBox and Buttons have the same size but the LineEdit field is smaller. What I do wrong? Is there a trick to bring them on the common same size (Height) like in the QT documentation?
In case your question is to understand how to make sure that elements will have the same height, we should consider the following:
Layout might not necessarily ensure that some elements will have same height you would like, since it also relies on the size (horizontal and vertical) policy of the element in layout itself. In case you want to have QLineEdit and QPushButton instances to have the same height, you should set minimum height for each of them. Probably, it would even make sense to make the height fixed (i.e. set both minimum and maximum height to be the same values) for such elements to fit your needs, since both of these elements by default have fixed vertical size policy. This is for the reason, since most apps treat buttons and one line text fields in the same way.
In most cases, combining QVBoxLayout, QHBoxLayout and then QGridLayout is not necessary at all, since QGridLayout is much more flexible, and combines QVBoxLayout and QHBoxLayout features in a single layout under the hood at the first place, this it will probably satisfy all your needs (i.e. to represent you elements in a grid manner). Also, construction of UI elements will be slightly faster if less elements will be used.
Qt documentation might have such an effect because of the following reason - elements were tested on a different device. Qt does not try to make identical style sheets for widgets' elements across all platforms, thus visual differences will be everywhere. On some operating systems, button height is smaller than text field height by default, and this is completely normal.
One approach to make sure that size will get bigger than by default is to change size policy (vertical in your case). Code snippet changing size policy is correct basically. However, size policy is different thing than fixed height across elements. However, if your button and line edit would be in the same row, and both would have minimum expanding vertical policy, probably these elements would have the same height in that row.
Thus, probably to make sure the height of your elements remains the same is to set some minimum (and maximum as well in case vertical size policy is fixed) height through code or Qt Creator. This would be the easiest and least painful from thinking perspective approach. I am not sure if I have answered the question (it looks like that you answered yourself in your own way), but I am sure that I have introduced some thoughts that might come in handy when understanding Qt layouts.

How to set Qdialog to have a fixed height as small as possible and an expending width in Qt Creator?

I have a Qdialog with a horizontal layout and a couple of elements. Now, I want the height to be fixed at its minimal possible size (while the width is still resizeable).
There are a couple of properties I can set, for example:
sizePolicy, minimumSize, maximumSize, baseSize, layoutSizeConstraint
I tried to understand how the values interact and a couple of combinations but none got me what I want.
For example, I can enter the smallest Height possible in maximumSize, in my case 178, and set the Vertical Policy in sizePolicy to Fixed. But then it is only fixed to a small range: I can still resize the dialog's height slightly to make it slightly smaller.
This type of tasks can not be done with Qt Designer, the minimum size if you use layouts is the sizeHint(), for example in your case the solution is:
dialog.setFixedHeight(dialog.sizeHint().height());
Try to set minimumSize.Height and maximumSize.Height with same values
or
Just set fixed height in code
Dialog dialog;
dialog.setFixedHeight(dialog.height());
dialog.exec();

How to ensure even pixel size when painting scaled QImage?

I have a 4 channel png image with 8x8 Pixels that is loaded by a QImage. The QImage is then scaled by a factor of 200, so the image will have a new resolution of 1600x1600, each original pixel having a size of 200x200. But when this image is added to a QLabel through the means of a QPixmap and shown on screen, the drawn pixels will have slightly different sizes.
I've taken screenshots with Gimp and looked at the painted image more closely. It seems that every other pixel is slightly bigger than it should be, 201 instead of 200 pixels wide for example. The very last pixel in a row will then be smaller to compensate, so that the entire image has the correct size in the end.
This does not happen for all scaling factors, 100 is fine for example and so are factors that are a power of 2, such as 256.
My original approach was using a QGraphicsView and a QGraphicsPixmapItem in which case I scaled the GraphicsItem instead of the image. The effect was the same.
What effect am I seeing here? And what, if anything, can be done about it?
The code to reproduce this issue is very straightforward
int scale = 200;
image = QImage("some image file");
QPixmap pixmap = QPixmap::fromImage(image.scaled(image.size() * scale));
some_label->setPixmap(pixmap);
Turns out the easiest solution to my problem is to use QOpenGLWidget in the QGraphicsView:
setViewport(new QOpenGLWidget);
This single line in the constructor will result in much higher precision when scaling an image with the caveat of adding OpenGL as a dependency.
Another gotcha with this approach is that calling setViewport invalidates many of the settings done on a QGraphicsView. So if the view is set up in a UI file, as in my case, make sure to call other setters after calling setViewport.
I could not find a better solution that would work without OpenGL, short of writing my own rasterizer of course.

Collision with fixed pixel-size items on QGraphicsView

I'm using Qt's GraphicsView/GraphicsScene framework, and I have to draw some line items.
To be sure these items are always visible (independant of the zoom level) I use a cosmetic pen, with a size of 3 (for example) so I always get lines of 3 pixels width drawn on screen.
But these items doesn't receive mouse events (such as hoverEnterEvent/hoverLeaveEvent) when I'm zooming out a lot.
I've digged in the code, and it appears that all collisions tests are done with the return value of the shape() function.
So I've tried to re-implement "shape()" and also "contains()" and "collidesWithPath()" methods, but I still have problems to detect collisions (because when zoom is changed, I need to re-update the shape for example).
Is there any tricks to do that ?
In an efficient way ? (without re-updating the item's shape at every zoom change)
Thanks

Odd sizing policy behavior

I'm trying to place a text label next to a spin box in a horizontal layout. I want the label to be as small as possible, and the spin box as large as possible, so I set the label's horizontal sizing policy to Minimum and the spin box's horizontal sizing policy to Maximum. However, This results in the label having the maximum size and the spin box having the minimum size:
If I swap the sizing policies, I get what I want:
Is this backwards behavior a known bug, or am I just not understanding something about Qt layouts?
Using QtCreator 2.7.0 based on Qt 5.0.2 (32-bit) on 64-bit Windows 7.
"minimum" means that the widget must have the given size or more (the given size is a minimum), while "maximum" means that the given size is an upper limit, so the behaviour you observe is consitent with semantics.
I would set the spinbox policy to "expanding" and the label to "preferred".

Resources