锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

一位大佬对于 Qt 学习的最全总结(三万字干货)

时间:2022-12-19 03:00:00 高脚连接器

击上方“C语言与CPP编程”,选择“关注/顶部/星标公众号

第一时间送达干货福利!

e8a90f32326094b7fd055b628ba12310.png

分享一个大佬 Github 上关于 Qt 学习总结。作者无私分享了100多个自定义控件和几本书 Qt 的书籍(C Qt),特此引用这个大佬的干货,左下角可以阅读原文进入GitHub原始共享地址。

一、个人总结的经验语录

  1. 学习编程是一个渐变的过程,一年精通,三年熟悉,八年入门,十年孟逼,十五年颈椎康复指南,三十年灰飞烟灭。

  2. 老板或客户:我不知道我需要什么,我也不知道我想要什么效果,但我知道你做了什么,我不想要什么!杀死一个程序员很简单,改变几次需求!

  3. 一个控件从0到基本可用,如果差3条街,从可用到好用,还差30条街。控件和软件系统也是如此。

  4. 一行代码,1元,知道怎么写,100元。就像医院的外科医生一样,手术中使用的药物是100元,但手术是几千元。为什么,因为只有他知道怎么做,也是手术,知道怎么做才是最有价值的!

  5. 我非常喜欢鬼谷子的一段话:我们做了很多事情,不必关心答案,因为没有答案,如果答案是别人需要的,我们只是在走别人的路,但我们是想给别人答案的人。没有什么是绝对的,答案会只有一个,所以论证答案本身就是愚蠢的。

  6. 至于阅读无用理论,教育只是一个小方面。事实上,最重要的是三种能力:独立学习、解决问题和人际交往的能力!这三个方面都很强大。即使他们从幼儿园毕业,他们也是顶尖人物。阅读培养了这三种能力。只是有些人训练得很好,有些人没有。

  7. 无论软件写得多好,代码多么强大,界面多么美丽,架构多么强大,都不能解决用户的实际需求,不能卖钱或赚钱,都是无用的!人们,真的需要找到合适的行业和运气!

  8. 不懂技术的人往往把技术看得太简单,比如很多老板;懂技术的人往往把技术想得太复杂,比如程序员;

  9. 享受生活是什么意思?周末下午,在家里大厅打开一部电影,打开一瓶红酒,拿出高脚杯,倒上半杯慢饮。偶尔看看窗外宜人的风景,你会突然发现写几行代码更有意思。NND!

  10. 我完全感兴趣,老板不给我钱,我也想写代码!白天干,晚上干,周一周五干,周末继续干!编程已经深入我的基因、骨髓和灵魂!每当你解决一个程序问题,你比其他人获得王者荣耀的第一名更快乐!想想看,能做自己感兴趣的事,像写诗一样写代码,玩游戏一样开心,还能拿到工资!真他妈爽!没有什么比这更酷的了!

  11. 不要以技术为荣,赚多少钱为荣,而是以名人为荣,文化自信,国家自强!

  12. 我目前的模式是销售代码,然后了解各行各业,然后探索需求,然后找到正确的机会,开始,直接滚动马上做!AB项目孵化,B项目孵化C项目。卖只是介绍,最多赚点零花钱,真正的意图是定制。

  13. 每当我看到你努力学习,我都惊慌失措,所以只有努力学习才能赶上老板的脚步,然后不被《纽约时报》抛弃,只能用勤奋来换取知识和技术的积累。我不聪明,但我会努力工作的蜗牛!

  14. 别看我QtWidget水平比很多人高一点。事实上,全国只有成千上万的人。你不知道外面有一天,外面有人!你应该四处走动,不要坐在井里看天空!因为我遇到了几十个比我强大得多的水平。这只是冰山一角!真正的老板通常不混合群体或论坛。他们非常低调!也许这就是所谓的沉默。

  15. 假如我们把期限定为人的一生,那就意味着年轻人要多探索,到后期要多注重收获。

  16. 有的人等退休做自己喜欢的事,有的人做自己一辈子喜欢的事,不想退休。

  17. 也许你现在做的事情看不到结果,但不要害怕,你不是长大了,而是扎根了。

  18. 要么选择试图探索一套成长和赚钱的思维模式,要么学习他人成功和赚钱的思维模式,并将其转化为自己的模式。

  19. 码农最重要的是学会沟通,而不是写代码。不要抱怨没人回答你的问题。首先,他们需要学会如何提问,其他人才能更好地理解你的问题。

  20. 回答你的问题是友谊。忽视你是我的权力。没有人有义务帮助你。你在寻求帮助,态度更好,但不要冤枉自己。最后,如果你什么都做不了,或者只有一点基础,不要指望我们告诉你怎么做!建议多读书,多练习。

  21. 如何有效地提问:你做了什么,你做了什么;你检查了什么信息,你说了什么;你是如何设计的;发布你的代码;编译错误是什么;代码截图,错误截图;结果是什么,你期望的结果是什么;你觉得怎么样;

  22. 代码如尿崩,谁与我争疯!用生命写代码,用灵魂做界面!

  23. 优秀的程序员写诗般的代码,平庸的程序员写屎般的代码。

  24. 虽然楼主没有讲很多底层原理,但只有那些数字让我心里澎湃。瞬间佩服楼主的五体投地,就像是一种启迪。回首往事,我发现自己没有技术。关公面前真的是一把大刀班。

  25. 秦始皇无意中得到了两种长生不老药,他自己服了一种,还剩一种让我服,我没服,就服你!

  26. 这一幕我想念一首诗:误入:IT后悔无声,一枪匹马夜挑灯,一进去就一进去Qt深似海,从此脂粉不沾身。

  27. 这一幕我想再唱一首诗:Qt群里行人稀少,车手往往高低不一。现在车道还在,没有老司机。

  28. 在我们通常的编程过程中,我们应该尽量抑制一些人的本性,尽量找不到理由,承担责任,减少攻击性,不断学习他人的优势,减少时间不思考,不撒谎,同理心,尽量不自私,永远不要水平。

  29. 人际关系在生活中有所改善,主要是在说话前思考,轿子抬人,来来往往是关系,努力思考,敢于分钱,带弟弟吃肉,喂老板肉,可以带别人一起成长。

  30. 在工作中,长期计划,短期计划;理解,执行;简化复杂问题,简单问题复杂,逻辑好;工程和代码能力好;至少60分;吹牛能力好。

  31. 我在上海接触过至少几十个老板,大大小小,学历低,但都有一个共同点,那就是我很喜欢学习,做人很到位。不管我的价值有多高,我都非常尊重和谦逊。如果你想成功,你必须培养这些共性。

  32. 如何成为一名优秀的独立开发人员,提出以下建议:做你喜欢做的事情;快速建立产品,尽快进入市场验证(精益创业);不要在技术上浪费太多时间,设定发布日期;不了解技术也可以创造好产品;如果你打算开始独自工作,记创造你的个人品牌;亲自为客户提供电子邮件支持,至少在一开始;客户至上;仔细思考,设定合理的目标,在谈论其他产品之前实现产品。

  33. 大学生应该放下自己的身体和教育背景,主动做事,端茶倒水做卫生,先生活,无论高低,忍受羞辱负担不断积累资本,可以有一个光明的未来。如果你有更好的运气,不仅找到适合你的职业方向,而且遇到老板可以鼓励和提供发展机会和发展空间,你可以把这个职业作为一个职业!

  34. 多换位思考,从对方的角度思考问题,学会一套圆滑的高招。懂得把悲伤变成力量,把战斗变成丝绸,把腐朽变成神奇!

  35. 一旦一个人走出巨大的阴霾,你会发现世界是如此美好,前途光明。

  36. 360行,程序员,现在现在很多人看到程序员职位赚钱受欢迎,转行,班级自学,但是,一个人是否适合写程序,当你还是一个精子时,如果你没有编程的感觉和意识,条路太难了!

  37. 我不是针对谁,我是说在座的各位,注意,是在座的各位,除了我都是大佬!

  38. 一个人最开心的时候不是在你拿到钱的一刹那,而是在你知道你可以拿这么多钱的时候!

  39. 上海没房的话,压根就没有存在感,所以伙伴们还是早点回老家创业吧,有句话说的好,上海挣钱上海花,一分别想寄回家。

  40. 选择公司的时候一定要注意,要看一看公司的氛围,一家正常的公司,一般没有那么多乱七八糟形式化的东西,不会一大早喊口号,打鸡血,也不会早请示,晚汇报,因为正经公司追求的是利润,做企业要赚钱的,大家没有那么多时间去浪费。

  41. Qt编程一时爽,一直Qt一直爽。左边跟我一起画个龙,在你右边画一道彩虹!

  42. 人一定要有才华,这是所有自信的根基和源泉。

  43. 输了你,赢了整个世界又如何!连心爱的人都留不住,代码写的再溜又能怎样?

  44. 当你对编程有着浓厚兴趣的时候,你就会因为这种兴趣的吸引而全身心的投入进去,也正是这种投入与忍耐,恒心和坚持,让你变得更加牛逼。

  45. 世界上只有两种区块链,一种在技术天才们的头脑里,还没有落地,另一种在中国人的微信群里,已经在做交易。

  46. 技术人员做技术时间久了,很容易陷入一个技术思维陷阱,以为技术就是整个世界整个生活,老子技术天下第一,其他人写的都是垃圾的感觉,很多人觉得自己5年10年的时候技术很牛逼,自我感觉良好,非常蔑视瞧不起那些做销售做市场做商业的技术人员,其实大错特错,这些人全身心投入到技术上,技术深度未必比你差。建议技术人员头5-10年,可以全身心投入技术研发,深扎根,打牢基础,过了这个阶段以后,可以适当的往市场、需求、商业、管理等更高层次方面拓展,格局慢慢变大而不仅限于技术方面。

  47. 有一种生意最赚钱,那就是教别人如何赚钱,让别人赚钱。有一种成功最成功,那就是让别人成功从而让自己获得成功!

  48. 在编程这条技术路线过程中,除了要耐得住寂寞,扛得住诱惑,技术深扎根以外,更需要自我总结、自我推动、自我激发、自我生产、自我疗伤、自我成长。学会左手温暖右手!

  49. 活在当下都不容易,多少人为了养家糊口远离他乡和父母小孩在外打工奋斗,住着简易的房子,甚至有些还不足10平米,一边还着房贷车贷,一边交着房租,而且很多人还是交着两个房租,一个是家里边为了小孩在县城读书租房的,一个是自己在外打工租房的,但是各位心中依然憧憬着美好的未来,致敬每一个在外打工漂泊的人。

  50. 程序员不要随意吹牛逼,这个月薪五万那个年薪百万,还有个刚毕业就月薪三万,当你跟着一起瞎几把吹牛逼的时候,有一天你会突然发现只有你在吹牛逼,别人说的都是真的!

  51. 如果不是为了荣归故里,谁他么愿意 ”抛妻弃子“ “漂泊流浪” ”远走他乡“。

  52. 我感觉我的技术遇到了瓶颈,该会的都已经会了,不会的再怎么学也不会,估计这辈子也就这样了,顶多就是学会另外一门语言框架做做过的事情,没有或者很难有质的突破!

  53. 当你离开大学走上社会以后,你会发现,大学的就业指导课的老师很可能自己都没去社会就过业,大学的计算机老师很可能没做过商业项目的开发,入门甚至还没入门的水平!

  54. 中间部分持续增加中,欢迎关注,敬请期待!

  55. 最后祝大家头发浓密,睡眠良好,情绪稳定,财富自由!

