一、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 渲染有锯齿或者撕裂感。
a.Qt6 使用 PassThrough 在 125% 缩放下的效果 :
效果感觉还不错