Adjusting QMainWindow size - qt

I am currently building a minesweeper game which has three different game modes. Harder mode has more objects and a bigger window size. When I try to switch back to a simpler mode, the size of the window will not resize to a smaller window, which will make the layout look terrible.
Before it looks like this:
After switching from a harder mode, the layout will be like this(which remains the size of the harder mode):
So what can I do to set those windows to suitable sizes? Or what can I do to set a default window size for each mode? Thanks

There is a few things you should look into:
Size policies. Size policies of the individual widgets dictate how they might shrink or be expanded vertically and horizontally. With the right policies, elements like the icons and scores at the bottom will stay reasonably sized in all geometric configurations. Depending on how you realized the playing field, you can also use size policies there to ensure that elements don't grow too big.
Spacers. A horizontal spacer element in the middle of your bottom bar will help keeping the icons and scores small and in position. It will eat up the additional space.
QWidget's adjustSize() method. You can call it whenever your playing field changes. If your playing field does not work with size hints, but absolute sizes, you can call resize() on the playing field widget, and then. if necessary, adjustSize() on the main window.

Related

QT Quick QML application support for multiple display size

How do we have QT Quick QML application render properly on different screen sizes?
For example screen size 800x600 and 1280x720.
So how should I build the screen so that it looks the same on both the screens?
I know we have to use Anchors and avoid X, Y fixed location.
But we need to provide Height and Width for the components and that is causing the issue for displaying the same component on two different screens.
I have read the below links:
https://doc.qt.io/qt-5/scalability.html
https://doc.qt.io/archives/qt-4.8/scalability.html
QT recommends, building two separate parent layouts sounds illogical.
Is the scaling approach is the way to go?
QML fit screen on all resolutions
Normally, when I deal with scalability it's in a smartphone environment which has much more variableness to it than your situation but I think the same principles hold.
Generally speaking, I don't think you should try to scale the logical pixel ratio of the entire user interface. I think it should stay at 1:1 where one logical screen unit (pixel) in QML equals one logical screen unit (pixel) outside of QML.
The main reason for this is you are normally going to have at least two different aspect ratios: in your case 800x600 is 4:3 and 1280x720 is 16:9. When the aspect ratios do not match, you either have to clip content or have black bars on the sides if your UI itself chooses one or the other of those aspect ratios and tries to display full screen on both (assuming you don't want to stretch the image of the UI in either direction - which almost never makes sense for a UI).
So, what I normally do is use RowLayout and ColumnLayout with fillWidth and fillHeight set appropriately on the UI itself so that appropriate interior areas of the UI stretch to accommodate greater or lesser space as the screen size changes. It's the same principle used in web apps to accommodate various window sizes.
One great way of doing this is to build the app to your desktop environment (Mac or Windows) and just resize the window and see how your layout adapts to different screen sizes. Once you've got it laying out rationally for the range of sizes you have to deal with, then you can build for your target environment and it should run fine.

How to properly size Qt widgets?

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

CSS react to mobile Browser Zoom

I was under the impression, that the units vh and vw deal with mobile browser zooming in, but apparently that's not the case and I think I am beginning to understand why. Zooming in does not change the viewport at all, but merely shows the user only a part of the viewport, despite the name viewport. Basically there is a difference between what you can see and the viewport. I don't know if distinguishing those two really makes sense, but that's how it seems to be.
The question is: How else do I "react" in my stylesheet to zoom changes?
For example, I have some html element with a width and it fits on the screen of a mobile phone. Now the user zooms in (doing that two finger gesture, moving the fingers away from each other). The size of the element should stay the same relative to what the user sees, but text should get bigger, because it might be the reason why the user zooms in. Maybe they couldn't read it before or want a link to be bigger, so that they can click more easily on it.
How would I do such a thing?
I've read about #viewport stuff, but it's not really supported yet and also poses the question, when to use which viewport size, how to make it as fluent as when you use vh and vw on a destop browser? Simple limiting "up to so and so much px of width" won't do. Defining a mathematical function for how much the element changes its size relative to what one can see and how much the text size changes would be great, but is probably not possible to have.
On mobile devices, the text-size-adjust property allows Web authors to control if and how the text-inflating algorithm is applied to the textual content of the element it is applied to.
As this property is non-standard, it must be used prefixed: -moz-text-size-adjust, -webkit-text-size-adjust, and -ms-text-size-adjust.
Browsers on smartphones don't display web pages using the same algorithms as browsers rendering web pages on desktop machines. Instead of laying out the web page at the width of the device screen, they lay it out using a viewport that is much wider than the device screen, usually of 800 or 1000 pixels wide. One of two possible methods is used to map back to the original device coordinates: either a smaller window is then used to display on the device screen only part of what is actually being rendered, or the viewport is stretched to the size of the device.
Its highly experimental though

Getting QDockWidget layout right

I heavily use dock widgets to let the user arrange the tools the way she wants. Some of my dock widgets contain static controls (FS, fixed vertical size), others depict images, the larger the better (ES, expanding vertical size).
The problem I face is that I cannot get a configuration of size hints that lets me do this:
Make the variable size dockwidgets as large as possible
Let all dockwidgets tab with each other without buggy behavior
For 1., I can set the Vertical Policy of all FS's content widgets to "Fixed". This will force the container to use all free space for variable size widgets. However, as soon as a ES widget is tabbed with a FS widget, while the FS widget is not shown, I get stubborn behavior at best (user cannot adjust size) and buggy behavior at worst (when adjusting size, drawing errors happen, actual size did not change).
For 2., I can set all Vertical Policies to either "Preferred" (FS) or "Expanding" (ES). This should give preference to the ES, but it doesn't. I also tried playing with Vertical Stretch to no advance (while it is helpful in other scenarios where no DockWidgets are involved).
I am stuck with a situation where by default, the application wastes space and the user has to do several adjustments to the dockwidget sizes whenever the window size/layout changes. It is very tedious and counter-intuitive.
How do I do this right?
And a follow-up question: How to teach a DockWidget that it's contents have a specific aspect ratio?
I found the biggest issue was that I used custom widgets for display which would not overload the virtual QSize sizeHint() const method.
Overloading this method and returning a high number, e.g. 500, for the vertical size, helped the layout considerably.
It seems that the (private API) QMainWindowLayout does an initial guess on best dock widget sizes and then sticks to that. In the same course, it seems to ignore the differences between Preferred and Expanding policies or Stretch settings.
By providing a large sizeHint the custom widget gets better balance with stock Qt Widgets (e.g. QListView) that do the same.
The result is acceptable, but far from perfect.

Understanding form layout mechanisms in Qt

Qt has a flexible and powerful layout mechanism to handle view of desktop application's windows.
But it is so flexible, that it nearly cannot be understood, when something goes wrong and needs fine tuning. And so powerful, that it can beat anyone in their tries to overwhelm Qt's opinion of how form should look.
So, can anyone explain, or provide articles, or source of Qt's positioning mechanisms?
I'm trying to force the QLabel, QPushButton and QTableView, marked by trailing underscores in their names, be two times higher than QTextBrowser having verticalStretch = 1 below. How can I handle widget's height properly?
.ui file of my form on google docs. Search '____' in names, preview in QtDesigner
Layouts are actually easy to understand "I think". :)
A simple explanation of layouts can be found in the QT book "C++ Gui programming with QT 2nd edition"
What you should be aware of regarding layouts and their size policies
Most Qt widgets have a size policy. This size policy tells the system how the widget should stretch or shrink. It's got from the class QSizePolicy. A size policy has both vertical and horizontal components.
Most widgets also have a size Hint. This size hint tells the system a widgets preferred size
QSizePolicy has a stretch factor to allow widgets to grow at different rates
**I am only familiar with 4 size policies**
fixed size policy - The size of the widget is fixed and it can't be stretched. It remains at its size hint.
minimum size policy - The size hint is the smallest possible size of the widget, but it _can still_ grow bigger if necessary.
Preferred size policy - the widget can shrink or grow bigger than its size hint.
expanding size policy - the widget can shrink or grow bigger than its size hint :)
You may want to ask,
What is the difference between preferred and expanding?
**Answer:** Imagine a form with 2 widgets, one with preferred and another with expanding. Then any extra space will be given to the widget with the expanding policy. The widget with the preferred policy will remain at its size hint.
I recommend (WARNING: am not an expert :)) you buy and read through "C++ Gui programming with QT 2nd edition". I am currently reading it and it is making a lot of sense. Look at the images and see if they make some sense.
Explaining size policies
A simple example
This is a simple dialog with 2 buttons whose horizontal and vertical size policies are shown as are the horizontal and vertical stretch.
Here is the preview at its smallest size.
Here is another preview at a larger size
[EDITED: //added size hint example]
WHY YOU SHOULD CARE ABOUT SIZEHINT
You can see that every widget has a sizeHint which is vital because QT's layout system always respects the sizeHint. This is only a problem if the default size of the widget is not exactly what you want. The only way around this problem is to extend (subclass) the widget and reimplement its sizeHint() member function. An example is worth 1000 words. To save space, see my blog where there is an example project.
According to its docs:
When you add widgets to a layout, the layout process works as follows:
All the widgets will initially be allocated an amount of space in accordance with their QWidget::sizePolicy() and QWidget::sizeHint().
If any of the widgets have stretch factors set, with a value greater than zero, then they are allocated space in proportion to their stretch factor (explained below).
If any of the widgets have stretch factors set to zero they will only get more space if no other widgets want the space. Of these, space is allocated to widgets with an Expanding size policy first.
Any widgets that are allocated less space than their minimum size (or minimum size hint if no minimum size is specified) are allocated this minimum size they require. (Widgets don't have to have a minimum size or minimum size hint in which case the stretch factor is their determining factor.)
Any widgets that are allocated more space than their maximum size are allocated the maximum size space they require. (Widgets do not have to have a maximum size in which case the stretch factor is their determining factor.)
And sizeHint() is the recommended size of a QWidget, and the Layout of the widget parent will take sizeHint() and sizePolicy() into consideration to determine the space of the child widget can hold.
You can use QT Style Sheets to control the widgets height
and other properties in an easy customizable way.
http://doc.qt.io/archives/qt-4.7/stylesheet.html
As for the layouts you need to use them wisely and strongly
coupled with spacers in order to make the widgets behave
exactly the way you want them to.
http://doc.qt.io/archives/qt-4.7/designer-layouts.html

Resources