二、程序员懵逼瞬间

  1. 不加代码前运行的好好的,手贱加了几行代码,就不行了,然后把加的这几行代码注释掉重新彻底编译,他娘的也还是不行,懵逼中,关键是他娘的真的回不去了。

  2. 昨天还运行的好好的,今天一开机运行就不行了,关键是什么都没干。一般这种情况,回去睡一觉第二天就莫名其妙的好了。

  3. 编译后明明只有1个错误,找到错误的地方改了改,信心满满按下F5,尼玛,几百个错误出来了。

三、开发经验总结

  1. 当编译发现大量错误的时候,从第一个看起,一个一个的解决,不要急着去看下一个错误,往往后面的错误都是由于前面的错误引起的,第一个解决后很可能都解决了。

  2. 定时器是个好东西,学会好使用它,有时候用QTimer::singleShot可以解决意想不到的问题。

  3. 打开creator,在构建套件的环境中增加MAKEFLAGS=-j8,可以不用每次设置多线程编译。珍爱时间和生命。新版的QtCreator已经默认就是j8。

  4. 如果你想顺利用QtCreator部署安卓程序,首先你要在AndroidStudio 里面配置成功,把坑全部趟平。

  5. 很多时候找到Qt对应封装的方法后,记得多看看该函数的重载,多个参数的,你会发现不一样的世界,有时候会恍然大悟,原来Qt已经帮我们封装好了。

  6. 可以在pro文件中写上标记版本号+ico图标(Qt5才支持)

 
     
