Qt开发经验总结之武林秘籍(转)

来源:  http://www.qtcn.org/bbs/read-htm-tid-85795-ds-1.html#tpc

 

一、开发经验总结
1. 当编译发现大量错误的时候,从第一个看起,一个一个的解决,不要急着去看下一个错误,往往后面的错误都是由于前面的错误引起的,第一个解决后很可能都解决了。
2. 定时器是个好东西,学会好使用它,有时候用QTimer::singleShot可以解决意想不到的问题
3. 打开creator,在构建套件的环境中增加MAKEFLAGS=-j8,可以不用每次设置多线程编译。珍爱时间和生命。新版的QtCreator已经默认就是j8。
4. 如果你想顺利用QtCreator部署安卓程序,首先你要在AndroidStudio 里面配置成功,把坑全部趟平。
5. 很多时候找到Qt对应封装的方法后,记得多看看该函数的重载,多个参数的,你会发现不一样的世界,有时候会恍然大悟,原来Qt已经帮我们封装好了。
6. 可以在pro文件中写上标记版本号+ico图标(Qt5才支持)
```
VERSION       = 2018.7.25
RC_ICONS    = main0.ico
```
7. 管理员运行程序,限定在MSVC编译器。
```
QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'requireAdministrator\' uiAccess=\'false\'\" #以管理员运行
QMAKE_LFLAGS += /SUBSYSTEM:WINDOWS,\"5.01\" #VS2013 在XP运行
```
8. 运行文件附带调试输出窗口
CONFIG += console pro
9. 绘制平铺背景QPainter::drawTiledPixmap
绘制圆角矩形QPainter::drawRoundedRect(),而不是QPainter::drawRoundRect();
10. 移除旧的样式
```
//移除原有样式
style()->unpolish(ui->btn);
//重新设置新的该控件的样式。
style()->polish(ui->btn);
```
11. 获取类的属性
```
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;
}
```
12. Qt内置图标封装在QStyle中,大概七十多个图标,可以直接拿来用。
QStyle::SP_TitleBarMenuButton
13. 根据操作系统位数判断加载
```
win32 {
    contains(DEFINES, WIN64) { DESTDIR = $${PWD}/../../bin64
    } else { DESTDIR = $${PWD}/../../bin32 }
}
```
14. Qt5增强了很多安全性验证,如果出现setGeometry: Unable to set geometry,请将该控件的可见移到加入布局之后
15. 可以将控件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);
```
16. 对QLCDNumber控件设置样式,需要将QLCDNumber的segmentstyle设置为flat。
17. 巧妙的使用findChildren可以查找该控件下的所有子控件。findChild为查找单个。
```
//查找指定类名objectName的控件
QList widgets = parentWidget.findChildren("widgetname");
//查找所有QPushButton
QList allPButtons = parentWidget.findChildren();
//查找一级子控件,不然会一直遍历所有子控件
QList childButtons = parentWidget.findChildren(QString(), Qt::FindDirectChildrenOnly);
```
18. 巧妙的使用inherits判断是否属于某种类。
```
QTimer *timer = new QTimer;         // QTimer inherits QObject
timer->inherits("QTimer");          // returns true
timer->inherits("QObject");         // returns true
timer->inherits("QAbstractButton"); // returns false
```
19. 使用弱属性机制,可以存储临时的值用于传递判断。
20. 在开发时, 无论是出于维护的便捷性, 还是节省内存资源的考虑, 都应该有一个 qss 文件来存放所有的样式表, 而不应该将 setStyleSheet 写的到处都是。
21. 如果出现Z-order assignment: " is not a valid widget.错误提示,用记事本打开对应的ui文件,找到为空的地方,删除即可。
22. 善于利用QComboBox的addItem的第二个参数设置用户数据,可以实现很多效果,使用itemData取出来。
23. 如果用了webengine模块,发布程序的时候带上QtWebEngineProcess.exe+translations文件夹+resources文件夹。
24. a.setAttribute(Qt::AA_NativeWindows);可以让每个控件都拥有独立的句柄
25. Qt+Android防止程序被关闭。
```
#if defined(Q_OS_ANDROID)
QAndroidService a(argc, argv);
return a.exec()
#else
QApplication a(argc, argv);
return a.exec();
#endif
```
26. 可以对整体的指示器设置样式,例如 *::down-arrow,*::menu-indicator{}  *::up-arrow:disabled,*::up-arrow:off{}。
27. 可以执行位置设置背景图片
```
QMainWindow > .QWidget {
    background-color: gainsboro;
    background-image: url(:/images/pagefold.png);
    background-position: top right;
    background-repeat: no-repeat
}
```
28. 嵌入式linux运行Qt程序  Qt4写法:./HelloQt -qws &   Qt5写法:./HelloQt --platform xcb
29. Qtcreator软件的配置文件存放在:C:\Users\Administrator\AppData\Roaming\QtProject,有时候如果发现出问题了,将这个文件夹删除后打开creator自动重新生成即可。
30. QMediaPlayer依赖本地解码器,WIN上下载k-lite或者LAV Filters安装即可。
31. 代码判断MSVC编译器版本,if (_MSC_VER == 1800),对应关系2013=1800  2012=1700  2010=1600  2008=1500  2005=1400
32. 在pro中判断不同平台:message($$QT_ARCH) contains(QT_ARCH,arm)。
33. Qt最小化后恢复界面假死冻结,加上代码
```
void showEvent(QShowEvent *e){
setAttribute(Qt::WA_Mapped);
QWidget::showEvent(e);
}

