QT Flowlayout - issue with multiline labels - qt

I have a small problem with QT layout.
I have a toolbox, and I want to populate it with some checkable buttons with a description. So I create a QWidget with a QGridLayout and put the QButton in the first cell and the QLabel in the second.
This is the most important part of the code (I removed dependancies from other irrelevant code in the app):
QWidget *createCellWidget()
{
QToolButton *button = new QToolButton(this);
button->setCheckable(true);
button->setMinimumSize(57,57);
button->setMaximumSize(57,57);
QWidget *widget = new QWidget(this);
QGridLayout *layout = new QGridLayout(widget);
layout->addWidget(button, 0, 0, Qt::AlignHCenter);
QLabel *lbl = new QLabel("my very long caption");
lbl->setWordWrap(true);
lbl->setAlignment(Qt::AlignCenter);
layout->addWidget(lbl, 1, 0, Qt::AlignTop);
widget->setMaximumWidth(80);
widget->setMinimumWidth(80);
return widget;
}
then I create a QGridLayout and populate it with these controls:
QWidget *itemWidget_FlowControl = new QWidget(this);
QGridLayout *_flowControl_layout = new QGridLayout(itemWidget_FlowControl);
_flowControl_layout->addWidget(createCellWidget(), 0, 0);
This works well and produces this output:
this is a nice layout. Unluckily if I enlarge the window the controls do not "flow", so I tried to replace the QGridLayout with a flowlayout (here are the source files).
Now the behavior is much better. BUT...
this is what I get. The longer captions are laid out as if they were single-lined, so the text overlaps with the button.
What can I do to make it look like before, but keeping it as a "flow layout"? Or do you know if there is any alternative in QT 5.2?
Thank you

What's wrong?
You are on the right track of using flowlayout.
The only problem is the internal layouts (QGridLayout in your case) of your cell widgets also stretch in response to the resize events.
Solution
The solution is surprisingly simple:
Try to limit the stretch of the internal layout.
Within the factory function QWidget *createCellWidget():
[Option 1]
Add lbl->setMaximumWidth(60); to manually limit the stretch of label width. This makes the internal layout not stretch so "freely."
[Option 2]
Add layout->setSizeConstraint(QLayout::SetFixedSize); to restrain the internal layout stretch. By doing this, you may want to manually add some line break code (\n) to your "very long caption" in case the label width automatically decided by Qt doesn't suit your need.
Result

IMO the best approach would be use off style sheets (flow layout is Ok).
Simply use QButton but customize its view by altering its stye sheet.
Currently I have no time to write an example.

Related

Adding/removing items from a QT layout

I'm trying to add some items dynamically to a vertical layout, so I'm creating a new horizontal layout, adding a label and push button to that, then adding this to the vertical layout using addLayout, but it doesn't seem to be happening correctly.
If i put a breakpoint in and go through the 'this' object's children, I find the vertical layout object, and it has the push button and label as children - no horizontal layout object to be seen, but in the GUI it is being layed out like it's in a horizontal layout (yes the naming convention here is bad).
QHBoxLayout *AA = new QHBoxLayout;
QLabel *BB = new QLabel;
QPushButton *CC = new QPushButton;
AA->addWidget(BB);
AA->addWidget(CC);
ui->verticalLayout->addLayout(AA);
I then try to remove the buttons from the horizontal layout and remove the horizontal layout and delete them, but depending upon how I do it, it either doesn't work or crashes.
QHBoxLayout *a1 = ui->verticalLayout->layout()->findChild<QHBoxLayout*>();
QPushButton *a2 = ui->verticalLayout->findChild<QPushButton*>();
QPushButton *a3 = a1->findChild<QPushButton*>();
//(a2 and a3 are both null, a1 returns an object)
So my question is how do I add items dynamically to a horizontal layout then add this to an existing layout, and then later iterate through this to remove them? (One unfortunate thing I've found with Qt thus far is tutorials or 'how tos' for dynamic layouts is completely lacking, most things I've tried have came from posts on SO).

Button arrangement on a full-screen window

