《QDebug 2024年12月》
一、Qt Widgets 问题交流
1.
二、Qt Quick 问题交流
1.QQuickPaintedItem 或者 QQuickItem 绘制的图片 dpi 缩放后模糊
启用 Qt 自带的缩放后,界面会跟随系统设置的 dpi 进行放大缩小:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endifQGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
放大之后,我们在 C++ QQuickPaintedItem 或者 QQuickItem 绘制的图片可能会模糊,如图分别是缩放前和缩放后效果:
在 QQuickPaintedItem 或者 QQuickItem 中获取组件尺寸是放大前的,但是渲染的时候用的尺寸是乘上 dpi 之后的,所以我们绘制时的图像尺寸也要乘上 dpi 值:
QRect rect = boundingRect().toRect();
QImage img(":/flower.jpg");
img = img.scaled(rect.size() * window()->devicePixelRatio(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
2.Popup 或 Dialog 点击弹框外部阴影区域
点击 Popup 或 Dialog 区域外阴影区域时,如果是模态框(modal: true),事件不会穿透下去,需要非模态才可以。通过将模态 modal 属性设置为 false,阴影 dim 属性设置为 true,然后背景放一个 MouseArea 拦截点击事件,就能实现阴影区域可以点击的对话框。
Popup {id: overlay_popanchors.centerIn: parentwidth: 300height: 300modal: falsedim: truepadding: 0closePolicy: Popup.CloseOnEscapeRectangle {anchors.fill: parentcolor: "#555555"}// Overlay.modal: Rectangle {}Overlay.modeless: Rectangle {color: "#55550000"MouseArea {anchors.fill: parentonClicked: {console.log("clicked")}}}}
点击事件的过滤是在组件内部进行的,似乎没别的设置来跳过:
bool QQuickPopupPrivate::blockInput(QQuickItem *item, const QPointF &point) const
{// don't block presses and releases// a) outside a non-modal popup,// b) to popup children/content, or// b) outside a modal popups's background dimmingreturn modal && !popupItem->isAncestorOf(item) && (!dimmer || dimmer->contains(dimmer->mapFromScene(point)));
}bool QQuickPopupPrivate::handlePress(QQuickItem *item, const QPointF &point, ulong timestamp)
{Q_UNUSED(timestamp);pressPoint = point;tryClose(point, QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnPressOutsideParent);return blockInput(item, point);
}bool QQuickPopupPrivate::handleRelease(QQuickItem *item, const QPointF &point, ulong timestamp)
{Q_UNUSED(timestamp);if (item != popupItem && !contains(pressPoint))tryClose(point, QQuickPopup::CloseOnReleaseOutside | QQuickPopup::CloseOnReleaseOutsideParent);pressPoint = QPointF();touchId = -1;return blockInput(item, point);
}
三、其他
1.英特尔上编译的QtCipherSqlitePlugin在M系列芯片上崩溃
QtCipherSqlitePlugin是一个用于支持SQLite数据库加密的插件,目前最新版本是v1.3,已经很久没更新了:https://github.com/devbean/QtCipherSqlitePlugin
英特尔上编译出来在M芯片上兼容运行会报错:
工程的sqlitecipher.pro文件中有一行设置:
QMAKE_CFLAGS += -march=native
去掉之后编译会报aes相关接口错误,我们直接改成aes:
QMAKE_CFLAGS += -maes
编译之后放到M芯片上就能正常运行了
2.安卓版本升级后授权相关的问题
Qt5安卓项目如果在Activity的onCreate请求权限,在之前的安卓版本权限操作结束之前,会阻塞在QApplication对象构造,但最近手机升级到澎湃OS2(安卓15)后,发现阻塞在engine.load去了。之前代码中一些需要权限才能进行的操作就需要后移,目前是放到初始化页面加载后QQmlApplicationEngine::objectCreated信号槽中。当然,最好在每次读写文件等需要权限的操作前都再次判断并请求一下相关权限。
int main(int argc, char *argv[])
{// 安卓老版本阻塞在这里QApplication app(argc, argv);QQmlApplicationEngine engine;const QUrl url(QStringLiteral("qrc:/main.qml"));QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,&app, [url](QObject *obj, const QUrl &objUrl) {if (!obj && url == objUrl)QCoreApplication::exit(-1);}, Qt::QueuedConnection);// 澎湃OS2(安卓15阻塞在这里)engine.load(url);return app.exec();
}