```
34. 获取标题栏高度:style()->pixelMetric(QStyle::PM_TitleBarHeight); PM_TitleBarHeight点进去你会发现新大陆。
35. 设置高分屏属性以便支持2K4K等高分辨率,尤其是手机app。必须写在main函数的QApplication a(argc, argv);的前面。
```
#if (QT_VERSION > QT_VERSION_CHECK(5,6,0))
    QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

```
36. 如果运行程序出现 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键值,从右侧列表中删除自己的那个程序路径即可。
37. Qt内置了QFormLayout表单布局用于自动生成标签+输入框的组合的表单界面。
38. qml播放视频在linux需要安装 sudo apt-get install libpulse-dev。
39. 可以直接继承QSqlQueryModel实现自定义的QueryModel,比如某一列字体颜色,占位符,其他样式等,重写QVariant CustomSqlModel::data(const QModelIndex &index, int role) const。
40. Qt5以后提供了类QScroller直接将控件滚动。
```
ui->listWidget->setHorizontalScrollMode(QListWidget::ScrollPerPixel);
QScroller::grabGesture(ui->listWidget,QScroller::LeftMouseButtonGesture);
```
41. 如果使用sqlite数据库不想产生数据库文件,可以创建内存数据库
```
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
```
42. 清空数据表并重置自增ID,sql = truncate table table_name
43. Qtchart模块最低要求Qt5.4。
44. QPushButton左对齐文字,需要设置样式表QPushButton{text-align:left;}

45. QLabel有三种设置文本的方法,掌握好Qt的属性系统,举一反三,可以做出很多效果。
```
ui->label->setStyleSheet("qproperty-text:hello;");
ui->label->setProperty("text", "hello");
ui->label->setText("hello");
```
46. 巧妙的用QEventLoop开启事件循环,可以使得很多同步获取返回结果而不阻塞界面。QEventLoop内部新建了线程执行。
```
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();

```
47. 多种预定义变量 #if (defined webkit) || (defined webengine)。
48. 新版的Qtcreator增强了语法检查,会弹出很多警告提示等,可以在插件列表中关闭clang打头的几个即可,Help》About Plugins。也可以设置代码检查级别,Tools》Options 》C++ 》Code Model。
49. QSqlTableModel的rowCount方法,默认最大返回256,如果超过256,可以将表格拉到底部,会自动加载剩余的,每次最大加载256条数据,如果需要打印或者导出数据,记得最好采用sql语句去查询,而不是使用QSqlTableModel的rowCount方法。不然永远最大只会导出256条数据。
如果数据量很小,也可以采用如下方法:
```
//主动加载所有数据,不然获取到的行数<=256
while(model->canFetchMore()) {
    model->fetchMore();
}
```
50. 如果需要指定无边框窗体,但是又需要保留操作系统的边框特性,可以自由拉伸边框,可以使用 setWindowFlags(Qt::CustomizeWindowHint);
51. 在某些http post数据的时候,如果采用的是&字符串连接的数据发送,中文解析乱码的话,需要将中文进行URL转码。
```
QString content = "测试中文";
QString note = content.toUtf8().toPercentEncoding();

