首页 文章

Qt:在QScrollArea中的小部件上调用setGeometry时出现奇怪的行为

提问于
浏览
3

我的环境如下:

  • 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);

And here comes the strange behavior:
如果 wh 等于当前的宽度和高度(即没有任何变化),则小部件跳转到左上角 .
如果 wh 与当前宽度和高度不同,则窗口小部件将保持在其居中位置并正确更改其大小 .

我编写了一个演示该问题的小型演示应用程序 . 如果单击 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 按钮:

First picture

单击 pushButton_Stay 按钮:

Second picture

Questions:

这里出了什么问题?

这是一个错误吗?一个if和yes,任何人都可以确认吗?

如果它不是一个错误,我怎么能让小部件始终保持居中?

1 回答

  • 2

    这里出了什么问题?这是一个错误吗?一个if和yes,任何人都可以确认吗?

    似乎 setGeometry 的第二次调用具有相同的参数 use different origin ,并且坐标(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);
    }
    

    我个人认为这是一个错误,但在我们确认之前需要提供更多证据 .


    如果它不是一个错误,我怎么能让小部件始终保持居中?

    实际上,如果您只想调整小部件的大小,则不必调用 setGeometry . 请改用resize

    void sizeStay() {
        scrollAreaWidgetContents->resize(w, h);
    }
    

    它解决了你的问题 .

相关问题