How to control widgets overlap priority in a q[grid]layout? - qt

I'm trying to have a 2x2 QGridLayout arranged as follows:
+-----+-----+
|(1) |(2) |
+-----+ |
|(3) | |
+-----+-----+
I want to be able to expand (1) programatically to occupy the whole first row, like as follows:
+-----------+
|(1) |
+-----+-----+
|(3) |(2) |
+-----+-----+
Actually, I want to expand and contract any widget to any direction.
I'm able to do this by just detecting what widget is in the cell I need to expand to. But the problem is that it is a pain to make this happen on any direction and any grid size, because I need to go back to the initial position of the just expanded widget (1), so I don't need to remember positions, except the one I'm expanding/contracting.
So, in the example above, I decided to just expand the widget to occupy the position 0,0 with column span of 2. This will result in overlapping widgets, which is ok for me. The problem is that widget (1) will be underneath (2), I guess because of order of insertion into the grid. Hence the question: how do I control a widget's overlap priority in a QGridLayout?
Thanks!

Perhaps you can make something like this work for you with some experimentation.
Both shots are of a QVBoxLayout with two QHBoxLayouts in them. You should be able to dynamically remove and add buttons from one QHBoxLayout to another. You can add or remove a spacer to determine if a button will span the whole width or not.
I realize that it is still adding and removing widgets but it might be a little easier than the grid layout.

I got the answer to my question. The solution is to call raise() on the widget I'm resizing. This "resizing" is actually a removeWidget from the layout and an addWidget to the layout (again), with the new cells and cell spans information. After this, I call raise() on the widget, and that's it.

I'm not sure that this will do what you want, but from what I understand you want to resize your three widgets in any way you want.
You could try to look into the QSplitter class. It allows you to change (manually or programmatically) the size of your widgets, a bit like the outlook separations.
It is really easy to use and may be flexible enough to give you what you want.
Hope this helps.

Related

Resizing Layout equal to MainWindow