```
52. Qt默认不支持大资源文件,比如添加了字体文件,需要pro文件开启。
CONFIG += resources_big
53. Qt中继承QWidget之后,样式表不起作用,解决办法有三个。强烈推荐方法一。
方法一:设置属性 this->setAttribute(Qt::WA_StyledBackground, true);
方法二:改成继承QFrame,因为QFrame自带paintEvent函数已做了实现,在使用样式表时会进行解析和绘制。
方法三:重新实现QWidget的paintEvent函数时,使用QStylePainter绘制。
```
void myclass::paintEvent(QPaintEvent *)
{
    QStyleOption o;
    o.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &o, &p, this);
}

```
54. 有时候在界面上加了弹簧,需要动态改变弹簧对应的拉伸策略,对应方法为changeSize,很多人会选择使用set开头去找,找不到的。
55. 在使用QFile的过程中,不建议频繁的打开文件写入然后再关闭文件,比如间隔5ms输出日志,IO性能瓶颈很大,这种情况建议先打开文件不要关闭,等待合适的时机比如析构函数中或者日期变了需要重新变换日志文件的时候关闭文件。不然短时间内大量的打开关闭文件会很卡,文件越大越卡。
56. 在很多网络应用程序,需要自定义心跳包来保持连接,不然断电或者非法关闭程序,对方识别不到,需要进行超时检测,但是有些程序没有提供心跳协议,此时需要启用系统层的保活程序,此方法适用于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));
```
57. 如果程序打包好以后弹出提示 This application failed to start because it could not find or load the Qt platform plugin 一般都是因为platforms插件目录未打包或者打包错了的原因导致的。
58. 非常不建议tr中包含中文,尽管现在的新版Qt支持中文到其他语言的翻译,但是很不规范,也不知道TMD是谁教的,tr的本意是包含英文,然后翻译到其他语言比如中文,现在大量的初学者滥用tr,如果没有翻译的需求,禁用tr,tr需要开销的,Qt默认会认为他需要翻译,会额外进行特殊处理。

59. 很多人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版本未必完全一致,必须擦亮眼睛看清楚,有些是完全一致的。
60. 超过两处相同处理的代码,建议单独写成函数。代码尽量规范精简,比如 if(a == 123) 要写成 if (123 == a),值在前面,再比如 if (ok == true) 要写成 if (ok),if (ok == false) 要写成 if (!ok)等。
61. 很多人问Qt嵌入式平台用哪个好,这里统一回答(当前时间节点2018年):imx6+335x比较稳定,性能高就用RK3288 RK3399,便宜的话就用全志H3,玩一玩可以用树莓派香橙派。
94. 不要怀疑这部分被狗吃了,^_^中间部分待更新,会持续更新。也欢迎各位在文章底部留言加进去。
95. Qt界的中文乱码问题,版本众多导致的如何选择安装包问题,如何打包发布程序的问题,堪称Qt界的三座大山!
96. Qt安装目录下的Examples目录下的例子,看完学完,月薪20K起步。
97. 崩溃的80%都是因为要么越界,要么未初始化,死扣这两点,80%的问题解决了。
98. 我一般保留四个版本,为了兼容qt4用4.8.7,最后的支持XP的版本5.7.0,最新的长期支持版本5.9.8,最高的新版本比如5.12.3。
99. 终极秘籍:如果遇到问题搜索Qt方面找不到答案,试着将关键字用JAVA C# android打头,你会发现别有一番天地,其他人很可能做过!
100. 最后一条:珍爱生命,远离编程。祝大家头发浓密,睡眠良好,情绪稳定,财富自由!
二、推荐的Qt论坛+个人博客+网站
Qt开发经验总结之武林秘籍(转)_第1张图片



三、微信公众号
欢迎关注微信公众号【高效程序员】,C++/Python、学习方法、写作技巧、热门技术、职场发展等内容,干货多多,福利多多!

 

 

你可能感兴趣的:(Qt开发经验总结之武林秘籍(转))