VERSION  = 2020.10.25
RC_ICONS = main0.ico
  1. 管理员运行程序,限定在MSVC编译器。

 
     
QMAKE_LFLAGS += /MANIFESTUAC:"level='requireAdministrator' uiAccess='false'" #以管理员运行
QMAKE_LFLAGS += /SUBSYSTEM:WINDOWS,"5.01" #VS2013 在XP运行
  1. 运行文件附带调试输出窗口 CONFIG += console pro

  2. 绘制平铺背景QPainter::drawTiledPixmap,绘制圆角矩形QPainter::drawRoundedRect(),而不是QPainter::drawRoundRect();

  3. 移除旧的样式

 
     
//移除原有样式
style()->unpolish(ui->btn);
//重新设置新的该控件的样式。
style()->polish(ui->btn);
获取类的属性
const QMetaObject *metaobject = object->metaObject();
int count = metaobject->propertyCount();
for (int i = 0; i < count; ++i) {
    QMetaProperty metaproperty = metaobject->property(i);
    const char *name = metaproperty.name();
    QVariant value = object->property(name);
    qDebug() << name << value;
}
  1. Qt内置图标封装在QStyle中,大概七十多个图标,可以直接拿来用。

 
     
SP_TitleBarMenuButton,
SP_TitleBarMinButton,
SP_TitleBarMaxButton,
SP_TitleBarCloseButton,
SP_MessageBoxInformation,
SP_MessageBoxWarning,
SP_MessageBoxCritical,
SP_MessageBoxQuestion,
...
  1. 根据操作系统位数判断加载

 
     
win32 {
    contains(DEFINES, WIN64) { DESTDIR = $${PWD}/../../bin64
    } else { DESTDIR = $${PWD}/../../bin32 }
}
  1. Qt5增强了很多安全性验证,如果出现setGeometry: Unable to set geometry,请将该控件的可见移到加入布局之后。

  2. 可以将控件A添加到布局,然后控件B设置该布局,这种灵活性大大提高了控件的组合度,比如可以在文本框左侧右侧增加一个搜索按钮,按钮设置图标即可。

 
     
QPushButton *btn = new QPushButton;
btn->resize(30, ui->lineEdit->height());
QHBoxLayout *layout = new QHBoxLayout(ui->lineEdit);
layout->setMargin(0);
layout->addStretch();
layout->addWidget(btn);
  1. 对QLCDNumber控件设置样式,需要将QLCDNumber的segmentstyle设置为flat。

  2. 巧妙的使用findChildren可以查找该控件下的所有子控件。findChild为查找单个。

 
     
//查找指定类名objectName的控件
QList widgets = parentWidget.findChildren("widgetname");
//查找所有QPushButton
QList allPButtons = parentWidget.findChildren();
//查找一级子控件,不然会一直遍历所有子控件
QList childButtons = parentWidget.findChildren(QString(), Qt::FindDirectChildrenOnly);
  1. 巧妙的使用inherits判断是否属于某种类。

 
     
QTimer *timer = new QTimer;         // QTimer inherits QObject
timer->inherits("QTimer");          // returns true
timer->inherits("QObject");         // returns true
timer->inherits("QAbstractButton"); // returns false
  1. 使用弱属性机制,可以存储临时的值用于传递判断。可以通过widget->dynamicPropertyNames()列出所有弱属性名称,然后通过widget->property("name")取出对应的弱属性的值。

  2. 在开发时, 无论是出于维护的便捷性, 还是节省内存资源的考虑, 都应该有一个 qss 文件来存放所有的样式表, 而不应该将 setStyleSheet 写的到处都是。如果是初学阶段或者测试阶段可以直接UI上右键设置样式表,正式项目还是建议统一到一个qss样式表文件比较好,统一管理。

  3. 如果出现Z-order assignment: is not a valid widget.错误提示,用记事本打开对应的ui文件,找到为空的地方,删除即可。

  4. 善于利用QComboBox的addItem的第二个参数设置用户数据,可以实现很多效果,使用itemData取出来。

  5. 如果用了webengine模块,发布程序的时候带上QtWebEngineProcess.exe+translations文件夹+resources文件夹。

  6. 默认Qt是一个窗体一个句柄,如果要让每个控件都拥有独立的句柄,设置下 a.setAttribute(Qt::AA_NativeWindows);

  7. Qt+Android防止程序被关闭。

 
     
#if defined(Q_OS_ANDROID)
QAndroidService a(argc, argv);
return a.exec()
#else
QApplication a(argc, argv);
return a.exec();
#endif
  1. 可以对整体的指示器设置样式,例如 ::down-arrow,::menu-indicator{}::up-arrow:disabled,::up-arrow:off{}。

  2. 可以执行位置设置背景图片。

 
     
QMainWindow > .QWidget {
    background-color: gainsboro;
    background-image: url(:/images/pagefold.png);
    background-position: top right;
    background-repeat: no-repeat
}
  1. 嵌入式linux运行Qt程序 Qt4写法:./HelloQt -qws & Qt5写法:./HelloQt --platform xcb

  2. Qtcreator软件的配置文件存放在:C:\Users\Administrator\AppData\Roaming\QtProject,有时候如果发现出问题了,将这个文件夹删除后打开creator自动重新生成即可。

  3. QMediaPlayer是个壳,依赖本地解码器,视频这块默认基本上就播放个MP4,如果要支持其他格式需要下载k-lite或者LAV Filters安装即可(WIN上,其他系统上自行搜索)。如果需要做功能强劲的播放器,初学者建议用vlc、mpv,终极大法用ffmpeg。

  4. 判断编译器类型、编译器版本、操作系统。

 
     
//GCC编译器
#ifdef __GNUC__
#if __GNUC__ >= 3 // GCC3.0以上


//MSVC编译器
#ifdef _MSC_VER
#if _MSC_VER >=1000 // VC++4.0以上
#if _MSC_VER >=1100 // VC++5.0以上
#if _MSC_VER >=1200 // VC++6.0以上
#if _MSC_VER >=1300 // VC2003以上
#if _MSC_VER >=1400 // VC2005以上
#if _MSC_VER >=1500 // VC2008以上
#if _MSC_VER >=1600 // VC2010以上
#if _MSC_VER >=1700 // VC2012以上
#if _MSC_VER >=1800 // VC2013以上
#if _MSC_VER >=1900 // VC2015以上


