質問

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: enter image description here

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:

enter image description here

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.

他のヒント

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 );
}

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top