When I run my program it will display all content properly, and when I resizing the main window, the layout along with all associated widgets remain fixed, rather than resizing with the main window. I used to increase my all widget and listWidget respect to window computer resolution size but still this not one work properly.
I used this one code finding the system height and width.
QWidget widget;
widget.resize(widget.width(), widget.minimumHeight());
QRect rec = QApplication::desktop()->screenGeometry();
int h = rec.height();
int w = rec.width();
// Increasing the listwidget size
ui->listWidget->setFixedHeight(h);
ui->listWidget->setFixedWidth(w);
//increasing the button size
ui->pushButton->setFixedHeight(h0.2);
ui->pushButton->setFixedWidth(w0.2);
At this link you will find two screenshots that illustrate my problem.
Please resolve to solve my problem. Thanks very much in advance.
When defining the layout of your windows and forms in Qt Designer you have to define each element of your form in advance, in order to have a working layout.
This solution is based on the screenshots provided in the comments to the question. Follow these steps:
Add an empty widget to the central area of your form, if there is nothing there. It will be used as a placeholder for the controls you will add later, and of course you can replace it with whatever widget you want. But you need it there to define a proper layout.
In the property panel, set the horizontal QSizePolicy of this widget to MinimumExpanding.
Add an horizontal spacer to the left side of your progress bar.
Define a minimum/maximum width for the white widget on the left (I guess it's a text area). As an example set the maximum width to 200
pixels.
Make the same for the QTabWidget on the right.
Give a minimum height to the Groupbox on top.
Then give the grid layout to the MainWindow.
You should get something similar in the designer view (I use a dark theme, yours will have different colors of course):
If you complete all steps you should have a nicely resizing window.
For the future: remember to integrally define your layouts, also using placeholder widgets when needed, read carefully the documentation about the widgets size policies (there are several, you need to play with them to fully understand each one) and keep in mind that Qt uses a container based approach which is different, as an example from those used by the .Net framework that relies on the concept of anchors.
EDIT : to answer questions in the comments
You will need to add a layout to any widget that contains other widgets, e.g. adding controls to your groupbox will require to give it a grid, horizontal or vertical layout in order to scale nicely on resize. Again use spacers and size policies to make it look the way you want. If you need to add or remove controls, or change their positions, you may need to brake the layout, rearrange and then set it again.
You can also select groups of widgets and give them a layout e.g. vertical, than another group and set them horizontal and so on... then give a grid layout to the container widget to build a compound layout.
There are endless possibilities, you just need to practice and go through trial and error as for everything else...
You can also do it all programmatically, check the Qt widgets documentation for this. But for complex layouts I would not go that way: it's a lot of code... and you have to compile and run to test every modification.
Using the QtCreator, within the designer you can simply right-click on the parent-widget and add a Grid-Layout.
This one resizes it's children to it's dimensions.

Is possible to do a flex layout with Qt?

I want to make something like a gridlayout but the layout must decide how many elements can be fitted in a row, and when the row is full continue with the next row.
QtGridLayout also fixes the columns width.
I want to something like this (this pictures was manually organised in Horizontals and verticals grids)
When the image size changes one of the buttons goes to first row.
((In this compositions both images looks with the same size, but actually second one is wider than first one).
Some one answer this question but remove it, so the credits are for my unknown friend.
Qt have an example named Flow Layout Example for a widget based form and another for Graphics View widget.

Qt layout children float

I have an empty horizontal layout that I dynamically populate with three children. This is a card game so this layout gets dynamically populated with children that are QLabel which have an image set. When I click on a card to play it and move it at the center of the screen I'd like the positions of the other cards to stay the same. Instead the cards tend to "float" to the right. How can I force them to stay in their original position?
+-----------------+
| |
| [A] - [B] - [C] |
| |
+-----------------+
I tried putting an expandable horizontal spacer in between each card but it doesn't really work. I also tried with replacing the horizontal layout with a grid layout but this forces me to specify the initial coordinates of the cards which I'd rather not. I like the fact that I can append widgets with addWidget pretty much like I do in the HTML version.
In the HTML version I use some wrapper divs with a fixed size around the cards. How can I do something similar in Qt?
EDIT
A little clarification on how the layout should look when one card (B) is played.
+-----------------+
| |
| [A] - - [C] |
| |
+-----------------+
As I mentioned I managed to fill the layout with empty QWidget and put cards on top of them (not inside them). I actually got also rid of the horizontal spacers I had as they are not needed anymore. This seems to work as I expect, although I still didn't fully validate this approach.
Simple algorithm steps to do what you want :
User clicks
Select the label where the click happened
If there is an image, Remove the image from the label
Don't remove the label from the layout, and make sure that the layout don't resize the label
Add the image to a label in the center of the board game.
When the user clicks on a label which has nothing, just ignore the click.
For each player you know the maximum numbers of cards which can be shown in your layout. Moreover, I don't think the size of the card is variable. So each time you create a deck for one player, create empty labels, each one having a fixed size.
EDIT: SOME OTHER PROPOSITIONS
fix size of labels using QWidget::setFixedSize();
Don't hide your label to remove your pixmap . Don't set an empty pixmap. Rather, set
a pixmap which is transparent or filled with some neutral color...
Alternatively subclass QLabel such that you can indicate a minimum size hint. The layout must and will respect anything you set. Example:
class MyQLabel : public QLabel {
MyQLabel(QSize cardSize, //remaining qlabel args)
:QLabel(//label args)
{_cardsize = cardcardSize;}
//only method to re-implement
virtual QSize minimumSizeHint () const {return _cardsize;}
private:
final QSize _cardsize;
}
Each time your whole application need to be painted again, all widgets properties are checked. My two cents is that a size property is modified when you play a card,
and the layout adapt to this modification. Tell me if the size hint trick work (it should).
In Qt you can use wrapper QWidget with Fixed sizePolicy.

QBoxLayout with stretchable separator

do anybody know how to create a stretchable separator between two Widgets in a QBoyLayout?
So that the user can easily change the stretch factor for the cols/rows.
Something like that you can see in the picture:
thanks.
I think a QSplitter would fit best for your need. You can click and drag it to adjust how much space each widget gets.
What you are looking for is a Splitter Layout:
Another common way to manage the layout of objects on a form is to
place them in a splitter. These splitters arrange the objects
horizontally or vertically in the same way as normal layouts, but also
allow the user to adjust the amount of space allocated to each object.

Qt QHboxLayout cell size ssues

For those of you who haven't been reading my Qt questoins, I am learning Qt for a project. I have only limited experience with GUI design at all, and not in Qt.
I've got a horizontal layout that I want to populate with some buttons. I can feed these buttons in just fine, but my formerly-square buttons are stretched horizontally to take up more space.
I want to let the layout manager determine the best way to size these buttons, but I also want their original proportions to remain intact. For instance, if I start would with 32X32 buttons that need to shrink to fit all of them in the layout, I want them to shrink proportionally so that the width to height scale is maintained. 20X20, 16X16, 12X12 would all be just fine, but 24X16 would be an example of dimensions that are unacceptable.
I've tinkered with size policies on the buttons and stretch options. I'm not seeing, even after reading the QPushButton and QHboxLayout classes how to do this. How is it accomplished?
Thanks.
As long as I understand the question correctly, I think what you want is QBoxLayout::addStretch(). This will add a spacer object that fills the unused space. So the buttons will have their ideal size and the spacer will fill the rest. You can try experimenting with this in Designer, it's easier than the write/compile/run cycle.
You should take a look at the answers to this question. This is a recap of my answer there.
You need to create a custom derivative of QLayoutItem, which overrides bool hasHeightForWidth() and int heightForWidth( int width ) to preserve the aspect ratio. You could either pass the button in and query it, or you could just set the ratio directly. You'll also need to make sure the widget() function returns a pointer to the proper button.
Once that is done, you can add a layout item to a layout in the same manner you would a widget. So when your button gets added, change it to use your custom layout item class.
I haven't actually tested any of this, so it is a theoretical solution at this point. I don't know of any way to do this solution through designer, if that was desired.

Resources