Qt资源文件编译缓慢

当Qt中编译资源文件太大时,效率很低,或者需要修改资源文件中的文件比如图片、样式表等,需要重新编译可执行文件,这样很不友好,当然Qt都给我们考虑好了策略,此时可以将资源文件转化为二进制的rcc文件,这样就将资源文件单独出来了,可在需要的时候动态加载。
  1. //Qt中使用二进制资源文件方法如下
  2. //将qrc编译为二进制文件rcc,在控制台执行下列命令
  3. rcc -binary main.qrc -o main.rcc
  4. //在应用程序中注册资源,一般在main函数启动后就注册
  5. QResource::registerResource(qApp->applicationDirPath() + "/main.rcc");

Qt高分屏缩放

Qt对高分屏以及dpi缩放的支持越来越成熟,在Qt4时代默认的策略就是跟随系统的缩放,从Qt5.6开始提供了 AA_EnableHighDpiScaling 的属性设置开启高分屏,到了5.14以后还可以指定缩放的策略 HighDpiScaleFactorRoundingPolicy 比如支持浮点数的缩放比而不是之前的整数倍,从Qt6开始默认永远开启了 AA_EnableHighDpiScaling 属性,没法取消。很多时候我们需要两种模式,一种就是永远不应用高分屏及缩放,一种就是自动应用高分屏及缩放。
  1. //永远不应用高分屏及缩放
  2. int main(int argc, char *argv[])
  3. {
  4. #if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
  5. QApplication::setAttribute(Qt::AA_Use96Dpi);
  6. #endif
  7. #if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
  8. QApplication::setHighDpiScaleFactorRoundingPolicy(
  9. Qt::HighDpiScaleFactorRoundingPolicy::Floor);
  10. #endif
  11. QApplication a(argc, argv);
  12. ....
  13. return a.exec();
  14. }
  15. //自动应用高分屏及缩放
  16. //方法很多,综合对比下来还是采用配置文件指定缩放策略最适中。
  17. //新建qt.conf文件放到可执行文件同一目录
  18. [Platforms]
  19. WindowsArguments = dpiawareness=0
  20. //下面这行用来解决Qt高DPI下文字显示有锯齿的问题
  21. WindowsArguments = fontengine=freetype
  22. //有时候想让用户去选择何种策略,需要开启高分屏的之后只需要将qt.conf文件放到
  23. //可执行文件同一目录即可,就算代码中设置了不应用高分屏及缩放,也无效,
  24. //也是优先取qt.conf文件的策略。
  25. //方法1:在main函数的最前面加上下面这句 5.6版本才开始有这个函数
  26. #if (QT_VERSION > QT_VERSION_CHECK(5,6,0))
  27. QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
  28. //开启高缩放支持以后图片可能发虚还要开启下面这个属性
  29. QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
  30. #endif
  31. //方法2:在可执行文件同目录下新建文件 qt.conf 填入下面内容
  32. [Platforms]
  33. WindowsArguments = dpiawareness=0
  34. //下面这行用来解决Qt高DPI下文字显示有锯齿的问题
  35. WindowsArguments = fontengine=freetype
  36. //方法3:在main函数最前面设置Qt内部的环境变量
  37. qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1.5");
  38. //方法4:新版本的Qt比如Qt5.14修正了对高分屏的处理支持不是整数的缩放
  39. qputenv("QT_ENABLE_HIGHDPI_SCALING", "1");
  40. QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
  41. //禁用缩放
  42. //测试发现AA_Use96Dpi属性在Qt5.9以上版本完全正常,以下版本比如5.7有部分控件在175%缩放不正常比如QTextEdit,需要外层套个widget才行。
  43. #if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
  44. QApplication::setAttribute(Qt::AA_Use96Dpi);
  45. #endif
  46. #if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
  47. QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
  48. #endif

Qt样式表

  1. Qt样式表有多种运行机制,主要是考虑到各种需求场景,继承自QWidget的类和qApp类都支持setStyleSheet方法,还可以统一将样式表放在文件,或者将样式文件加入到资源文件。
  • 斗气:qss内容写得到处都是,哪里需要就写在哪里,各种控件调用 setStyleSheet方法传入样式表内容,或者直接对应控件鼠标右键弹出菜单选择改变样式表填入内容;
  • 斗者:qss内容放在文件,读取文件内容设置样式表,程序发布的时候带上qss文件;
  • 斗师:qss文件作为资源文件放到qrc文件,直接编译到可执行文件中,防止篡改;
  • 斗灵:在qss文件中自定义一些标志充当变量使用,读取以后替换对应的变量为颜色值,类似动态换肤;
  • 斗王:放在文件容易被篡改,集成到可执行文件不够灵活,一旦样式表更新需要重新编译文件,如何做到既能只更新样式表文件,又不需要重新编译可执行文件,又能防止被篡改:采用rcc命令将资源文件编译生成二进制,只需要替换该二进制文件即可;
  • 斗皇:继承qstyle类自己实现完成所有样式接口,统一整体风格,大名鼎鼎的UOS系统默认规则就是如此,不允许用样式表,全部painter绘制;

