Не удается автоматически изменить размер QScrollArea - PullRequest
0 голосов
/ 24 января 2019

Моя среда:

  • Windows 10, 64-битная
  • Microsoft Visual Studio 2015
  • Qt 5.6.2
  • Qt Creator 4.8.1

У меня есть диалоговое окно, содержащее область прокрутки. Область прокрутки изначально пуста:

empty scroll area

Когда пользователь нажимает флажок, виджеты добавляются в область прокрутки:

widgets added, scroll area not resized

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

widgets added, manually resized

Чего не хватает в моем коде?

Я уменьшил проблему до минимального примера программы (из которой были сделаны вышеупомянутые снимки). Вот код:

scroll_area.pro:

QT += widgets
TEMPLATE = app
SOURCES += main.cpp my_dialog.cpp
HEADERS += my_dialog.h my_widget.h
TARGET = ScrollArea

main.cpp:

#include "my_dialog.h"
#include <QApplication>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    MyDialog myDialog;
    myDialog.show();
    return app.exec();
}

my_dialog.h:

#ifndef MY_DIALOG_H
#define MY_DIALOG_H

#include <QBoxLayout>
#include <QDialog>
#include <QScrollArea>

class MyDialog : public QDialog
{
    Q_OBJECT

public:
    MyDialog();

private:
    QScrollArea* m_scrollArea;
    QHBoxLayout* m_hLayout;

private slots:
    void changeScrollArea(int newState);
};

#endif // MY_DIALOG_H

my_dialog.cpp:

#include "my_dialog.h"
#include "my_widget.h"
#include <QCheckBox>
#include <QDialogButtonBox>

MyDialog::MyDialog() :
    QDialog(nullptr), m_scrollArea(new QScrollArea(this)), m_hLayout(new QHBoxLayout())
{
    setWindowTitle("My Dialog");

    QVBoxLayout* vlayout = new QVBoxLayout(this);

    // Set up the scroll area.
    m_scrollArea->setBackgroundRole(QPalette::ColorRole::Light);
    m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    vlayout->addWidget(m_scrollArea);

    // Set up the scroll contents.
    QWidget* scrollContents = new QWidget(this);
    scrollContents->setLayout(m_hLayout);
    m_scrollArea->setWidget(scrollContents);

    // Set up the check box.
    QCheckBox* checkbox = new QCheckBox("Check to add widgets", this);
    connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(changeScrollArea(int)));
    vlayout->addWidget(checkbox);
}

void MyDialog::changeScrollArea(int newState)
{
    // Set up the horizontal layout.
    m_hLayout->deleteLater();
    m_hLayout = new QHBoxLayout();

    // Set up the scroll contents.
    QWidget* scrollContents = new QWidget(this);
    scrollContents->setLayout(m_hLayout);
    if (newState == Qt::Checked)
    {
        m_hLayout->addWidget(new MyWidget(scrollContents));
        m_hLayout->addWidget(new MyWidget(scrollContents));
    }
    m_scrollArea->setWidget(scrollContents);
}
* * My_widget.h тысяча сорок-девять
#ifndef MY_WIDGET_H
#define MY_WIDGET_H

#include <QGridLayout>
#include <QPushButton>

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    MyWidget(QWidget* parent) : QWidget(parent)
    {
        QGridLayout* gridLayout = new QGridLayout(this);

        for (int row = 0; row < 5; ++row)
        {
            for (int column = 0; column < 1; ++column)
            {
                QPushButton* button = new QPushButton("FOO");
                gridLayout->addWidget(button, row, column);
            }
        }
    }
};

#endif // MY_WIDGET_H

1 Ответ

0 голосов
/ 24 января 2019

QScrollArea не будет изменять размер в соответствии с его содержимым, поскольку его задача состоит в создании виджета, который может иметь большой размер в области просмотра, поэтому решение состоит в том, чтобы изменить размер с помощью кода:

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H

#include <QDialog>

class QScrollArea;
class QHBoxLayout;

class MyDialog : public QDialog
{
    Q_OBJECT
public:
    MyDialog();
private:
    QScrollArea* m_scrollArea;
    QHBoxLayout* m_hLayout;
private slots:
    void changeScrollArea(int newState);
    void adjust();
};
#endif // MYDIALOG_H

mydialog.cpp

#include "mydialog.h"
#include "mywidget.h"

#include <QCheckBox>
#include <QHBoxLayout>
#include <QScrollArea>
#include <QScrollBar>
#include <QTimer>

MyDialog::MyDialog() :
    QDialog(nullptr), m_scrollArea(new QScrollArea), m_hLayout(new QHBoxLayout())
{
    setWindowTitle("My Dialog");
    QVBoxLayout* vlayout = new QVBoxLayout(this);
    // Set up the scroll area.
    m_scrollArea->setBackgroundRole(QPalette::ColorRole::Light);
    m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    m_scrollArea->setWidgetResizable(true);
    vlayout->addWidget(m_scrollArea);
    // Set up the scroll contents.
    QWidget* scrollContents = new QWidget;
    scrollContents->setLayout(m_hLayout);
    m_scrollArea->setWidget(scrollContents);
    // Set up the check box.
    QCheckBox* checkbox = new QCheckBox("Check to add widgets");
    connect(checkbox, &QCheckBox::stateChanged, this, &MyDialog::changeScrollArea);
    vlayout->addWidget(checkbox);
}
void MyDialog::changeScrollArea(int newState)
{
    m_hLayout->deleteLater();
    // Set up the scroll contents.
    QWidget* scrollContents = new QWidget;
    // Set up the horizontal layout.
    m_hLayout = new QHBoxLayout(scrollContents);
    if (newState == Qt::Checked)
    {
        m_hLayout->addWidget(new MyWidget(scrollContents));
        m_hLayout->addWidget(new MyWidget(scrollContents));
    }
    m_scrollArea->setWidget(scrollContents);
    m_scrollArea->resize(m_scrollArea->minimumSizeHint());
    resize(sizeHint());
    QTimer::singleShot(0, this, &MyDialog::adjust);
}

void MyDialog::adjust()
{
    const QSize max_size(1000, 1000);
    const int step = 5;
    while (m_scrollArea->verticalScrollBar()->isVisible() && height() < max_size.height())
        resize(width(), height() + step);
    while (m_scrollArea->horizontalScrollBar()->isVisible() && width() < max_size.width())
        resize(width()+step, height());
}
...