My intention is to provide a GUI with two sections, one of which displays k buttons, where k is the number of .txt files in a specific folder. I would be glad to know that there is a way to to simply add buttons (largest possible), still “nicely” arranged in a full screen window. In other words, I would like to only add push buttons, and these would be automatically arranged for me (no specification of coordinates and sizes).
The initial window should be full screen, and buttons should be as large as possible. Any description on how this might be achieved, with pointers to existing examples, is highly appreciated.
You should look into Qt Layouts, for exactly this kind of problem.
A simple example might look something like:
QStringList myListOfFiles;
QWidget *parentWidget; // The widget you want to put them into
QVBoxLayout *layout = new QVBoxLayout;
foreach(QString file, myListOfFiles)
{
QPushButton *button = new QPushButton(fileName,this);
layout->addWidget(button);
}
parentWidget->setLayout(layout);
This will arrange the buttons in one vertical column, and will be as wide as the parent widget. You could look at QGridLayout if you need more than one column.

Strange behavior of margins for Qt controls

I have just started using Qt (5.3) and encountered the fact that some controls appears with margins which I cannot control.
First, I tried to put QLabel and QPushButton right inside QMainWindow
window = new QMainWindow;
label = new QLabel( title, window );
In this case label appears with a margin of 12 pixels at the top (see picture).
QPushButton appears with 1 pixel top & left margins.
But if I insert QFrame with a border, it appears without any margin.
So the margins seem to be attributes of QLabel and QPushButton.
BUT:
When I tried to add extra QFrame between windows and controls:
window = new QMainWindow;
frame = new QFrame(window );
label = new QLabel( title, frame);
I had got different picture:
QLabels top margin had shortened to 1 pixel
QPushButton 1 pixel margins remained intact, but the height of the button had changed
I have tried:
setStyleSheet( "padding:0px" )
and
setContentsMargins( 0, 0, 0, 0 )
for all elements, but without any success.
Any help would be greatly appreciated
The QMainWindow class isn't designed to have widgets added to it directly. Whatever results you see are due to this fact.
The "margins" that you see are not really margins. Since a QLabel is a QFrame, you can enable its frame to see that it has no margin - merely the text is offset from the edge, and that's by design. You can similarly overlay a same-size translucent rectangle on a QPushButton to see that there is also no margin, merely the styling adds its own platform-specific margin. Do not mistake the platform styling mechanism for the style sheets: they are two separate mechanisms and mostly exclusive, with the use of the latter disabling the effects of the former, with few exceptions. For example, the stylesheet spacing/margins/padding is additive to whatever the platform style mandates.
See this answer for an example of how to show overlays on any widget without subclassing.

Qt QLayout inside QDesktopWidget

I want to do universal method to set position of my widget.
All I wanna get it is set right coordinates for my widget wich must always be in right bottom corner of desktop. My widget can change his height (or maybe width) but it must have adjusted size by both ordinates... (too many words)
My idea is using QDesktopWidget as basic widget to put into my QLayout with stratch items (to align inner (my) widget to right and to bottom sides)
my code prototype is here:
QDesktopWidget * desktopWidget = QApplication::desktop();
MyWidget * myWidget = new MyWidget(desktopWidget);
QVBoxLayout * vlayout = new QVBoxLayout;
vlayout->addStretch();
vlayout->addWidget(myWidget);
QHBoxLayout * hlayout = new QHBoxLayout(desktopWidget);
hlayout->addStretch();
hlayout->addLayout(vlayout);
but it doesn't work...
Help me please implement my idea if you know how.
At this moment I know only one work way to do it - it is manually set pos of widget and handle many events (resize etc.) - but this is not good... (because i do it bad of cause ;-)
)
PS: idea with qlayout inside other widget is working for example with QTextBrowser with sandclock at certer of view, etc.
A QDesktopWidget isn't intended to be used like a typical widget (at least as far as I'm aware, I'm surprised the documentation isn't more explicit about that). So you shouldn't try to parent widgets to it or try to assign it a layout. You call its methods to obtain information about the desktop environment or connect to its signals to be informed of changes.
Using this information, you would then set the geometry of your own application widgets so that they appear on the correct screen and position you want.
This page shows some basic functionality.

Qt - change QWidget layout

Let's consider we have a QWidget and a QLayout named general_layout that contains other widgets and layouts. general_layout is set as the QWidget layout like this:
setLayout(general_layout)
Now I should to change the content of QWidget. How can I do that? I have tried to delete and create a new layout for the QWidget and that new layout set as a layout of the QWidget, but could not complete my intentions successfully.
This is my code:
delete general_layout;
general_layout = new QHBoxLayout;
general_layout->addLayout(some_layout);
myQWidget->setLayout(general_layout);
The problem is that the widgets of a layout are not destroyed when deleting a layout. This results in all child widgets of myQWidget still being present, be it without a layout.
The solution is simple: add a
qDeleteAll(myQWidget->children());
after
delete general_layout;

Resources