//Borland C++
#ifdef __BORLANDC__


//Cygwin
#ifdef __CYGWIN__
#ifdef __CYGWIN32__


//mingw
#ifdef __MINGW32__


//windows
#ifdef _WIN32    //32bit
#ifdef _WIN64    //64bit
#ifdef _WINDOWS     //图形界面程序
#ifdef _CONSOLE     //控制台程序
//Windows(95/98/Me/NT/2000/XP/Vista)和Windows CE都定义了
#if (WINVER >= 0x030a)     // Windows 3.1以上
#if (WINVER >= 0x0400)     // Windows 95/NT4.0以上
#if (WINVER >= 0x0410)     // Windows 98以上
#if (WINVER >= 0x0500)     // Windows Me/2000以上
#if (WINVER >= 0x0501)     // Windows XP以上
#if (WINVER >= 0x0600)     // Windows Vista以上
//_WIN32_WINNT 内核版本
#if (_WIN32_WINNT >= 0x0500) // Windows 2000以上
#if (_WIN32_WINNT >= 0x0501) // Windows XP以上
#if (_WIN32_WINNT >= 0x0600) // Windows Vista以上
  1. 在pro中判断Qt版本及构建套件位数

 
     
#打印版本信息
message(qt version: $$QT_VERSION)
#判断当前qt版本号
QT_VERSION = $$[QT_VERSION]
QT_VERSION = $$split(QT_VERSION, ".")
QT_VER_MAJ = $$member(QT_VERSION, 0)
QT_VER_MIN = $$member(QT_VERSION, 1)
#下面是表示 Qt5.5
greaterThan(QT_VER_MAJ, 4) {
greaterThan(QT_VER_MIN, 4) {
#自己根据需要做一些处理
}
}


#QT_ARCH是Qt5新增的,在Qt4上没效果
#打印当前Qt构建套件的信息
message($$QT_ARCH)
#表示arm平台构建套件
contains(QT_ARCH, arm) {}
#表示32位的构建套件
contains(QT_ARCH, i386) {}
#表示64位的构建套件
contains(QT_ARCH, x86_64) {}
  1. Qt最小化后恢复界面假死冻结,加上代码

 
     
void showEvent(QShowEvent *e)
{
    setAttribute(Qt::WA_Mapped);
    QWidget::showEvent(e);
}
  1. 获取标题栏高度:style()->pixelMetric(QStyle::PM_TitleBarHeight); PM_TitleBarHeight点进去你会发现新大陆。

  2. 设置高分屏属性以便支持2K4K等高分辨率,尤其是手机app。必须写在main函数的QApplication a(argc, argv);的前面。

 
     
#if (QT_VERSION > QT_VERSION_CHECK(5,6,0))
    QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
  1. 如果运行程序出现 Fault tolerant heap shim applied to current process. This is usually due to previous crashes. 错误。办法:打开注册表,找到HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\,选中Layers键值,从右侧列表中删除自己的那个程序路径即可。

  2. Qt内置了QFormLayout表单布局用于自动生成标签+输入框的组合的表单界面。

  3. qml播放视频在linux需要安装 sudo apt-get install libpulse-dev。

  4. 可以直接继承QSqlQueryModel实现自定义的QueryModel,比如某一列字体颜色,占位符,其他样式等,重写QVariant CustomSqlModel::data(const QModelIndex &index, int role) const。

  5. Qt5以后提供了类QScroller直接将控件滚动。

 
     
//禁用横向滚动条
ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
//禁用纵向滚动条
ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
//设置横向按照像素值为单位滚动
ui->listWidget->setHorizontalScrollMode(QListWidget::ScrollPerPixel);
//设置纵向按照像素值为单位滚动
ui->listWidget->setVerticalScrollMode(QListWidget::ScrollPerPixel);
//设置滚动对象以及滚动方式为鼠标左键拉动滚动
QScroller::grabGesture(ui->listWidget, QScroller::LeftMouseButtonGesture);
//还有个QScrollerProperties可以设置滚动的一些参数
  1. 如果使用sqlite数据库不想产生数据库文件,可以创建内存数据库。

 
     
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
  1. 清空数据表并重置自增ID,sql = truncate table table_name。

  2. Qtchart模块从Qt5.7开始自带,最低编译要求Qt5.4。在安装的时候记得勾选,默认不勾选。使用该模块需要引入命名空间。

 
     
#include 
QT_CHARTS_USE_NAMESPACE
class CustomChart : public QChartView
  1. QPushButton左对齐文字,需要设置样式表QPushButton{text-align:left;}

  2. QLabel有三种设置文本的方法,掌握好Qt的属性系统,举一反三,可以做出很多效果。

 
     
ui->label->setStyleSheet("qproperty-text:hello;");
ui->label->setProperty("text", "hello");
ui->label->setText("hello");
  1. 巧妙的用QEventLoop开启事件循环,可以使得很多同步获取返回结果而不阻塞界面。QEventLoop内部新建了线程执行。

 
     
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
  1. 多种预定义变量 #if (defined webkit) || (defined webengine),去掉生成空的debug和release目录 CONFIG -= debug_and_release。

  2. 新版的Qtcreator增强了语法检查,会弹出很多警告提示等,可以在插件列表中关闭clang打头的几个即可,Help》About Plugins。也可以设置代码检查级别,Tools》Options 》C++ 》Code Model。

  3. QSqlTableModel的rowCount方法,默认最大返回256,如果超过256,可以将表格拉到底部,会自动加载剩余的,每次最大加载256条数据,如果需要打印或者导出数据,记得最好采用sql语句去查询,而不是使用QSqlTableModel的rowCount方法。不然永远最大只会导出256条数据。如果数据量很小,也可以采用如下方法:

 
     
//主动加载所有数据,不然获取到的行数<=256
while(model->canFetchMore()) {
    model->fetchMore();
}
  1. 如果需要指定无边框窗体,但是又需要保留操作系统的边框特性,可以自由拉伸边框,可以使用 setWindowFlags(Qt::CustomizeWindowHint);

  2. 在某些http post数据的时候,如果采用的是&字符串连接的数据发送,中文解析乱码的话,需要将中文进行URL转码。

 
     
