2014-01-21 2 views
3

У меня есть QScrollArea с некоторыми кнопками в нем, как показано на картинке. enter image description hereQScrollArea с динамически меняющимся содержимым

Идея макета: 1. Кнопка влево и вправо следует использовать для прокрутки кнопок, когда они слишком широки

2. количество кнопок в области прокрутки можно изменить динамически 3. Любое свободное пространство должно использоваться, чтобы максимально расширить область прокрутки. Если такое пространство не существует, кнопки навигации должны использоваться для прокрутки.

С моей текущей реализации, когда я увеличиваю кнопки у меня есть это: enter image description here

Но есть свободное пространство справа, так что это должно выглядеть следующим образом: enter image description here

Если я увеличить еще раз 10, например, должна появиться полоса прокрутки (потому что макет установлен в виде виджета).

Я хочу знать, есть ли другой путь в стороне от ручного изменения размера виджетов (потому что пользовательский интерфейс может быть переведен и кнопки можно изменить размер намек также реальная конструкция сложнее :(

Вот моя реализация виджета 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

ответ

6

существенные шаги:

  1. Контейнер виджет, который держит кнопки (ваш CheckableButtonGroup) должен быть указан QLayout::SetMinAndMaxSize ограничение размера а. Тогда он будет достаточно большим, чтобы удерживать кнопки. Его размерная политика не имеет значения, поскольку вы просто помещаете ее в QScrollArea, а не в другую компоновку.

  2. Область прокрутки должна установить максимальный размер в соответствии с размером виджета, который он удерживает. Реализация по умолчанию не делает этого, поэтому его нужно реализовать, просмотрев события изменения размера встроенного виджета.

Приведенный ниже код является минимальным примером, который работает как под Qt 4.8, так и 5.2.

Screenshot with two buttons

Screenshot with multiple buttons

// 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" 
+0

У меня аналогичная прокрутки-область и мне было просто интересно, если это возможно, чтобы эти нажимные кнопки расположены 4 кнопки/строку (как я увидел приведенный выше пример). [?] –

+0

@groenhen Уверен, что можно устроить их так, как вы хотите. –

+0

Уже сделано. Теперь я пытаюсь выяснить способ получить однострочный пробел, я хочу пропустить одну строку и поместить новые кнопки после этого «виртуального» пространства ... –

Смежные вопросы