在不同的平台上文件路径的斜杠也是不一样的,比如linux系统一般都是 / 斜杠,而在windows上都是 \ 两个反斜杠,Qt本身程序内部无论在win还是linux都支持 / 斜杠的路径,但是一些第三方库的话可能需要转换成对应系统的路径,这就需要用到斜杠转换,Qt当然内置类方法。
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巧用QMetaObject::invokeMethod方法可以实现很多效果,包括同步和异步执行,很大程度上解决了跨线程处理信号槽的问题。比如有个应用场景是在回调中,需要异步调用一个public函数,如果直接调用的话会发现不成功,此时需要使用 QMetaObject::invokeMethod(obj, "fun", Qt::QueuedConnection); 这种方式来就可以。invokeMethod函数有很多重载参数,可以传入返回值和执行方法的参数等。invokeMethod函数不仅支持槽函数还支持信号,而且这逼居然是线程安全的,可以在线程中放心使用,牛逼!
//头文件声明信号和槽函数 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::on_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; }
Qt5中的信号是public的,可以在需要的地方直接emit即可,而在Qt4中信号是protected的,不能直接使用,需要定义一个public函数来emit。
Qt5.15版本开始官方不再提供安装包,只提供源码,可以自行编译或者在线安装,估计每次编译各种版本太麻烦,更多的是为了统计收集用户使用信息比如通过在线安装,后期可能会逐步加大商业化力度。
有时候我们需要判断当前Qt版本有没有某个模块可以使用qtHaveModule(Qt5新引入的判断)来判断,如果要判断自己的项目中有没有 QT += 的方式添加的模块,可以用 contains来判断。
qtHaveModule(webenginewidgets) { message("当前Qt库有找到 webenginewidgets 模块") } !qtHaveModule(webkit) { message("当前Qt库没有找到 webkit 模块") } contains(QT, network) { message("当前项目已经引入 network 模块") } !contains(QT, widgets) { message("当前项目没有引入 widgets 模块") }c++11新引入了原始字符串格式,用户避免在字符串中加入转义字符\,可以用于表示json字符串等场景。
QString s1 = R"(test\001.jpg)"; s1.replace("\\", "#"); qDebug()<< s1; //结果 test#001.jpg
安卓上打印信息建议使用 qInfo() 而不是 qDebug() ,qInfo()才有效果。
Qt的默认定时器精度不够高(比如应用场景是1分钟保存一条记录或者文件,当你用默认的定时器的时候你会发现有些时候是60秒而有些是59秒随机的,如果客户有要求这就需要设置精度了。当然我们所做的绝大部分项目也不需要精度非常高的定时器,毕竟精度越高,占用的系统资源可能越大),如果需要设置更高的精度可以设置 setTimerType(Qt::PreciseTimer)。Qt有两种定时器处理,一种是QTimer类,还有一种是QObject类就内置的timeevent事件,如果是QObject类的定时器要设置的话调用 startTimer(interval, Qt::PreciseTimer);
Qt::PreciseTimer 精确的定时器,尽量保持毫秒精度。
Qt::CoarseTimer 粗略的定时器,尽量保持精度在所需的时间间隔5%范围内。
Qt::VeryCoarseTimer 很粗略的定时器,只保留完整的第二精度。
精度再高,也依赖对应的操作系统中断,假设中断需要 5ms,则定时器精度不可能高于5毫秒。
QGraphicsEffect相关类很耗CPU,甚至在绘制的时候和某些地方有冲突干扰,基本上不建议使用,情非得已只建议少量使用和非频繁触发绘制的地方使用。
用QSettings设置注册表,如果不是管理员身份运行会打印 QSettings: failed to set subkey "xxx" (拒绝访问。),你需要手动鼠标右键管理员身份运行就可以。
QLineEdit除了单纯的文本框以外,还可以做很多特殊的处理用途。
限制输入只能输入IP地址。
限制输入范围,强烈推荐使用 QRegExpValidator 正则表达式来处理。
//正在表达式限制输入 QString str = "\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"; ui->lineEdit->setValidator(new QRegExpValidator(QRegExp(str))); //用于占位 ui->lineEdit->setInputMask("000.000.000.000"); #if 0 //下面代码设置浮点数范围限制失败 ui->lineEdit->setValidator(new QDoubleValidator(20, 50, 1)); #else //下面代码设置浮点数范围限制成功 QDoubleValidator *validator = new QDoubleValidator(20, 50, 1); validator->setNotation(QDoubleValidator::StandardNotation); ui->lineEdit->setValidator(validator); #endif //下面代码设置整数范围限制成功 ui->lineEdit->setValidator(new QIntValidator(10, 120)); //其实上面的代码缺陷很多,只能限制只输入小数,无法设定数值范围,很操蛋 //需要来个万能的牛逼的 QRegExpValidator //限制浮点数输入范围为[-180,180] QRegExp regexp("^-?(180|1?[0-7]?\\d(\\.\\d+)?)$"); //限制浮点数输入范围为[-90,90]并限定为小数位后4位 QRegExp regexp("^-?(90|[1-8]?\\d(\\.\\d{1,4})?)$"); QRegExpValidator *validator = new QRegExpValidator(regexp, this); ui->lineEdit->setValidator(validator);