Qt arranging ltems in layout

qt grid layout example
qt layout resize with window
qt layout size constraint
qt add layout to layout
qt spacer
qt responsive layout
qhboxlayout
pyqt5 layout

For the last couple of days i am trying to solve a particular problem with the Qt Layout system. I'll try to generalize it: I have a widget with two rows. On the first row there are tree buttons( or whatever other controls ). Their layout is shown on the picture:

The center button is taking all the extra space available( and is expanding as the widget increases its size ). The thing is that i want to programmatically want to resize the center widget( button ) and maintain the layout. With my current implementation when i resize the center button this is what happens:

I want the right button to be aligned on the right of the center button( without the extra space ). Now when i resize the widget it is going back to position 1 ( center takes all the extra space ), but this is not the effect i want.

Here is my current implementation:

#include "Widget_Old.h"

#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDebug>

WidgetOld::WidgetOld(QWidget *parent) :
    QWidget(parent)
{
    QVBoxLayout* mainLayout = new QVBoxLayout( this );

    QWidget* firstRowWidget = new QWidget( this );

    QPushButton* left   = new QPushButton;
    left->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
    left->setText( "left" );

    m_center = new QPushButton;
    m_center->setText( "centerr");
    m_center->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );

    QPushButton* right  = new QPushButton;
    right->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
    right->setText( "right" );

    QHBoxLayout* firstRowLayout = new QHBoxLayout( firstRowWidget );

    firstRowLayout->addWidget( left );
    firstRowLayout->addWidget( m_center );
    firstRowLayout->addWidget( right );

    QHBoxLayout* secondRowLayout = new QHBoxLayout;
    QPushButton* button = new QPushButton( "resize" );
    connect( button, SIGNAL(clicked()), SLOT(decrement()) );
    secondRowLayout->addWidget( button );

    mainLayout->addWidget( firstRowWidget  );
    mainLayout->addLayout( secondRowLayout );
}

WidgetOld::~WidgetOld()
{
}


void WidgetOld::decrement()
{
    qDebug() << "Changing width from " << m_center->width() << " to " << m_center->width()/2;
    m_center->resize( m_center->width()/2, m_center->height() );
}

Notes:

I've tried aligning the center, and right widget Qt::AlignLeft, but no result. Actually when aligning widget left in a layout it tries to take the minimal size which breaks the expanding functionality:(

I've shared my code if any reference is needed: https://drive.google.com/file/d/0B-mc4aKkzWlxTWdNNmpuQ0ptQ3M/edit?usp=sharing

Thanks for reading my post, hope you know the solution:)

You have to set the maximum size of your central widget. For the right widget to adapt, set its size policy to MinimumExpanding when you resize the central one:

void WidgetOld::decrement ()
{
    qDebug() << "Changing width from " << m_center->width() << " to " << m_center->width()/2;
    m_center->setMaximumWidth (m_center->width()/2);
    m_right->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
}

Alternatively, if you resize the central widget manually (which is deprecated, as the above commenter noted), you must also update the geometry of the right one manually. Then your decrement method should look like

void WidgetOld::decrement ()
{
    qDebug() << "Changing width from " << m_center->width() << " to " << m_center->width()/2;
    m_center->resize( m_center->width()/2, m_center->height() );
    int rightPosX = m_center->pos().x() + m_center->width() + m_firstRowLayout->spacing ();
    int rightWidth = centralWidget()->pos().x() + centralWidget()->width() - m_mainLayout->margin() - rightPosX;
    m_right->setGeometry (rightPosX, m_right->pos().y(), rightWidth, m_right->height());
}

In this case, you should also update your custom sizes on resize, as the layout will try to restore default proportions.

Layout Management, Embed your combobox into an horizontallayout and add spacer https://doc.qt.io/​archives/2.3/designer/chap4_2.html. The Qt layout system provides a simple and powerful way of automatically arranging child widgets within a widget to ensure that they make good use of the available space. Introduction. Qt includes a set of layout management classes that are used to describe how widgets are laid out in an application's user interface.

when you use layouts you move responsibility of managing the size to a layout, so you should NEVER resize items manually when they are in layout.

try this:

WidgetOld::WidgetOld(QWidget *parent) :
    QWidget(parent)
{
    QVBoxLayout* mainLayout = new QVBoxLayout( this );

    QWidget* firstRowWidget = new QWidget( this );

    QPushButton* left   = new QPushButton;
    left->setText( "left" );
    left->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );

    m_center = new QPushButton;
    m_center->setText( "centerr");
    m_center->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );

    QPushButton* right  = new QPushButton;
    right->setText( "right" );
    right->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );

    QHBoxLayout* firstRowLayout = new QHBoxLayout( firstRowWidget );

    firstRowLayout->addWidget( left );
    firstRowLayout->addStretch();
    firstRowLayout->addWidget( m_center );
    firstRowLayout->addStretch();
    firstRowLayout->addWidget( right );

    QHBoxLayout* secondRowLayout = new QHBoxLayout;
    QPushButton* button = new QPushButton( "resize" );
    connect( button, SIGNAL(clicked()), SLOT(decrement()) );
    secondRowLayout->addWidget( button );

    mainLayout->addWidget( firstRowWidget  );
    mainLayout->addLayout( secondRowLayout );
}

Using Layouts in Qt Designer, How to arrange the items in the default layout of QMainWindow? c++ qt layout qmainwindow. This is the arrangement that I want: -------  The Qt layout system provides a simple and powerful way of automatically arranging child widgets within a widget to ensure that they make good use of the available space. Introduction Qt includes a set of layout management classes that are used to describe how widgets are laid out in an application's user interface.

I don't know if it's a bad idea.

Could you make your firstRowLayout global and then dynamically add a stretch to the layout in the end in your decrement() SLOT function?

void WidgetOld::decrement(){
    qDebug() << "Changing width from " << m_center->width() << " to " << m_center->width()/2;
    m_center->resize( m_center->width()/2, m_center->height() );
    firstRowLayout->addStretch(1);
}

this way the stretch will push all your buttons to the left

How to arrange items horizontally in vertical layout?, Introduction; Qt's Layout Classes; Horizontal, Vertical, Grid, and Form Layouts The Qt layout system provides a simple and powerful way of automatically arranging Represents an anchor between two items in a QGraphicsAnchorLayout. Qt Quick Layouts can also be used to arrange Qt Quick items in a user interface. They manage both the positions and the sizes of items on a declarative user interface, and are well suited for resizable user interfaces.

How to arrange the items in the default layout of QMainWindow , Qt's layout managers are structured containers which automatically arrange In Qt Designer, you can create layout objects by applying a layout to a group of  Each layout defines its own API for arranging widgets and layout items. For example, with a grid layout, you require a row and a column index with optional row and column spans, alignment, spacing, and more. A linear layout, however, requires a single row or column index to position its items.

Qt 4.8: Layout Management, In this tutorial, we will learn Grid Layout of Qt. We will modify the code we used in the Grid Layout provides a way of dynamically arranging items in a grid. FlowLayout:: ~ FlowLayout() { QLayoutItem * item; while ((item = takeAt(0))) delete item; } In this example we reimplement addItem() , which is a pure virtual function. When using addItem() the ownership of the layout items is transferred to the layout, and it is therefore the layout's responsibility to delete them.

Build GUI layouts with Qt Designer for PyQt5 apps, Qt Quick Layouts are items that are used to arrange items in a user interface. Since Qt Quick Layouts also resize their items, they are well suited for resizable  This property holds the layout direction of the grid layout - it controls whether items are laid out from left to right or right to left. If Qt.RightToLeft is specified, left-aligned items will be right-aligned and right-aligned items will be left-aligned. Possible values: Qt.LeftToRight (default) - Items are laid out from left to right.

Comments
  • Actually with the first approach indeed the right button will remain to the left, but it will also increase its size. I guess if i want to keep the right button its size, I should add a stretch after the last button?
  • So you want the right widget to retain its size, so that you have blank space to the right when you resize the central widget? In this case, you don't need to set size policy in WidgetOld::decrement, instead add firstRowLayout->setAlignment( Qt::AlignLeft ); in the constructor.
  • Thanks for the quick reply, but this doesn't really work. I think the stretches actually add spacing between the buttons and i want them to be tied together:) Concerning that rule for not re-sizing custom widgets do you have any ideas on how to solve the problem using another approach.
  • maybe I don't understand what are you trying to achieve. I thought that center button should be centered with spacing with other buttons. If you need other combination just put stretching in different position (where you need space).
  • I will add stretch after the last button and this should work. But when I increment the size of the center button, the right one is not moving and its geometry should be updated manually.
  • read again first sentence from my answer. You can enforce different size for example by changing minimum minimumWidth.