找回密码
 立即注册
收起左侧

Qt开发经验小技巧111-120

0
回复
219
查看
[复制链接]
累计签到:7 天
连续签到:1 天
来源: 2021-4-19 09:18:14 显示全部楼层 |阅读模式

马上注册,查看详细内容!注册请先查看:注册须知

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
111. 在不同的平台上文件路径的斜杠也是不一样的,比如linux系统一般都是 / 斜杠,而在windows上都是 \\ 两个反斜杠,Qt本身程序内部无论在win还是linux都支持 / 斜杠的路径,但是一些第三方库的话可能需要转换成对应系统的路径,这就需要用到斜杠转换,Qt当然内置类方法。
```cpp
QString path = "C:/temp/test.txt";
path = QDir::toNativeSeparators(path);
//输出 C:\\temp\\test.txt

QString path = "C:\\temp\\test.txt";
path = QDir::toNativeSeparators(path);
//输出 C:/temp/test.txt
```

112. 巧用QMetaObject::invokeMethod方法可以实现很多效果,包括同步和异步执行,很大程度上解决了跨线程处理信号槽的问题。比如有个应用场景是在回调中,需要异步调用一个public函数,如果直接调用的话会发现不成功,此时需要使用 QMetaObject::invokeMethod(obj, "fun", Qt:ueuedConnection); 这种方式来就可以。invokeMethod函数有很多重载参数,可以传入返回值和执行方法的参数等。invokeMethod函数不仅支持槽函数还支持信号,而且这逼居然是线程安全的,可以在线程中放心使用,牛逼!
```cpp
//头文件声明信号和槽函数
signals:
    void sig_test(int type,double value);
private slots:
    void slot_test(int type, double value);

//构造函数关联信号槽
connect(this, SIGNAL(sig_test(int, double)), this, SLOT(slot_test(int, double)));
//单击按钮触发信号和槽,这里是同时举例信号槽都可以
void MainWindow:n_pushButton_clicked()
{
    QMetaObject::invokeMethod(this, "sig_test", Q_ARG(int, 66), Q_ARG(double, 66.66));
    QMetaObject::invokeMethod(this, "slot_test", Q_ARG(int, 88), Q_ARG(double, 88.88));
}
//会打印 66 66.66 和 88 88.88
void MainWindow::slot_test(int type, double value)
{
    qDebug() << type << value;
}
```

113. Qt5中的信号是public的,可以在需要的地方直接emit即可,而在Qt4中信号是protected的,不能直接使用,需要定义一个public函数来emit。

114. Qt5.15版本开始官方不再提供安装包,只提供源码,可以自行编译或者在线安装,估计每次编译各种版本太麻烦,更多的是为了统计收集用户使用信息比如通过在线安装,后期可能会逐步加大商业化力度。

115. 有时候我们需要判断当前Qt版本有没有某个模块可以使用qtHaveModule(Qt5新引入的判断)来判断,如果要判断自己的项目中有没有 QT += 的方式添加的模块,可以用 contains来判断。
```cpp
qtHaveModule(webenginewidgets) {
message("当前Qt库有找到 webenginewidgets 模块")
}

!qtHaveModule(webkit) {
message("当前Qt库没有找到 webkit 模块")
}

contains(QT, network) {
message("当前项目已经引入 network 模块")
}

!contains(QT, widgets) {
message("当前项目没有引入 widgets 模块")
}
```

116. c++11新引入了原始字符串格式,用户避免在字符串中加入转义字符\,可以用于表示json字符串等场景。
```cpp
QString s1 = R"(test\001.jpg)";
s1.replace("\\", "#");
qDebug()<< s1;
//结果 test#001.jpg
```

117. 安卓上打印信息建议使用 qInfo() 而不是 qDebug() ,qInfo()才有效果。

118. Qt的默认定时器精度不够高(比如应用场景是1分钟保存一条记录或者文件,当你用默认的定时器的时候你会发现有些时候是60秒而有些是59秒随机的,如果客户有要求这就需要设置精度了。当然我们所做的绝大部分项目也不需要精度非常高的定时器,毕竟精度越高,占用的系统资源可能越大),如果需要设置更高的精度可以设置 setTimerType(Qt:reciseTimer)。Qt有两种定时器处理,一种是QTimer类,还有一种是QObject类就内置的timeevent事件,如果是QObject类的定时器要设置的话调用 startTimer(interval, Qt:reciseTimer);
- Qt:reciseTimer 精确的定时器,尽量保持毫秒精度。
- Qt::CoarseTimer 粗略的定时器,尽量保持精度在所需的时间间隔5%范围内。
- Qt::VeryCoarseTimer 很粗略的定时器,只保留完整的第二精度。
- 精度再高,也依赖对应的操作系统中断,假设中断需要 5ms,则定时器精度不可能高于5毫秒。

119. QGraphicsEffect相关类很耗CPU,甚至在绘制的时候和某些地方有冲突干扰,基本上不建议使用,情非得已只建议少量使用和非频繁触发绘制的地方使用。

120. 用QSettings设置注册表,如果不是管理员身份运行会打印 QSettings: failed to set subkey "xxx" (拒绝访问。),你需要手动鼠标右键管理员身份运行就可以。

Qt开发经验开源主页(持续更新):
1. [https://gitee.com/feiyangqingyun/qtkaifajingyan](https://gitee.com/feiyangqingyun/qtkaifajingyan)
2. [https://github.com/feiyangqingyun/qtkaifajingyan](https://github.com/feiyangqingyun/qtkaifajingyan)

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册