Qt搜索文件夹下特定的文件

  1. /**
  2. * @func: FindFile
  3. * @brief: 查找某个目录下特定类型的文件
  4. * @author: XXX 2020
  5. * @param: strFilePath:要搜索的文件夹
  6. strNameFilters:要搜索的文件类型(例如"*.xml")
  7. * @return: 符合的文件列表
  8. */
  9. QFileInfoList FindFile(const QString &strFilePath, const QString &strNameFilters)
  10. {
  11. QFileInfoList fileList;
  12. if (strFilePath.isEmpty() || strNameFilters.isEmpty())
  13. {
  14. return fileList;
  15. }
  16. QDir dir;
  17. QStringList filters;
  18. filters << strNameFilters;
  19. dir.setPath(strFilePath);
  20. dir.setNameFilters(filters);
  21. QDirIterator iter(dir,QDirIterator::Subdirectories);
  22. while (iter.hasNext())
  23. {
  24. iter.next();
  25. QFileInfo info=iter.fileInfo();
  26. if (info.isFile())
  27. {
  28. fileList.append(info);
  29. }
  30. }
  31. return fileList;
  32. }

使用示例

  1. QFileInfoList fileList = m_pDialogCfg->FindFile("./test", "*.xml");
  2. QFileInfo fileInfo;
  3. bool bIsFind = false;
  4. foreach(fileInfo, fileList)
  5. {
  6. if (fileInfo.fileName().compare(iedRowHeaderitem->text()) == 0)
  7. {
  8. bIsFind = true;
  9. break;
  10. }
  11. }
  12. if (bIsFind == false)
  13. {
  14. ...
  15. }
  16. else
  17. {
  18. ...
  19. }

关于 QLineEdit设置QDoubleValidator设置范围无效问题 的解决方法

问题

开发时,对于QLineEdit设置其值有限输入范围限制。 QLineEdit设置QDoubleValidator无效,设置QIntValidator有效。

无效代码与有效代码

  1. #if 0
  2. // 浮点数无效代码
  3. ui->lineEdit_t->setValidator(new DoubleValidator(40, 80, 1);
  4. #else
  5. // 浮点数无效代码 2022-07-28 02:00:37 测试
  6. QDoubleValidator * doubleValidator = new QDoubleValidator(40, 80, 1);
  7. doubleValidator->setNotation(QDoubleValidator::StandardNotation);
  8. ui->lineEdit_t->setValidator(doubleValidator);
  9. #end
  10. // 整数有效代码
  11. ui->lineEdit_coverT->setValidator(new QIntValidator(0, 110));

Qt: Attempting to add QLayout “” to MainWindow “”, which already has a layout

Qt: Attempting to add QLayout “” to MainWindow “”, which already has a layout 意思是,试图添加一个布局到 mainwindow 上,但实际上该布局已经存在了

原因:主界面在设置布局之后,重新设定的(多部分都是代码写的)QWidget的布局指定父对象时要注意设置成QWidget的而不是this

  1. QWidget *buttongroup = new QWidget(this);//自定义右上角按钮组
  2. buttongroup->setMaximumSize(100,30);
  3. buttongroup->setObjectName("buttongroup");
  4. QPushButton *setbutton = new QPushButton(this);//设置按钮
  5. setbutton->setMaximumSize(100,30);
  6. setbutton->setObjectName("settingButton");
  7. setbutton->setIcon(QIcon(":/img/setting.png"));
  8. setbutton->setText(tr("设置"));
  9. //错误示例
  10. //QHBoxLayout *layout1= new QHBoxLayout(this);
  11. //正确示例
  12. //定义按钮组水平布局
  13. QHBoxLayout *layout1= new QHBoxLayout(buttongroup); //这里的父对象要设置为buttongroup,而不是this
  14. layout1->setSizeConstraint(QLayout::SetFixedSize);
  15. layout1->addWidget(setbutton);
  16. layout1->setMargin(0);
  17. buttongroup->setLayout(layout1);

Qt通过setText(tr()),设置的翻译不生效!!!

源代码

  1. //加载翻译文件
  2. QTranslator translator;
  3. QString qmFile = ":/translations/es.qm";
  4. translator.load(qmFile);
  5. QApplication::installTranslator(&translator);

translator 声明为了局部变量,当构造函数执行后就被销毁了,所以当构造函数执行后,翻译生效了一次,此后当我们通过setText的方式再设置文本时,翻译就失效了。

解决方案

  1. //加载翻译文件
  2. QTranslator *translator = new QTranslator(this);
  3. QString qmFile = ":/translations/es.qm";
  4. translator->load(qmFile);
  5. QApplication::installTranslator(translator);

translator声明为指针,使用new方法,将其声明在堆上,则只有当该类被析构时,该translator才会被析构,此后的setText方法设置的文本就会被正常翻译。

Qt通过路径 斜杠 和 反斜杠的转换问题

  1. QString str = "D:\\02_Demo\\123";
  2. // \转/ (反斜杠转斜杠)
  3. QString strpath=QDir::fromNativeSeparators(str);
  4. qDebug()<<"strpath=="<<strpath;
  5. // 将/转\(斜杠转反斜杠
  6. QString strpath2 = QDir::toNativeSeparators(str);
  7. qDebug()<<"strpath2=="<<strpath2;