当我将 window 移动到具有不同 DPI 的屏幕时,为什么我的 QML 项目没有被缩放?

Why aren't my QML items being scaled when I move the window to a screen with a different DPI?

我正在使用 Windows 10 和 Qt 5.15.1。当我将我的 QML 应用程序 window 从低 DPI 屏幕(100% 比例)移动到高 DPI(125% 比例)屏幕时,window 按预期放大(调整大小)以使用更多像素.这使得 window 在两个屏幕上看起来物理尺寸相同。

但是 window 中的项目不会缩放 -- 它们保持相同的像素数。所以所有项目在高 DPI 屏幕上看起来都更小了。

当我在具有不同 DPI 的屏幕之间移动 window 时,如何让项目缩放(到相同的物理尺寸)?我希望所有项目都出现这种情况,例如文本、按钮、矩形等。

我的 QML 是:

import QtQuick 2.12
import QtQuick.Controls 2.12

ApplicationWindow {
    visible: true
    width: 240
    height: 60

    Text {
        text: "Hello World"
        font.pointSize: 14
    }

}

我的 Python 是:

QtCore.QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QtCore.QCoreApplication.setAttribute(Qt.AA_UseOpenGLES)

app = QtWidgets.QApplication([])

engine = QtQml.QQmlEngine()
context = QtQml.QQmlContext(engine.rootContext())
designer = QtQml.QQmlComponent(engine, 'main.qml')
designer.create(context)

app.exec_()

使用更高的 DPI 会改变应用的尺寸,这对我来说真的很奇怪。不过,它并没有真正“缩放”它。它只是让 window 变大。而且您没有将 Rectangle 的大小绑定到 ApplicationWindow,所以这就是它保持相同大小的原因。这里的简单答案是您可以这样做:

    Rectangle {
        anchors.fill: parent
        color: "green"
    }

这将使矩形保持与应用程序相同的大小。

如果您确实希望应用程序的所有内容(包括 Rectangle 的子项)随着 ApplicationWindow 改变大小而缩放,那么您可以这样做:

ApplicationWindow {
    visible: true
    width: defaultWidth
    height: defaultHeight

    property real defaultWidth: 320
    property real defaultHeight: 240

    Rectangle {
        width: defaultWidth
        height: defaultHeight
        color: "green"

        transform: Scale { 
            xScale: parent.width / defaultWidth
            yScale: parent.height / defaultHeight
        }
    }
}

我了解到 Qt rounds DPI scaling 默认为整数。所以在我的屏幕上,缩放比例为 125%,它被四舍五入为 100%...因此没有变化。

可以通过将 QT_SCALE_FACTOR_ROUNDING_POLICY 环境变量设置为 PassThrough 来禁用此行为 as of Qt 5.14。或者在代码中:

QtGui.QGuiApplication.setHighDpiScaleFactorRoundingPolicy(
    Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)

或者,如果您知道显示器的比例因子,则可以通过设置 QT_SCREEN_SCALE_FACTORS 环境变量直接指定它们,例如 QT_SCREEN_SCALE_FACTORS=1.25\;1

所以现在我的两个屏幕都得到了预期的自动缩放。