QString content = "测试中文";
QString note = content.toUtf8().toPercentEncoding();
  1. Qt默认不支持大资源文件,比如添加了字体文件,需要pro文件开启。CONFIG += resources_big

  2. Qt中继承QWidget之后,样式表不起作用,解决办法有三个。强烈推荐方法一。

  • 方法一:设置属性 this->setAttribute(Qt::WA_StyledBackground, true);

  • 方法二:改成继承QFrame,因为QFrame自带paintEvent函数已做了实现,在使用样式表时会进行解析和绘制。

  • 方法三:重新实现QWidget的paintEvent函数时,使用QStylePainter绘制。

 
     
void Widget::paintEvent(QPaintEvent *)
{
    QStyleOption option;
    option.initFrom(this);
    QPainter painter(this);
    style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this);
}
  1. 有时候在界面上加了弹簧,需要动态改变弹簧对应的拉伸策略,对应方法为changeSize,很多人会选择使用set开头去找,找不到的。

  2. 在使用QFile的过程中,不建议频繁的打开文件写入然后再关闭文件,比如间隔5ms输出日志,IO性能瓶颈很大,这种情况建议先打开文件不要关闭,等待合适的时机比如析构函数中或者日期变了需要重新变换日志文件的时候关闭文件。不然短时间内大量的打开关闭文件会很卡,文件越大越卡。

  3. 在很多网络应用程序,需要自定义心跳包来保持连接,不然断电或者非法关闭程序,对方识别不到,需要进行超时检测,但是有些程序没有提供心跳协议,此时需要启用系统层的保活程序,此方法适用于TCP连接。

 
     
int fd = tcpSocket->socketDescriptor();
int keepAlive = 1;      //开启keepalive属性,缺省值:0(关闭)
int keepIdle = 5;       //如果在5秒内没有任何数据交互,则进行探测,缺省值:7200(s)
int keepInterval = 2;   //探测时发探测包的时间间隔为2秒,缺省值:75(s)
int keepCount = 2;      //探测重试的次数,全部超时则认定连接失效,缺省值:9(次)
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));
setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
  1. 如果程序打包好以后弹出提示 This application failed to start because it could not find or load the Qt platform plugin 一般都是因为platforms插件目录未打包或者打包错了的原因导致的。

  2. 非常不建议tr中包含中文,尽管现在的新版Qt支持中文到其他语言的翻译,但是很不规范,也不知道TMD是谁教的,tr的本意是包含英文,然后翻译到其他语言比如中文,现在大量的初学者滥用tr,如果没有翻译的需求,禁用tr,tr需要开销的,Qt默认会认为他需要翻译,会额外进行特殊处理。

  3. 很多人Qt和Qt Creator傻傻分不清楚,经常问Qt什么版本结果发一个Qt Creator的版本过来,Qt Creator是使用Qt编写的集成开发环境IDE,和宇宙第一的Visual Studio一样,他可以是msvc编译器的(WIN对应的Qt集成安装环境中自带的Qt Cerator是msvc的),也可以是mingw编译的,还可以是gcc的。如果是自定义控件插件,需要集成到Qt Creator中,必须保证该插件的动态库文件(dll或者so等文件)对应的编译器和Qt版本以及位数和Qt Creator的版本完全一致才行,否则基本不大可能集成进去。特别注意的是Qt集成环境安装包中的Qt版本和Qt Creator版本未必完全一致,必须擦亮眼睛看清楚,有些是完全一致的。

  4. 超过两处相同处理的代码,建议单独写成函数。代码尽量规范精简,比如 if(a == 123) 要写成 if (123 == a),值在前面,再比如 if (ok == true) 要写成 if (ok),if (ok == false) 要写成 if (!ok)等。

  5. 很多人问Qt嵌入式平台用哪个好,这里统一回答(当前时间节点2018年):imx6+335x比较稳定,性能高就用RK3288 RK3399,便宜的话就用全志H3,玩一玩可以用树莓派香橙派。

  6. 对于大段的注释代码,建议用 #if 0 #endif 将代码块包含起来,而不是将该段代码选中然后全部 // ,下次要打开这段代码的话,又需要重新选中一次取消,如果采用的是 #if 0则只要把0改成1即可,效率大大提升。

  7. Qt打包发布,有很多办法,Qt5以后提供了打包工具windeployqt(linux上为linuxdeployqt,mac上为macdeployqt)可以很方便的将应用程序打包,使用下来发现也不是万能的,有时候会多打包一些没有依赖的文件,有时候又会忘记打包一些插件尤其是用了qml的情况下,而且不能识别第三方库,比如程序依赖ffmpeg,则对应的库需要自行拷贝,终极大法就是将你的可执行文件复制到Qt安装目录下的bin目录,然后整个一起打包,挨个删除不大可能依赖的组件,直到删到正常运行为止。

  8. Qt中的动画,底层用的是QElapsedTimer定时器来完成处理,比如产生一些指定规则算法的数据,然后对属性进行处理。

  9. 在绘制无背景颜色只有边框颜色的圆形时候,可以用绘制360度的圆弧替代,效果完全一致。

 
     
QRect rect(-radius, -radius, radius * 2, radius * 2);
//以下两种方法二选一,其实绘制360度的圆弧=绘制无背景的圆形
painter->drawArc(rect, 0, 360 * 16);
painter->drawEllipse(rect);
  1. 不要把d指针看的很玄乎,其实就是在类的实现文件定义了一个私有类,用来存放局部变量,个人建议在做一些小项目时,没有太大必要引入这种机制,会降低代码可读性,增加复杂性,新手接受项目后会看的很懵逼。

  2. 很多人在绘制的时候,设置画笔以为就只可以设置个单调的颜色,其实QPen还可以设置brush,这样灵活性就提高不知道多少倍,比如设置QPen的brush以后,可以使用各种渐变,比如绘制渐变颜色的进度条和文字等,而不再是单调的一种颜色。

  3. 很多控件都带有viewport,比如QTextEdit/QTableWidget/QScrollArea,有时候对这些控件直接处理的时候发现不起作用,需要对其viewport()设置才行,比如设置滚动条区域背景透明,需要使用scrollArea->viewport()->setStyleSheet("background-color:transparent;");而不是scrollArea->setStyleSheet("QScrollArea{background-color:transparent;}");

  4. 有时候设置了鼠标跟踪setMouseTracking为真,如果该窗体上面还有其他控件,当鼠标移到其他控件上面的时候,父类的鼠标移动事件MouseMove识别不到了,此时需要用到HoverMove事件,需要先设置 setAttribute(Qt::WA_Hover, true);

  5. Qt封装的QDateTime日期时间类非常强大,可以字符串和日期时间相互转换,也可以毫秒数和日期时间相互转换,还可以1970经过的秒数和日期时间相互转换等。

 
     
