91、数据库处理一般建议在主线程,如果非要在其他线程,务必记得打开数据库也要在那个线程,即在那个线程使用数据库就在那个线程打开,不能打开数据库在主线程,执行sql在子线程,很可能出问题。
92、新版的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
93、Qt支持所有的界面控件比如QPushButton、QLineEdit自动关联 on_控件名_信号(参数) 信号槽,比如按钮的单击信号 on_pushButton_clicked(),然后直接实现槽函数即可。
94、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);
95、QStyle内置了很多方法用处很大,比如精确获取滑动条鼠标按下处的值。
QStyle::sliderValueFromPosition(minimum(), maximum(), event->x(), width());
96、用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(); }
97、用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(" "); #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(); } }
98、QString内置了很多转换函数,比如可以调用toDouble转为double数据,但是当你转完并打印的时候你会发现精确少了,只剩下三位了,其实原始数据还是完整的精确度的,只是打印的时候优化成了三位,如果要保证完整的精确度,可以调用 qSetRealNumberPrecision 函数设置精确度位数即可。
QString s1, s2; s1 = "666.5567124"; s2.setNum(888.5632123, 'f', 7); qDebug() << qSetRealNumberPrecision(10) << s1.toDouble() << s2.toDouble();
99、用QScriptValueIterator解析数据的时候,会发现总是会多一个节点内容,并且内容为空,如果需要跳过则增加一行代码。
while (it.hasNext()) { it.next(); if (it.flags() & QScriptValue::SkipInEnumeration) continue; qDebug() << it.name(); }
100、setPixmap是最糟糕的贴图方式,一般只用来简单的不是很频繁的贴图,频繁的建议painter绘制,默认双缓冲,在高级点用opengl绘制,利用GPU。
如果需要在尺寸改变的时候不重绘窗体,则设置属性即可 this->setAttribute(Qt::WA_StaticContents, true); 这样可以避免可以避免对已经显示区域的重新绘制。
默认程序中获取焦点以后会有虚边框,如果看着觉得碍眼不舒服可以去掉,设置样式即可:setStyleSheet("*{outline:0px;}");
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); } }
101、在一些大的项目中,可能嵌套了很多子项目,有时候会遇到子项目依赖其他子项目的时候,比如一部分子项目用来生成动态库,一部分子项目依赖这个动态库进行编译,此时就需要子项目按照顺序编译。
TEMPLATE = subdirs #设置ordered参数以后会依次编译 demo designer examples CONFIG += ordered SUBDIRS += demo SUBDIRS += designer SUBDIRS += examples
102、MSVC编译器的选择说明
如果是32位的Qt则编译器选择x86开头的
如果是64位的Qt则编译器选择amd64开头的
具体是看安装的Qt构建套件版本以及目标运行平台的系统位数和架构
一般现在的电脑默认以64位的居多,选择amd64即可
如果用户需要兼容32位的系统则建议选择32位的Qt,这样即可在32位也可以在64位系统运行
103、很多时候用QDialog的时候会发现阻塞了消息,而有的时候我们希望是后台的一些消息继续运行不要终止,此时需要做个设置。
QDialog dialog; dialog.setWindowModality(Qt::WindowModal);
104、很多初学者甚至几年工作经验的人,对多线程有很深的误解和滥用,尤其是在串口和网络通信这块,什么都往多线程里面丢,一旦遇到界面卡,就把数据收发啥的都搞到多线程里面去,殊不知绝大部分时候那根本没啥用,因为没找到出问题的根源。
1)如果你没有使用wait***函数的话,大部分的界面卡都出在数据处理和展示中,比如传过来的是一张图片的数据,你需要将这些数据转成图片,这个肯定是耗时的;
2)还有就是就收到的数据曲线绘制出来,如果过于频繁或者间隔过短,肯定会给UI造成很大的压力的,最好的办法是解决如何不要频繁绘制UI比如合并数据一起绘制等;
3)如果是因为绘制UI造成的卡,那多线程也是没啥用的,因为UI只能在主线程;
4)串口和网络的数据收发默认都是异步的,由操作系统调度的,如果数据处理复杂而且数据量大,你要做的是将数据处理放到多线程中;
5)如果没有严格的数据同步需求,根本不需要调用wait***之类的函数来立即发送和接收数据,实际需求中大部分的应用场景其实异步收发数据就足够了;
6)有严格数据同步需求的场景还是放到多线程会好一些,不然你wait***就卡在那边了;
7)多线程是需要占用系统资源的,理论上来说,如果线程数量超过了CPU的核心数量,其实多线程调度可能花费的时间更多,各位在使用过程中要权衡利弊;