《QDebug 2023年5月》

一、Qt Widgets 问题交流

1.在 VS 中双击打开 ui 文件后,过一会儿 Qt Designer 就闪退

我是在 Windows11 + VS2019/2022 环境遇到这个问题,解决方法是设置 Run in detached window 为 True。

点击 "扩展->QT VS Tools->Options",对话框中左侧选择 "Qt->General";或者点击 "工具->选项" 也能进到这个设置界面。

网上也有其他相关的解决方案,比如:

VS打开Qt的ui界面后闪退(ui无法打开文件)的解决办法_vs打开qt闪退_严就方法的博客-CSDN博客

二、Qt Quick 问题交流

1.Qt6 Controls 组件样式自定义报错且样式异常

根据 Qt5 的经验,我新建一个 MyButton.qml 文件自定义按钮组件,import Controls 模块,然后对样式自定义。

import QtQuick
import QtQuick.Controls

Button {
    id: control
    implicitWidth: 90
    implicitHeight: 30
    text: qsTr("Button")

    contentItem: Text {
        text: control.text
        font: control.font
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
    }

    background: Rectangle {
        border.color: control.down ? "cyan" : "red"
        border.width: 1
        color: "gray"
    }
}

但是运行后报错:QML Rectangle: The current style does not support customization of this control... ...

同时,样式也不完全是我们设置的样式 。

先说解决方案:

1.参考 Quick Controls 源码 import QtQuick.Templates 中的类型自定义;

2.import QtQuick.Controls.Basic 使用 Basic 样式自定义(或者其他非 native 样式);

3.main 函数设置 QQuickStyle::setStyle("Basic") 全局设置 Basic 就不用单独 import Basic 了(或者其他非 native 样式)。

接下来找到源码报错的地方:

//qquickcontrol.cpp
void QQuickControlPrivate::warnIfCustomizationNotSupported(QObject *control, QQuickItem *item, const QString &propertyName)
{
    static const bool ignoreWarnings = [](){
        return qEnvironmentVariableIntValue("QT_QUICK_CONTROLS_IGNORE_CUSTOMIZATION_WARNINGS");
    }();
    if (ignoreWarnings)
        return;

    if (!control->property("__notCustomizable").toBool()
            || (item && item->property("__ignoreNotCustomizable").toBool()))
        return;

    qmlWarning(item ? item : control).nospace() << "The current style does not support customization of this control "
        << "(property: " << propertyName << " item: " << item << "). "
        "Please customize a non-native style (such as Basic, Fusion, Material, etc). For more information, see: "
        "https://doc.qt.io/qt-6/qtquickcontrols2-customize.html#customization-reference";
}
//DefaultButton.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.impl
import QtQuick.Templates as T
import QtQuick.NativeStyle as NativeStyle

T.Button {
    id: control

    readonly property bool __nativeBackground: background instanceof NativeStyle.StyleItem
    readonly property bool __notCustomizable: true
    //... ...
}

原来是默认的 native 样式代码里标注了 __notCustomizable 属性,我尝试覆盖这个属性,但也只是警告没了,hover 样式仍然是错误的。

原来是类型有没导出的属性,没法覆盖掉,所以还是得替换掉 native 版本的实现:

import QtQuick
import QtQuick.Controls.impl
import QtQuick.NativeStyle as NativeStyle

NativeStyle.DefaultButton {
    id: control

    background: NativeStyle.Button { ... ...}

    NativeStyle.Button {
        id: hoverButton
        control: control
        x: background.x
        y: background.y
        width: background.width
        height: background.height
        useNinePatchImage: false
        overrideState: NativeStyle.StyleItem.AlwaysHovered
        opacity: control.hovered ? 1 : 0
        visible: opacity !== 0
        Behavior on opacity { NumberAnimation { duration: hoverButton.transitionDuration } }
    }

    contentItem: IconLabel { ... ... }
}

2.Qt6 QML 在 QVariant 解析上的一点小区别

先上代码:

#pragma once
#include <QObject>
#include <QVariant>

class MyItem : public QObject
{
    Q_OBJECT
public:
    using QObject::QObject;

    Q_INVOKABLE QVariant getChar() {
        return QVariant::fromValue(char{65});
    }
    Q_INVOKABLE QVariant getInt8() {
        return QVariant::fromValue(int8_t{65});
    }
    Q_INVOKABLE QVariant getUint8() {
        return QVariant::fromValue(uint8_t{65});
    }
};
    MyItem {
        id: item
        Component.onCompleted: {
            var c8 = item.getChar()
            var i8 = item.getInt8()
            var u8 = item.getUint8()
            console.log(typeof c8, c8)
            console.log(typeof i8, i8)
            console.log(typeof u8, u8)
        }
    }

如果是 Qt5,打印如下:

唯独 int8 转成了特殊的对象显示为字符 A,其他是数字,并且这个对象还不能用 parseInt 转换,只能用属性绑定或赋值来中转一下转成 int。

但是在 Qt6,三者的类型统一了:

三、其他

1.Qt5 和 Qt6 非整数倍 dpi 缩放的测试

Qt5 的时候对 dpi 非整数倍缩放的支持不太好,Qt6 在这方面进行了优化,测试一下。

测试环境:Win10 + Qt5.15.2/Qt6.5.1

测试代码:https://github.com/gongjianbo/MyTestCode/tree/master/Qt/TestQt_20230529_DpiScaleTest

主要是对比 Qt::HighDpiScaleFactorRoundingPolicy::PassThrough 的效果,以及 qt.conf 设置 WindowsArguments=dpiawareness=0 的效果。

实测 qt.conf 的方式没啥改进仍然比较模糊,而 PassThrough 在 Qt6 修复了很多渲染问题,效果看起来还不错。

//qt.conf
[Platforms]
WindowsArguments=dpiawareness=0
//main.cpp
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    // 这是 qt6 的默认策略,而 qt5 默认是没开启缩放的
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
    // qt5 默认 Round 四舍五入,qt6 默认 PassThrough 允许小数值
    QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif

有一些要注意的地方:Qt5 和 Qt6 默认字体设置有区别;Qt6 默认开启 dpi 缩放还把 AA_DisableHighDpiScaling 给废掉了,我测试了一些其他的接口来恢复不缩放的效果:

    // 关闭缩放
    // https://doc.qt.io/qt-6/highdpi.html
    // 参见文档,仅用于测试,且不支持 mac os 和 wayland 平台
    qputenv("QT_ENABLE_HIGHDPI_SCALING", "0");

    // 设置固定 dpi
    // windows 默认是 96 dpi,mac 似乎是 72
    // AA_Use96Dpi 在 mac os 以及 qt6 似乎没效果这里用变量设置
    qputenv("QT_FONT_DPI", "96");

下面是对比图:

a.Qt5 使用 PassThrough 在 125% 缩放下的效果:

Widgets:QPainter 绘图模糊,pt 字号的文字显示不完整;

QML:框线会有加粗的情况,如果是有 layer 会比较模糊,文字用 native 渲染有锯齿或者撕裂感。(变粗可以设置 QSurfaceFormat 多重采样)

a.Qt6 使用 PassThrough 在 125% 缩放下的效果 :

效果感觉还不错

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龚建波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值