QDateTime dateTime;
QString dateTime_str = dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
//从字符串转换为毫秒(需完整的年月日时分秒)
datetime.fromString("2011-09-10 12:07:50:541", "yyyy-MM-dd hh:mm:ss:zzz").toMSecsSinceEpoch();
//从字符串转换为秒(需完整的年月日时分秒)
datetime.fromString("2011-09-10 12:07:50:541", "yyyy-MM-dd hh:mm:ss:zzz").toTime_t();
//从毫秒转换到年月日时分秒
datetime.fromMSecsSinceEpoch(1315193829218).toString("yyyy-MM-dd hh:mm:ss:zzz");
//从秒转换到年月日时分秒(若有zzz,则为000)
datetime.fromTime_t(1315193829).toString("yyyy-MM-dd hh:mm:ss[:zzz]");
  1. 在我们使用QList、QStringList、QByteArray等链表或者数组的过程中,如果只需要取值,而不是赋值,强烈建议使用 at() 取值而不是 [] 操作符,在官方书籍《C++ GUI Qt 4编程(第二版)》的书中有特别的强调说明,此教材的原作者据说是Qt开发的核心人员编写的,所以还是比较权威,至于使用 at() 与使用 [] 操作符速度效率的比较,网上也有网友做过此类对比。原文在书的212页,这样描述的:Qt对所有的容器和许多其他类都使用隐含共享,隐含共享是Qt对不希望修改的数据决不进行复制的保证,为了使隐含共享的作用发挥得最好,可以采用两个新的编程习惯。第一种习惯是对于一个(非常量的)向量或者列表进行只读存取时,使用 at() 函数而不用 [] 操作符,因为Qt的容器类不能辨别 [] 操作符是否将出现在一个赋值的左边还是右边,他假设最坏的情况出现并且强制执行深层赋值,而 at() 函数则不被允许出现在一个赋值的左边。

  2. 如果是dialog窗体,需要在exec以后还能让其他代码继续执行,请在dialog窗体exec前增加一行代码,否则会阻塞窗体消息。

 
     
QDialog dialog;
dialog.setWindowModality(Qt::WindowModal);
dialog.exec();
  1. 安全的删除Qt的对象类,强烈建议使用deleteLater而不是delete,因为deleteLater会选择在合适的时机进行释放,而delete会立即释放,很可能会出错崩溃。如果要批量删除对象集合,可以用qDeleteAll,比如 qDeleteAll(btns);

  2. 在QTableView控件中,如果需要自定义的列按钮、复选框、下拉框等其他模式显示,可以采用自定义委托QItemDelegate来实现,如果需要禁用某列,则在自定义委托的重载createEditor函数返回0即可。自定义委托对应的控件在进入编辑状态的时候出现,如果想一直出现,则需要重载paint函数用drawPrimitive或者drawControl来绘制。

  3. 将 QApplication::style() 对应的drawPrimitive、drawControl、drawItemText、drawItemPixmap等几个方法用熟悉了,再结合QStyleOption属性,可以玩转各种自定义委托,还可以直接使用paint函数中的painter进行各种绘制,各种牛逼的表格、树状列表、下拉框等,绝对屌炸天。QApplication::style()->drawControl 的第4个参数如果不设置,则绘制出来的控件不会应用样式表。

  4. 心中有坐标,万物皆painter,强烈建议在学习自定义控件绘制的时候,将qpainter.h头文件中的函数全部看一遍、试一遍、理解一遍,这里边包含了所有Qt内置的绘制的接口,对应的参数都试一遍,你会发现很多新大陆,会大大激发你的绘制的兴趣,犹如神笔马良一般,策马崩腾遨游代码绘制的世界。

  5. 在使用setItemWidget或者setCellWidget的过程中,有时候会发现设置的控件没有居中显示而是默认的左对齐,而且不会自动拉伸填充,对于追求完美的程序员来说,这个可不大好看,有个终极通用办法就是,将这个控件放到一个widget的布局中,然后将widget添加到item中,这样就完美解决了,而且这样可以组合多个控件产生复杂的控件。

 
     
//实例化进度条控件
QProgressBar *progress = new QProgressBar;
//增加widget+布局巧妙实现居中
QWidget *widget = new QWidget;
QHBoxLayout *layout = new QHBoxLayout;
layout->setSpacing(0);
layout->setMargin(0);
layout->addWidget(progress);
widget->setLayout(layout);
ui->tableWidget->setCellWidget(0, 0, widget);
  1. 很多时候需要在已知背景色的情况下,能够清晰的绘制文字,这个时候需要计算对应的文字颜色。

 
     
