QQuickWidget Custom Resizing Mode

602 views Asked by At

Note: This a self answered question. It cause me some headache to solve it in past, so I think it is worth to share.

I have a qml application designed for HD resolution(1366x768). It's using QtQuick.Layouts, so adaptable to custom resolution. But resizing it to less than HD resolution makes it squishy and meaningless. I am not restricting QQuickWidget's size with minimum size, cause now I'm trying to place multiple of them in grid layout of a QWidget. I want to scale down root item to fit in widget when size of QQuickWidget is less than initial size(1366x768). Problem is QQuickWidget offers only two ResizeMode options and none of them suits to my needs. And it is not possible deactiave ResizeMode. So I'm trying to disable ResizeMode and write a custom one.

1

There are 1 answers

0
Kao On BEST ANSWER

It's kinda ugly but working solution. I checked the source code of QQuickWidget, and realized inner updateSize function does nothing when ResizeMode is invalid.

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(); }

Make sure transformOrigin of root item is TopLeft.

transformOrigin: Item.TopLeft