Qt:在 QScrollArea 中的小部件上调用 setGeometry 时出现奇怪的行为
Qt: Strange behavior when calling setGeometry on a widget in QScrollArea
我的环境如下:
- Qt 5.4,使用
-platform win32-msvc2013 -opengl desktop -no-icu -skip webkit
从源代码构建
- Visual Studio 2013
- Windows 7 x64
考虑以下设置(一个 QScrollArea 包含一个固定大小的居中小部件):
QScrollArea scrollArea;
scrollArea.setAlignment(Qt::AlignCenter);
scrollArea.setWidgetResizable(false);
QWidget scrollAreaWidgetContents;
scrollArea.setWidget(scrollAreaWidgetContents);
现在,我想在我的程序中调整该小部件的大小,如下所示:
int w = 200, h = 200;
scrollAreaWidgetContents.setGeometry(0, 0, w, h);
奇怪的行为来了:
如果 w
和 h
等于当前的宽度和高度(即没有任何变化),则小部件跳转到左上角。
如果 w
和 h
与当前宽度和高度不同,小部件将保持在其居中位置并正确更改其大小。
我已经编写了一个演示该问题的小演示应用程序。如果单击 pushButton_Stay
按钮,小部件将跳转到左上角。
#include <QtWidgets/QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QScrollArea>
QScrollArea *scrollArea;
QWidget *scrollAreaWidgetContents;
QPushButton *pushButton_Up;
QPushButton *pushButton_Down;
QPushButton *pushButton_Stay;
QVBoxLayout *layout;
int w = 200, h = 200;
void sizeUp() {
w += 10;
h += 10;
scrollAreaWidgetContents->setGeometry(0, 0, w, h);
}
void sizeDown() {
w -= 10;
h -= 10;
scrollAreaWidgetContents->setGeometry(0, 0, w, h);
}
void sizeStay() {
scrollAreaWidgetContents->setGeometry(0, 0, w, h);
}
int main(int argv, char **args)
{
QApplication app(argv, args);
// Scroll area
scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(false);
scrollArea->setAlignment(Qt::AlignCenter);
scrollAreaWidgetContents = new QWidget();
scrollAreaWidgetContents->setGeometry(QRect(0, 0, w, h));
scrollAreaWidgetContents->setAutoFillBackground(true);
QPalette Pal(scrollAreaWidgetContents->palette());
Pal.setColor(QPalette::Background, Qt::black);
scrollAreaWidgetContents->setPalette(Pal);
scrollArea->setWidget(scrollAreaWidgetContents);
// Buttons
pushButton_Up = new QPushButton(scrollAreaWidgetContents);
pushButton_Up->setGeometry(QRect(85, 50, 31, 23));
pushButton_Up->setText("+");
pushButton_Down = new QPushButton(scrollAreaWidgetContents);
pushButton_Down->setGeometry(QRect(85, 110, 31, 23));
pushButton_Down->setText("-");
pushButton_Stay = new QPushButton(scrollAreaWidgetContents);
pushButton_Stay->setGeometry(QRect(85, 80, 31, 23));
pushButton_Stay->setText("0");
QObject::connect(pushButton_Up, &QPushButton::clicked, sizeUp);
QObject::connect(pushButton_Stay, &QPushButton::clicked, sizeStay);
QObject::connect(pushButton_Down, &QPushButton::clicked, sizeDown);
// Central layout
layout = new QVBoxLayout;
layout->addWidget(scrollArea);
// Main window
QWidget window;
window.setGeometry(200, 200, 400, 400);
window.setLayout(layout);
window.show();
return app.exec();
}
单击 pushButton_Up
按钮:
单击 pushButton_Stay
按钮:
问题:
这里出了什么问题?
这是一个错误吗?如果是,有人可以确认吗?
如果不是错误,我怎样才能使小部件始终居中?
What's going wrong here?
Is it a bug? An if and yes, can anyone confirm it?
似乎第二次调用 setGeometry
使用相同的参数 使用不同的原点 ,并且坐标 (0, 0) 使小部件移动到左上角角落。您可以使用 setGeometry(100, 50, w, h)
等其他坐标来查看差异。
这里是source code of QWidget::setGeometry
:
if (testAttribute(Qt::WA_WState_Created)) {
d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
d->setDirtyOpaqueRegion();
} else {
data->crect.setTopLeft(r.topLeft());
// ^^^^^^^^^ Could be the reason why (0, 0) move to top-left
data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
setAttribute(Qt::WA_PendingMoveEvent);
setAttribute(Qt::WA_PendingResizeEvent);
}
我个人认为这是一个错误,但在我们确认之前需要提供更多证据。
If it's not a bug, how can I make it that the widget always stays
centered?
实际上,如果您只想调整小部件的大小,则不必调用 setGeometry
。使用 resize
代替:
void sizeStay() {
scrollAreaWidgetContents->resize(w, h);
}
它解决了你的问题。
我的环境如下:
- Qt 5.4,使用
-platform win32-msvc2013 -opengl desktop -no-icu -skip webkit
从源代码构建
- Visual Studio 2013
- Windows 7 x64
考虑以下设置(一个 QScrollArea 包含一个固定大小的居中小部件):
QScrollArea scrollArea;
scrollArea.setAlignment(Qt::AlignCenter);
scrollArea.setWidgetResizable(false);
QWidget scrollAreaWidgetContents;
scrollArea.setWidget(scrollAreaWidgetContents);
现在,我想在我的程序中调整该小部件的大小,如下所示:
int w = 200, h = 200;
scrollAreaWidgetContents.setGeometry(0, 0, w, h);
奇怪的行为来了:
如果 w
和 h
等于当前的宽度和高度(即没有任何变化),则小部件跳转到左上角。
如果 w
和 h
与当前宽度和高度不同,小部件将保持在其居中位置并正确更改其大小。
我已经编写了一个演示该问题的小演示应用程序。如果单击 pushButton_Stay
按钮,小部件将跳转到左上角。
#include <QtWidgets/QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QScrollArea>
QScrollArea *scrollArea;
QWidget *scrollAreaWidgetContents;
QPushButton *pushButton_Up;
QPushButton *pushButton_Down;
QPushButton *pushButton_Stay;
QVBoxLayout *layout;
int w = 200, h = 200;
void sizeUp() {
w += 10;
h += 10;
scrollAreaWidgetContents->setGeometry(0, 0, w, h);
}
void sizeDown() {
w -= 10;
h -= 10;
scrollAreaWidgetContents->setGeometry(0, 0, w, h);
}
void sizeStay() {
scrollAreaWidgetContents->setGeometry(0, 0, w, h);
}
int main(int argv, char **args)
{
QApplication app(argv, args);
// Scroll area
scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(false);
scrollArea->setAlignment(Qt::AlignCenter);
scrollAreaWidgetContents = new QWidget();
scrollAreaWidgetContents->setGeometry(QRect(0, 0, w, h));
scrollAreaWidgetContents->setAutoFillBackground(true);
QPalette Pal(scrollAreaWidgetContents->palette());
Pal.setColor(QPalette::Background, Qt::black);
scrollAreaWidgetContents->setPalette(Pal);
scrollArea->setWidget(scrollAreaWidgetContents);
// Buttons
pushButton_Up = new QPushButton(scrollAreaWidgetContents);
pushButton_Up->setGeometry(QRect(85, 50, 31, 23));
pushButton_Up->setText("+");
pushButton_Down = new QPushButton(scrollAreaWidgetContents);
pushButton_Down->setGeometry(QRect(85, 110, 31, 23));
pushButton_Down->setText("-");
pushButton_Stay = new QPushButton(scrollAreaWidgetContents);
pushButton_Stay->setGeometry(QRect(85, 80, 31, 23));
pushButton_Stay->setText("0");
QObject::connect(pushButton_Up, &QPushButton::clicked, sizeUp);
QObject::connect(pushButton_Stay, &QPushButton::clicked, sizeStay);
QObject::connect(pushButton_Down, &QPushButton::clicked, sizeDown);
// Central layout
layout = new QVBoxLayout;
layout->addWidget(scrollArea);
// Main window
QWidget window;
window.setGeometry(200, 200, 400, 400);
window.setLayout(layout);
window.show();
return app.exec();
}
单击 pushButton_Up
按钮:
单击 pushButton_Stay
按钮:
问题:
这里出了什么问题?
这是一个错误吗?如果是,有人可以确认吗?
如果不是错误,我怎样才能使小部件始终居中?
What's going wrong here?
Is it a bug? An if and yes, can anyone confirm it?
似乎第二次调用 setGeometry
使用相同的参数 使用不同的原点 ,并且坐标 (0, 0) 使小部件移动到左上角角落。您可以使用 setGeometry(100, 50, w, h)
等其他坐标来查看差异。
这里是source code of QWidget::setGeometry
:
if (testAttribute(Qt::WA_WState_Created)) {
d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
d->setDirtyOpaqueRegion();
} else {
data->crect.setTopLeft(r.topLeft());
// ^^^^^^^^^ Could be the reason why (0, 0) move to top-left
data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
setAttribute(Qt::WA_PendingMoveEvent);
setAttribute(Qt::WA_PendingResizeEvent);
}
我个人认为这是一个错误,但在我们确认之前需要提供更多证据。
If it's not a bug, how can I make it that the widget always stays centered?
实际上,如果您只想调整小部件的大小,则不必调用 setGeometry
。使用 resize
代替:
void sizeStay() {
scrollAreaWidgetContents->resize(w, h);
}
它解决了你的问题。