//根据背景色自动计算合适的前景色
double gray = (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255;
QColor textColor = gray > 0.5 ? Qt::black : Qt::white;
  1. 对QTableView或者QTableWidget禁用列拖动。

 
     
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
    ui->tableView->horizontalHeader()->setResizeMode(0, QHeaderView::Fixed);
#else
    ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
#endif
  1. 从Qt4转到Qt5,有些类的方法已经废弃或者过时了,如果想要在Qt5中启用Qt4的方法,比如QHeadVew的setMovable,可以在你的pro或者pri文件中加上一行即可:DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0

  2. Qt中的QColor对颜色封装的很完美,支持各种转换,比如rgb、hsb、cmy、hsl,对应的是toRgb、toHsv、toCmyk、toHsl,还支持透明度设置,颜色值还能转成16进制格式显示。

 
     
QColor color(255, 0, 0, 100);
qDebug() << color.name() << color.name(QColor::HexArgb);
//输出 #ff0000 #64ff0000
  1. QVariant类型异常的强大,可以说是万能的类型,在进行配置文件的存储的时候,经常会用到QVariant的转换,QVariant默认自带了toString、toFloat等各种转换,但是还是不够,比如有时候需要从QVariant转到QColor,而却没有提供toColor的函数,这个时候就要用到万能办法。

 
     
if (variant.typeName() == "QColor") {
    QColor color = variant.value();
    QFont font = variant.value();
    QString nodeValue = color.name(QColor::HexArgb);
}
  1. Qt中的QString和const char *之间转换,最好用toStdString().c_str()而不是toLocal8Bit().constData(),比如在setProperty中如果用后者,字符串中文就会不正确,英文正常。

  2. Qt的信号槽机制非常牛逼,也是Qt的独特的核心功能之一,有时候我们在很多窗体中传递信号来实现更新或者处理,如果窗体层级比较多,比如窗体A的父类是窗体B,窗体B的父类是窗体C,窗体C有个子窗体D,如果窗体A一个信号要传递给窗体D,问题来了,必须先经过窗体B中转到窗体C再到窗体D才行,这样的话各种信号关联信号的connect会非常多而且管理起来比较乱,可以考虑增加一个全局的单例类AppEvent,公共的信号放这里,然后窗体A对应信号绑定到AppEvent,窗体D绑定AppEvent的信号到对应的槽函数即可,干净清爽整洁。

  3. QTextEdit右键菜单默认英文的,如果想要中文显示,加载widgets.qm文件即可,一个Qt程序中可以安装多个翻译文件,不冲突。

  4. Qt中有个全局的焦点切换信号focusChanged,可以用它做自定义的输入法。Qt4中默认会安装输入法上下文,比如在main函数打印a.inputContext会显示值,这个默认安装的输入法上下文,会拦截两个牛逼的信号QEvent::RequestSoftwareInputPanel和QEvent::CloseSoftwareInputPanel,以至于就算你安装了全局的事件过滤器依然识别不到这两个信号,你只需要在main函数执行a.setInputContext(0)即可,意思是安装输入法上下文为空。

  5. 在Qt5.10以后,表格控件QTableWidget或者QTableView的默认最小列宽改成了15,以前的版本是0,所以在新版的qt中,如果设置表格的列宽过小,不会应用,取的是最小的列宽。所以如果要设置更小的列宽需要重新设置ui->tableView->horizontalHeader()->setMinimumSectionSize(0);

  6. Qt源码中内置了一些未公开的不能直接使用的黑科技,都藏在对应模块的private中,比如gui-private widgets-private等,比如zip文件解压类QZipReader、压缩类QZipWriter就在gui-private模块中,需要在pro中引入QT += gui-private才能使用。

 
     
#include "QtGui/private/qzipreader_p.h"
#include "QtGui/private/qzipwriter_p.h"


QZipReader reader(dirPath);
QString path("");
//解压文件夹到当前目录
reader.extractAll(path);
//文件夹名称
QZipReader::FileInfo fileInfo = reader.entryInfoAt(0);
//解压文件
QFile file(filePath);
file.open(QIODevice::WriteOnly);
file.write(reader.fileData(QString::fromLocal8Bit("%1").arg(filePath)));
file.close();
reader.close();


QZipWriter *writer = new QZipWriter(dirPath);
//添加文件夹
writer->addDirectory(unCompress);
//添加文件
QFile file(filePath);
file.open(QIODevice::ReadOnly);
writer->addFile(data, file.readAll());
file.close();
writer->close();
  1. 理论上串口和网络收发数据都是默认异步的,操作系统自动调度,完全不会卡住界面,网上那些说收发数据卡住界面主线程的都是扯几把蛋,真正的耗时是在运算以及运算后的处理,而不是收发数据,在一些小数据量运算处理的项目中,一般不建议动用线程去处理,线程需要调度开销的,不要什么东西都往线程里边扔,线程不是万能的。只有当真正需要将一些很耗时的操作比如编码解码等,才需要移到线程处理。

  2. 在构造函数中获取控件的宽高很可能是不正确的,需要在控件首次显示以后再获取才是正确的,控件是在首次显示以后才会设置好正确的宽高值,记住是在首次显示以后,而不是构造函数或者程序启动好以后,如果程序启动好以后有些容器控件比如QTabWidget中的没有显示的页面的控件,你去获取宽高很可能也是不正确的,万无一失的办法就是首次显示以后去获取。

  3. 数据库处理一般建议在主线程,如果非要在其他线程,务必记得打开数据库也要在那个线程,即在那个线程使用数据库就在那个线程打开,不能打开数据库在主线程,执行sql在子线程,很可能出问题。

  4. 新版的QTcpServer类在64位版本的Qt下很可能不会进入incomingConnection函数,那是因为Qt5对应的incomingConnection函数参数变了,由之前的int改成了qintptr,改成qintptr有个好处,在32位上自动是quint32而在64位上自动是quint64,如果在Qt5中继续写的参数是int则在32位上没有问题在64位上才有问题,所以为了兼容Qt4和Qt5,必须按照不一样的参数写。

 
     
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
    void incomingConnection(qintptr handle);
#else
    void incomingConnection(int handle);
#endif
  1. Qt支持所有的界面控件比如QPushButton、QLineEdit自动关联 on_控件名_信号(参数) 信号槽,比如按钮的单击信号 on_pushButton_clicked(),然后直接实现槽函数即可。

  2. QWebEngineView控件由于使用了opengl,在某些电脑上可能由于opengl的驱动过低会导致花屏或者各种奇奇怪怪的问题,比如showfullscreen的情况下鼠标右键失效,需要在main函数启用软件opengl渲染。

 
     
#if (QT_VERSION > QT_VERSION_CHECK(5,4,0))
    //下面两种方法都可以,Qt默认采用的是AA_UseDesktopOpenGL
    QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
    //QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
#endif
    QApplication a(argc, argv);

另外一个方法解决 全屏+QWebEngineView控件一起会产生右键菜单无法弹出的bug,需要上移一个像素

 
     
QRect rect = qApp->desktop()->geometry();
rect.setY(-1);
rect.setHeight(rect.height());
this->setGeometry(rect);
  1. QStyle内置了很多方法用处很大,比如精确获取滑动条鼠标按下处的值。

 
     
QStyle::sliderValueFromPosition(minimum(), maximum(), event->x(), width());
  1. 用QFile读写文件的时候,推荐用QTextStream文件流的方式来读写文件,速度快很多,基本上会有30%的提升,文件越大性能区别越大。

 
     
//从文件加载英文属性与中文属性对照表
QFile file(":/propertyname.txt");
if (file.open(QFile::ReadOnly)) {
    //QTextStream方法读取速度至少快30%
#if 0
    while(!file.atEnd()) {
        QString line = file.readLine();
        appendName(line);
    }
#else
    QTextStream in(&file);
    while (!in.atEnd()) {
        QString line = in.readLine();
        appendName(line);
    }
#endif
    file.close();
}
  1. 用QFile.readAll()读取QSS文件默认是ANSI格式,不支持UTF8,如果在QtCreator中打开qss文件来编辑保存,这样很可能导致qss加载以后没有效果。

 
     
void frmMain::initStyle()
{
    //加载样式表
    QString qss;
    //QFile file(":/qss/psblack.css");
    //QFile file(":/qss/flatwhite.css");
    QFile file(":/qss/lightblue.css");
    if (file.open(QFile::ReadOnly)) {
#if 1
        //用QTextStream读取样式文件不用区分文件编码 带bom也行
        QStringList list;
        QTextStream in(&file);
        //in.setCodec("utf-8");
        while (!in.atEnd()) {
            QString line;
            in >> line;
            list << line;
        }


        qss = list.join("\n");
#else
        //用readAll读取默认支持的是ANSI格式,如果不小心用creator打开编辑过了很可能打不开
        qss = QLatin1String(file.readAll());
#endif
        QString paletteColor = qss.mid(20, 7);
        qApp->setPalette(QPalette(QColor(paletteColor)));
        qApp->setStyleSheet(qss);
        file.close();
    }
}
  1. QString内置了很多转换函数,比如可以调用toDouble转为double数据,但是当你转完并打印的时候你会发现精确少了,只剩下三位了,其实原始数据还是完整的精确度的,只是打印的时候优化成了三位,如果要保证完整的精确度,可以调用 qSetRealNumberPrecision 函数设置精确度位数即可。

 
     
QString s1, s2;
s1 = "666.5567124";
s2.setNum(888.5632123, 'f', 7);
qDebug() << qSetRealNumberPrecision(10) << s1.toDouble() << s2.toDouble();
  1. 用QScriptValueIterator解析数据的时候,会发现总是会多一个节点内容,并且内容为空,如果需要跳过则增加一行代码。

 
     
while (it.hasNext()) {
    it.next();    
    if (it.flags() & QScriptValue::SkipInEnumeration)      
       continue;     
    qDebug() << it.name();
}
  1. setPixmap是最糟糕的贴图方式,一般只用来简单的不是很频繁的贴图,频繁的建议painter绘制,默认双缓冲,在高级点用opengl绘制,利用GPU。

  2. 如果需要在尺寸改变的时候不重绘窗体,则设置属性即可 this->setAttribute(Qt::WA_StaticContents, true); 这样可以避免可以避免对已经显示区域的重新绘制。

  3. 默认程序中获取焦点以后会有虚边框,如果看着觉得碍眼不舒服可以去掉,设置样式即可:setStyleSheet("*{outline:0px;}");

  4. Qt表格控件一些常用的设置封装,QTableWidget继承自QTableView,所以下面这个函数支持传入QTableWidget。

 
     
void QUIHelper::initTableView(QTableView *tableView, int rowHeight, bool headVisible, bool edit)
{
    //奇数偶数行颜色交替
    tableView->setAlternatingRowColors(false);
    //垂直表头是否可见
    tableView->verticalHeader()->setVisible(headVisible);
    //选中一行表头是否加粗
    tableView->horizontalHeader()->setHighlightSections(false);
    //最后一行拉伸填充
    tableView->horizontalHeader()->setStretchLastSection(true);
    //行标题最小宽度尺寸
    tableView->horizontalHeader()->setMinimumSectionSize(0);
    //行标题最大高度
    tableView->horizontalHeader()->setMaximumHeight(rowHeight);
    //默认行高
    tableView->verticalHeader()->setDefaultSectionSize(rowHeight);
    //选中时一行整体选中
    tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    //只允许选择单个
    tableView->setSelectionMode(QAbstractItemView::SingleSelection);


    //表头不可单击
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
    tableView->horizontalHeader()->setSectionsClickable(false);
#else
    tableView->horizontalHeader()->setClickable(false);
#endif


    //鼠标按下即进入编辑模式
    if (edit) {
        tableView->setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::DoubleClicked);
    } else {
        tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    }
}
  1. 在一些大的项目中,可能嵌套了很多子项目,有时候会遇到子项目依赖其他子项目的时候,比如一部分子项目用来生成动态库,一部分子项目依赖这个动态库进行编译,此时就需要子项目按照顺序编译。

 
     
