Is there a way to obtain the size of the buttons/arrows of a Qt QSpinBox?
Note: This question has nothing to do with changing the style of a QSpinBox. On the contrary: The intent is to use the QSpinBox style as given and obtain at runtime the size of its buttons/arrows, which will be different for different platforms, for the purpose of fine tuning the layout constraints in which the QSpinBox is one component.
Also: The QStyle class does not appear to provide PixelMetric values for the button/arrows sizes.
Thnx.
Related
Qt's widgets have 2 properties determining how small they can be:
minimumSizeHint
minimumSize
Now their basic difference seems clear enough: minimumSize restricts what size the widget can actually have, and Qt won't allow setting the size smaller. It also overrides minimumSizeHint, if set. And then minimumSizeHint is only used by layouts, which won't resize the widget smaller than that when resizing its contents.
Now I was implementing a custom widget, no problems there, and I started wondering about this.
Question: why would you ever want to use mininumSizeHint at all? What is the scenario, where you have to, or want to use it instead of just always using minimumSize? Why does minimumSizeHint exist?
(And if answer is "yeah, sizeHint is enough for everything", that's fine.)
I think the main difference is that minimumSize can be changed by any other object at any time, whether you like it or not, as all QWidgets have a public setMinimumSize() function; whereas your widget alone controls what is returned by minimumSizeHint().
As an implementer of a custom widget, you always want to override minimumSizeHint() if your widget has a minimum size that you think should usually be respected. This is what the built-in Qt widgets do.
Main Question
What is the "right" way to give your widgets default sizes and make sure they contract, expand, or remain fixed if there is additional or not enough space to accommodate them?
How I Think Qt Works
After reading the Qt documentation it seems like the sizing algorithm goes something like this...the layout begins by asking its children for their ideal size via the QWidget::sizeHint method. If the layout has additional space or not enough space then it'll determine which widgets to resize based on each widget's sizing policy (QWidget::sizePolicy), minimum size (QWidget::minimumSize), and maximum size (QWidget::maximumSize).
Why isn't there a QWidget::setSizeHint method?
If my understanding is close to being accurate then it would seem all you'd have to do is set the sizeHint, sizePolicy, maximumSize, and minimumSize on each widget and everything would just work. So why isn't there a setSizeHint method?!?!??!! Sure, every time you use a widget that provides all of the functionality you need (QTableView, QComboBox, etc) you could extend it and override a single method but that sounds absolutely ridiculous.
One of the sizing issues I'm fighting with.
I've got a QMainWindow with a QDockWidget on the left hand side. The QDockWidget has a QTableView. I'd like to have the QDockWidget/QTableView take up a "reasonable" amount of space on start up and then the user can resize it however small or large they'd like.
Unfortunately, when the application starts up it gives the QDockWidget/QTableView so little space that it requires a horizontal scroll bar. The only way I've found to force it to give it a reasonable amount of width is to set the QDockWidget's minimum width but then it prevents the user from resizing it as small as they might like to.
Why isn't there a QWidget::setSizeHint method?
In my opinion it is much better for a widget to compute its preferred size based on its content (or rules) instead of allowing the coder to set a sizeHint probably hardcoded or at least prone to errors.
I almost never had to set a size on a widget, playing with the QSizePolicy was enough. And when I needed some specific constraints, playing with minimum/maximum sizes was enough. So that Qt layouts were always able to adapt the widget.
If you want to set up yourself some percentages on the sizes etc, you can play with the stretch parameter. You can also add spacers when you need empty spaces.
Extending a QWidget to override the QWidget::sizeHint method does not sound ridiculous to me, as you change the widget behaviour by changing its preferred size and that fits the polymorphism spirit of OOD.
How to properly size Qt widgets? is a vague question and depends on the use cases. Most of the time choosing the good layouts and size-policy lets you achieve very adaptative GUI. Qt Designer can help to do this right, even if the layout management is not always intuitive (you need to place your widgets first and then set them in layouts from the inner to the outer layout).
About your specific issue, it's hard to tell why your QDockWidget gets too small without knowing the details of the layout(s) you have around your two widgets in the window. Maybe it is a specific issue with QDockWidget : see related questions :
QDockWidget starting size
Qt 5.7 QDockWidget default size
Prevent QDockWidget autosizing behaviour
I want to control the pointSize-to-pixel scaling of all Text elements in my Qt 5.2.1 QML/C++ app.
I have a QML singleton component with target display properties like width, height and dot pitch that calculates appropriate pixel sizes for common dimensions such as the recommended size in pixels for a touchscreen button. This works fine for controls I write, but the Text element has a perfectly good font.pointSize that I would like to use if I could just set the logical DPI used for text scaling.
I use this to simulate target devices with very different screen DPI while debugging on my 96 DPI development screen. For example, I would like to run my app that targets a 1280x720 133DPI display and has an element like:
Text { font.pointSize: 72; text: “Xy” }
display 133 pixels tall, not the 96 pixel tall text I get because the OS tells Qt that I have a 96 DPI monitor attached. I want to override the logical DPI scaling for my application.
I can see the logicalDotsPerInchX through the QGuiApplication QScreen list. There is tons of documentation on how to get the logical DPI. But I cannot find any information on how to change it.
How can I change the logical DPI for my Qt app?
I don't think you can simply change the DPI values in the QScreen class (there are only public getter methods).
Maybe there are some "hacks" for that problem if you modify the QScreen class and add a public setter or something yourself and then recompile Qt, but that might be some work and takes a lot of time...
Another solution might be to just add a scale factor to your font sizes? I don't know how many you have but that can be simply done in QML and I use something like that even for production setting to scale the fonts and other sizes properly to the device.
You could use Screen.pixelDensityor just define your custom QML property and multiply that to all font sizes? if you do that you can dynamically change the sizes while the app is running.
I have several QDialogs that I have made in Qt Designer that use layouts, so the dialog can size itself correctly depending on the size of its children. The size of its children is run-time dependent (variable text fields, system font size etc).
It does not make sense for my dialog to be user-resizeable, so I want the size grip disabled. As far as I can tell, the size grip is disabled by calling setFixedSize(). However, I cannot put in a pixel size here, so I have implemented resizeEvent() like so:
void cRemoteConnectionDialog::resizeEvent(QResizeEvent *)
{
setFixedSize(minimumSize());
}
This works fine on Windows, but the dialog is far to small on Mac OS X.
How can I achieve a program resizable but not user resizeable QDialog that takes up the minimum space it requires based on run-time state?
Try something like this on your dialog:
this->layout()->setSizeConstraint(QLayout::SetFixedSize);
I'm working with QGraphicsView/Scene for the first time. This is in PyQt, but except for the fact that Python is different with multiple inheritance, I think this is a generic Qt question.
I started out by creating a couple of QGraphicsItem overloads as building blocks. Once I had those working the way I wanted, I wanted to try to combine them and was unpleasantly surprised to find that I couldn't use the in QGraphicsLayouts. This is due to the fact the QGraphicsLayouts take items that inherit from QGraphicsLayoutItem, and QGraphicsItems are inherited by QGraphicsLayoutItems, which are in turn inherited by QGraphicsWidgets.
There is a graphicsItem property of QGraphicsItem/QGraphicsWidget, but looking at the code, I don't think I can assign my Item's to this property and have them work properly. I did find this example, but strangely enough it has examples that inherit from both classes. Pretty confusing to me.
So I'm trying to find the easiest way to get my Items working in Layouts. Is there an easier way to do this than rewriting and inheriting from one of this two classes?
Secondary question, is there a rule of thumb for when you should inherit from QGraphicsWidget vs when you should inherit from QGraphicsLayoutItem?
Extra credit for explaining when sizeHint vs. boundingRect are used.
Appreciate the help,
Brett
The easiest way to get items working in layouts is to change the inheritance to QGraphicsWidget and override the setGeometry() and sizeHint() methods. Should be a simple change since your items will still be QGraphicsItems through the inheritance ancestry.
The Qt Graphics View framework is designed to be as lightweight as possible. Thus there are many choices for assembling items with different capabilities. If the sizes of items to be in layouts are not a concern, you can inherit from QGraphicsWidget. Otherwise, inherit from QGraphicsLayoutItem (unless you need the extra capabilities of QGraphicsWidget). Since you can't multiply inherit from PyQt classes, you'll have to use composition for creating an item controlled by the QGraphicsLayoutItem, like in the example you referenced.
The boundingRect() method is used by the scene to manage items. The sizeHint() method is used by the layouts to determine the size of layout items. The shape() method is used by the scene to more precisely determine the location of items (for collisions, hit tests, etc).