QQuickWidget 自定义调整大小模式

QQuickWidget Custom Resizing Mode

注意:这是一个自我回答的问题。以前解决的时候很头疼,所以觉得值得分享一下。

我有一个专为高清分辨率 (1366x768) 设计的 qml 应用程序。它使用 QtQuick.Layouts,因此可以适应自定义分辨率。但是将其调整为小于高清分辨率会使它变软且毫无意义。我没有用最小尺寸限制 QQuickWidget 的尺寸,因为现在我正试图将它们中的多个放置在 QWidget 的网格布局中。当 QQuickWidget 的大小小于初始大小 (1366x768) 时,我想缩小根项目以适应小部件。问题是 QQuickWidget 只提供了两个 ResizeMode 选项,其中 none 适合我的需要。而且不可能停用 ResizeMode。所以我试图禁用 ResizeMode 并编写一个自定义的。

这个解决方案有点丑陋但可行。我检查了 source code of QQuickWidget, and realized inner updateSize function does nothing when ResizeMode 是无效的。

CustomQuickWidget(QWidget* parent = nullptr)
    : QQuickWidget(parent) 
{
    //set invalid resize mode for custom resizing
    setResizeMode(static_cast<QQuickWidget::ResizeMode>(-1));
    setSource(QML_SOURCE);
}

void CustomQuickWidget::resizeEvent(QResizeEvent *event) {
    QQuickWidget::resizeEvent(event);

    const int eventWidth = event->size().width();
    const int eventHeight = event->size().height();
    const int initialWidth = initialSize().width();
    const int initialHeight = initialSize().height();

    if (eventWidth >= initialWidth && eventHeight >= initialHeight) {
        // SizeRootObjectToView
        rootObject()->setSize(event->size());
        rootObject()->setScale(1);
    }
    else {
        // Scale down
        const qreal widthScale = qreal(eventWidth) / initialWidth;
        const qreal heightScale = qreal(eventHeight) / initialHeight;

        if (widthScale < heightScale) {
            // stretch height to fill
            rootObject()->setWidth(initialWidth);
            rootObject()->setHeight(qMin(int(eventHeight / widthScale), maximumHeight()));
            rootObject()->setScale(widthScale);
        }
        else {
            // stretch width to fill
            rootObject()->setWidth(qMin(int(eventWidth / heightScale), maximumWidth()));
            rootObject()->setHeight(initialHeight);
            rootObject()->setScale(heightScale);
        }
    }
}

QSize CustomQuickWidget::sizeHint() const { return initialSize(); }

确保根项目的 transformOriginTopLeft

transformOrigin: Item.TopLeft