TEMPLATE = subdirs
#设置ordered参数以后会依次编译 demo designer examples
CONFIG  += ordered
SUBDIRS += demo
SUBDIRS += designer
SUBDIRS += examples
  1. MSVC编译器的选择说明

  • 如果是32位的Qt则编译器选择x86开头的

  • 如果是64位的Qt则编译器选择amd64开头的

  • 具体是看安装的Qt构建套件版本以及目标运行平台的系统位数和架构

  • 一般现在的电脑默认以64位的居多,选择amd64即可

  • 如果用户需要兼容32位的系统则建议选择32位的Qt,这样即可在32位也可以在64位系统运行

  • 诸葛大佬补充:x86/x64都是编译环境和运行环境相同,没有或。带下划线的就是交叉编译,前面是编译环境,后面是运行环境。

名称

说明



x86

32/64位系统上编译在32/64位系统上运行

x86_amd64

32/64位系统上编译在64位系统上运行

x86_arm

32/64位系统上编译在arm系统上运行

amd64

64位系统上编译在64位系统上运行

amd64_x86

64位系统上编译在32/64位系统上运行

amd64_arm

64位系统上编译在arm系统上运行

  1. 很多时候用QDialog的时候会发现阻塞了消息,而有的时候我们希望是后台的一些消息继续运行不要终止,此时需要做个设置。

 
     
QDialog dialog;
dialog.setWindowModality(Qt::WindowModal);
  1. 很多初学者甚至几年工作经验的人,对多线程有很深的误解和滥用,尤其是在串口和网络通信这块,什么都往多线程里面丢,一旦遇到界面卡,就把数据收发啥的都搞到多线程里面去,殊不知绝大部分时候那根本没啥用,因为没找到出问题的根源。

  • 如果你没有使用wait***函数的话,大部分的界面卡都出在数据处理和展示中,比如传过来的是一张图片的数据,你需要将这些数据转成图片,这个肯定是耗时的;

  • 还有就是就收到的数据曲线绘制出来,如果过于频繁或者间隔过短,肯定会给UI造成很大的压力的,最好的办法是解决如何不要频繁绘制UI比如合并数据一起绘制等;

  • 如果是因为绘制UI造成的卡,那多线程也是没啥用的,因为UI只能在主线程;

  • 串口和网络的数据收发默认

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章