我有一个QScrollArea,里面有一些按钮,如图所示。
布局的想法是: 1.当按钮太宽时,应使用左右按钮滚动按钮
2.滚动区域中的按钮数量可以动态更改 3.应尽可能使用任何可用空间来扩展滚动区域。如果不存在这样的空间,则应使用导航按钮进行滚动。
当我增加按钮时,我的当前实现我有这个:
但是右边有可用空间,所以这应该是这样的:
如果我再次增加到10,例如,那么应该出现滚动条(因为小部件会构成布局)。
我想知道除了手动调整窗口小部件之外是否还有其他方法(因为ui可以翻译,按钮可以改变大小提示,但实际设计也更复杂:(
以下是我对ScrollAreaTest小部件的实现:
#include "MainWidget.h"
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QScrollArea>
#include <QPushButton>
#include <QDebug>
#include "ButtonWidget.h"
#include "CheckableButtonGroup.h"
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent),
m_scrollArea( 0 ),
m_lineEdit( 0 ),
m_buttons( 0 )
{
QVBoxLayout* mainLayout = new QVBoxLayout( this );
QWidget* firstRow = new QWidget;
QHBoxLayout* firstRowLayout = new QHBoxLayout( firstRow );
QPushButton* left = new QPushButton;
QPushButton* right = new QPushButton;
m_buttons = new CheckableButtonGroup( Qt::Horizontal );
m_buttons->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
m_buttons->setButtonsCount( 5 );
m_buttons->setStyleSheet( "border: none" );
QWidget* const buttonsContainer = new QWidget;
QHBoxLayout* const buttonsContainerLayout = new QHBoxLayout( buttonsContainer );
buttonsContainerLayout->setSpacing( 0 );
buttonsContainerLayout->setSizeConstraint( QLayout::SetMinAndMaxSize );
buttonsContainerLayout->setMargin( 0 );
buttonsContainerLayout->addWidget( m_buttons, 0, Qt::AlignLeft );
qDebug() << m_buttons->buttons()[ 0 ]->size();
m_scrollArea = new QScrollArea;
m_scrollArea->setContentsMargins( 0, 0, 0, 0 );
m_scrollArea->setWidget( buttonsContainer );
m_scrollArea->setWidgetResizable( true );
m_scrollArea->setStyleSheet( "border: 1px solid blue" );
m_scrollArea->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
firstRowLayout->addWidget( left , 0, Qt::AlignLeft );
firstRowLayout->addWidget( m_scrollArea, 1, Qt::AlignLeft );
firstRowLayout->addWidget( right , 0, Qt::AlignLeft );
m_lineEdit = new QLineEdit;
QPushButton* button = new QPushButton;
QHBoxLayout* secondRowLayout = new QHBoxLayout;
secondRowLayout->addWidget( m_lineEdit );
secondRowLayout->addWidget( button );
connect( button, SIGNAL(clicked()), SLOT(setButtonsCount()) );
mainLayout->addWidget( firstRow, 1, Qt::AlignLeft );
mainLayout->addLayout( secondRowLayout );
button->setText( "Set buttons count" );
buttonsContainer->resize( m_buttons->buttonsOptimalWidth(), buttonsContainer->height() );
m_buttons->resize( m_buttons->buttonsOptimalWidth(), m_buttons->height() );
//area->resize( 100, area->height() );
//area->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
}
MainWidget::~MainWidget()
{
}
void MainWidget::setButtonsCount()
{
m_buttons->setButtonsCount( m_lineEdit->text().toInt() );
}
这是包含问题的整个Qt项目: https://drive.google.com/file/d/0B-mc4aKkzWlxQzlPMEVuNVNKQjg/edit?usp=sharing
答案 0 :(得分:8)
基本步骤是:
包含按钮的容器窗口小部件(您的CheckableButtonGroup
)必须设置QLayout::SetMinAndMaxSize
大小约束。然后它将足够大,可以按住按钮。它的大小政策无关紧要,因为您只需将其放入QScrollArea
,而不是放入另一种布局。
滚动区域需要根据其保存的窗口小部件的大小设置其最大大小。默认实现不会这样做,因此必须通过监视嵌入式窗口小部件的resize事件来实现它。
下面的代码是一个在Qt 4.8和5.2下都能运作的最小例子。
// https://github.com/KubaO/stackoverflown/tree/master/questions/scrollgrow-21253755
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
class ButtonGroup : public QWidget {
Q_OBJECT
QHBoxLayout m_layout{this};
public:
ButtonGroup(QWidget * parent = 0) : QWidget{parent} {
m_layout.setSizeConstraint(QLayout::SetMinAndMaxSize); // <<< Essential
}
Q_SLOT void addButton() {
auto n = m_layout.count();
m_layout.addWidget(new QPushButton{QString{"Btn #%1"}.arg(n+1)});
}
};
class AdjustingScrollArea : public QScrollArea {
bool eventFilter(QObject * obj, QEvent * ev) {
if (obj == widget() && ev->type() == QEvent::Resize) {
// Essential vvv
setMaximumWidth(width() - viewport()->width() + widget()->width());
}
return QScrollArea::eventFilter(obj, ev);
}
public:
AdjustingScrollArea(QWidget * parent = 0) : QScrollArea{parent} {}
void setWidget(QWidget *w) {
QScrollArea::setWidget(w);
// It happens that QScrollArea already filters widget events,
// but that's an implementation detail that we shouldn't rely on.
w->installEventFilter(this);
}
};
class Window : public QWidget {
QGridLayout m_layout{this};
QLabel m_left{">>"};
AdjustingScrollArea m_area;
QLabel m_right{"<<"};
QPushButton m_add{"Add a widget"};
ButtonGroup m_group;
public:
Window() {
m_layout.addWidget(&m_left, 0, 0);
m_left.setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
m_left.setStyleSheet("border: 1px solid green");
m_layout.addWidget(&m_area, 0, 1);
m_area.setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
m_area.setStyleSheet("QScrollArea { border: 1px solid blue }");
m_area.setWidget(&m_group);
m_layout.setColumnStretch(1, 1);
m_layout.addWidget(&m_right, 0, 2);
m_right.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
m_right.setStyleSheet("border: 1px solid green");
m_layout.addWidget(&m_add, 1, 0, 1, 3);
connect(&m_add, SIGNAL(clicked()), &m_group, SLOT(addButton()));
}
};
int main(int argc, char *argv[])
{
QApplication a{argc, argv};
Window w;
w.show();
return a.exec();
}
#include "main.moc"