QT中关于将窗口大小调整为其子项大小的再次说明

3
已经有类似的问题被问过,但没有得到清晰的答案,所以我要再问一遍。假设我们有一个QMainWindow和一个内部的QScrollArea。我在程序中调整了QScrollArea的大小,希望窗口也能相应调整大小。 下面的代码几乎可以正确地工作:当新图片大于旧图片时,窗口大小会增加。然而,当新图片比旧图片小时,窗口不会变小,而是只有QScrollArea变小,导致QScrollArea与其他元素(标签、按钮)之间出现了空隙。
class PictureDialog : public QMainWindow {
Q_OBJECT

public:
    PictureDialog() : QMainWindow() {
        QWidget* canvas = new QWidget(this);
        setCentralWidget(canvas);
        QVBoxLayout* layout = new QVBoxLayout(canvas);
        imageLabel = new QLabel(" ");
        imageLabel->setStyleSheet("QLabel { background-color : white; color : black; }");
        scrollArea = new QScrollArea(this);
        scrollArea->resize(300, 300);
        scrollArea->setBackgroundRole(QPalette::Dark);
        scrollArea->setWidget(imageLabel);
        layout->addWidget(scrollArea);
        imgnamelabel = new QLabel(tr("Picture: "), this);
        layout->addWidget(imgnamelabel);
        QHBoxLayout *hlayout = new QHBoxLayout();
        layout->addLayout(hlayout);
        yesButton = new QPushButton(QPixmap(":pics/yes.png"), QString::null, this);
        yesButton->setShortcut(Qt::Key_Plus);
        yesButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
        hlayout->addWidget(yesButton);
        noButton = new QPushButton(QPixmap(":pics/no.png"), QString::null, this);
        noButton->setShortcut(Qt::Key_Minus);
        noButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
        hlayout->addWidget(noButton);
        hlayout->addStretch();
        connect(yesButton, SIGNAL(clicked()), SLOT(hide()));
        connect(noButton, SIGNAL(clicked()), SLOT(hide()));
    }

    void setPicture(QString imagePath, bool showNo) {
        imgnamelabel->setText(tr("Picture: ") + imagePath);
        if (!QFile::exists(imagePath)) {
            imageLabel->setText(tr("Picture file not found: ") + imagePath);
            imageLabel->resize(imageLabel->fontMetrics().boundingRect(imageLabel->text()).width(),
                               imageLabel->fontMetrics().boundingRect(imageLabel->text()).height());
        } else {
            QImage image(imagePath);
            if (image.isNull()) {
                imageLabel->setText(tr("Failed to open picture file: ") + imagePath);
                imageLabel->resize(imageLabel->fontMetrics().boundingRect(imageLabel->text()).width(),
                                imageLabel->fontMetrics().boundingRect(imageLabel->text()).height());
            } else {
                imageLabel->setPixmap(QPixmap::fromImage(image));
                imageLabel->resize(image.width(), image.height());
            }
        }

        scrollArea->setFixedSize(mini(imageLabel->width() + 20, QApplication::desktop()->screenGeometry().width() * 8 / 10),
                                 mini(imageLabel->height() + 20, QApplication::desktop()->screenGeometry().height() * 8 / 10));
        adjustSize();
        updateGeometry();
        if (showNo)
            noButton->setEnabled(true);
        else
            noButton->setEnabled(false);
    }

    QPushButton *yesButton, *noButton;

private:
    QLabel *imageLabel;
    QLabel *imgnamelabel;
    QScrollArea* scrollArea;
};

你可以调整ScrollArea::widgetResizable属性,或者用QWidget(QLabel)::minimumSizeHint(),也可以从已加载的QPixmap::size()中获取尺寸。 - Chugaister
你有查看过adjustSize()文档中的这段话吗?“对于Windows系统,屏幕尺寸也会被考虑在内。如果sizeHint()小于(200, 100)并且大小策略是扩展的,那么窗口至少会是(200, 100)。” - galinette
尝试在调用adjustSize()之前添加打印QScrollArea的sizeHint()的QDebug行。 - galinette
也许使用不同的大小策略会有所帮助? - Trilarion
1个回答

1

几个月前我遇到过类似的问题(与Qt SQL表视图有关)。

简而言之:在调整MainWindow的大小之前,尝试添加CentralWidget->adjustSize()行。

示例:

...
scrollArea->setFixedSize(...);
canvas->adjustSize();
adjustSize();
updateGeometry();
...
说明: 在我的情况下,关键因素是我一直在使用MainWindow + CentralWidget组合来呈现UI。
当您尝试调整一个"CentralWidgeted" MainWindow的大小以适应其内容的大小时,它将采用CentralWidget的大小作为内容大小。在这种情况下,MainWindow的adjustSize()方法尝试将窗口调整为CentralWidget的大小,但CentralWidget仍具有原始的(更大的)大小[1],因此MainWindow保持其原始大小。
[1]: 有些小部件可能能够自动调整大小(我无法特别回忆起任何一个,但我确信有一些),但在您的代码中,您使用一个简单的QWidget作为CentralWidget,而QWidget缺乏这种功能(就像QMainWindows一样)。在使用这样的“自动调整大小”小部件的情况下,可以省略调整CentralWidget的大小。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接