Последние пару дней я пытаюсь решить конкретную проблему с системой Qt Layout. Я постараюсь обобщить это:
У меня есть виджет с двумя рядами. В первом ряду находятся кнопки дерева (или любые другие элементы управления). Их расположение показано на картинке:
Центральная кнопка занимает все доступное дополнительное пространство (и расширяется по мере того, как виджет увеличивает свой размер). Дело в том, что я хочу программно изменить размер центрального виджета (кнопки) и сохранить макет. С моей текущей реализацией, когда я изменяю размер центральной кнопки, вот что происходит:
Я хочу, чтобы правая кнопка была выровнена справа от центральной кнопки (без дополнительного места). Теперь, когда я изменяю размер виджета, он возвращается в положение 1 (центр занимает все дополнительное пространство), но это не тот эффект, который мне нужен.
Вот моя текущая реализация:
#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() );
}
Заметки:
Я пытался выровнять центр и правый виджет Qt :: AlignLeft, но безрезультатно. На самом деле, когда
выравнивая виджет слева в макете, он пытается получить минимальный размер, который нарушает расширяющуюся функциональность 🙁
Я поделился своим кодом, если какая-либо ссылка нужна:
https://drive.google.com/file/d/0B-mc4aKkzWlxTWdNNmpuQ0ptQ3M/edit?usp=sharing
Спасибо за чтение моего поста, надеюсь, вы знаете решение 🙂
Вы должны установить максимальный размер вашего центрального виджета. Чтобы адаптировать нужный виджет, установите для его политики размера значение MinimumExpanding при изменении размера центрального:
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 );
}
альтернативно, если вы измените размер центрального виджета вручную (что устарело, как отмечалось выше), вы также должны обновить геометрию правого виджета вручную. Тогда ваш decrement
метод должен выглядеть так
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());
}
В этом случае вам также следует обновить ваши собственные размеры при изменении размера, так как макет будет пытаться восстановить пропорции по умолчанию.
когда вы используете макеты, вы перекладываете ответственность за управление размером на макет, поэтому НИКОГДА не следует изменять размеры элементов вручную, когда они находятся в макете.
попробуй это:
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 );
}
Я не знаю, плохая ли это идея.
Не могли бы вы сделать свой firstRowLayout глобальным, а затем динамически добавить растяжку к макету в конце в вашей функции SLOT декремента ()?
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);
}
таким образом растяжка будет нажимать все ваши кнопки влево