#qt #qdialog #qscrollarea
#qt #qdialog #qscrollarea
Вопрос:
У меня есть QDialog
и QScrollArea
внутри. Когда содержимое в QScrollArea
маленьком, диалоговое окно также мало. Когда ширина содержимого увеличивается, ширина диалогового окна также увеличивается, но только до некоторого фиксированного значения.
Когда QPushButton
ширина в моем примере составляет около 450 или более, появляется вертикальная полоса прокрутки. Как я могу избежать этого и позволить диалоговому окну расширяться больше?
class Dialog : public QDialog {
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr) : QDialog(parent) {
auto dialogLayout = new QVBoxLayout(this);
auto scrollArea = new QScrollArea(this);
scrollArea->setWidgetResizable(true);
auto scrollWidget = new QWidget(scrollArea);
auto scrollLayout = new QVBoxLayout(scrollWidget);
scrollLayout->setAlignment(Qt::AlignTop);
scrollArea->setWidget(scrollWidget);
dialogLayout->addWidget(scrollArea);
auto button = new QPushButton("Button", this);
button->setFixedSize(500, 30);
scrollLayout->addWidget(button);
}
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
{
auto centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
auto mainLayout = new QVBoxLayout(centralWidget);
auto button = new QPushButton("Dialog", this);
mainLayout->addWidget(button);
connect(button, amp;QPushButton::clicked, this, []() {Dialog().exec();});
}
};
Я пробовал QDialog::setMaximumWidth
и устанавливал политику расширения размера для обоих QDialog
и QScrollArea
, но ничего не помогает
Ответ №1:
QScrollArea ограничивает максимальный размер своего sizeHint()
метода (получается 468 пикселей на моей текущей машине Win7). Вы можете увидеть это здесь. (Я тоже этого до сих пор не знал… не уверен, почему они решили сделать это таким образом.)
Похоже, вам придется повторно реализовать QScrollArea
или найти другую стратегию отображения. Для повторной реализации нам просто нужно переписать sizeHint()
функцию, но без глупого ограничения.
#include <QApplication>
#include <QtWidgets>
class ScrollArea : public QScrollArea
{
public:
ScrollArea(QWidget *parent = nullptr) : QScrollArea(parent) {}
QSize sizeHint() const
{
QSize sz = QScrollArea::viewportSizeHint();
const int f = frameWidth() * 2;
sz = QSize(f, f);
if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOn)
sz.setWidth(sz.width() verticalScrollBar()->sizeHint().width());
if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOn)
sz.setHeight(sz.height() horizontalScrollBar()->sizeHint().height());
return sz;
}
};
class Dialog : public QDialog {
public:
Dialog(QWidget *parent = nullptr) : QDialog(parent) {
auto dialogLayout = new QVBoxLayout(this);
auto scrollArea = new ScrollArea(this);
//scrollArea->setWidgetResizable(true);
auto scrollWidget = new QWidget(this);
auto scrollLayout = new QVBoxLayout(scrollWidget);
auto button = new QPushButton("Button", this);
button->setFixedSize(600, 30);
scrollLayout->addWidget(button);
scrollArea->setWidget(scrollWidget);
dialogLayout->addWidget(scrollArea);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
return Dialog().exec();
}
В качестве небольшого отступа, если вы добавите элементы в область прокрутки в порядке, который я показываю здесь, вам технически не понадобится setWidgetResizable(true)
бит, который я прокомментировал (я заметил, что в исходном порядке, в котором он у вас был, внутренний виджет отображался с неправильным размером).
ДОБАВЛЕНО: Причина sizeHint()
имеет значение, потому что это то, что QDialog
используется для определения его начального размера. Можно также (например) повторно реализовать QDialog::showEvent()
и установить определенный размер для диалогового окна там на основе любых критериев, имеющих смысл.
Комментарии:
1. Большое вам спасибо! О заполнении 2px: может быть, нам нужно добавить
QSize(2 * frameWidth(), 2 * frameWidth())
в sz, как в начале оригинальнойsizeHint()
реализации? ОsetWidgetResizable()
: это требуется, если в моем случае что-то будет добавлено кscrollLayout
послеscrollWidget
установки2. @Kot, добро пожаловать, и да, вы абсолютно правы, добавление
frameWidth() * 2
работает без необходимости дополнительного заполнения. Я отредактировал код в своем ответе.3. В вашем коде ошибка, которую я заметил только сейчас. в
SizeHint
вы проверяете наличиеhorizontalScrollBar
, но добавляетеverticalScrollBar
высоту и наоборот