本人在刚接触Qt时,碰到很多坑,光安装软件就折腾了好几次,真的是心累,话不多说,我们就从安装开始简单讲起,不是很重要的步骤我就跳过哈。
下载Qt 在线安装软件
使用清华镜像:
Index of /qt/development_releases/online_installers/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror
在线安装
自行注册一个用户名,登录后一步一步来到这个页面,选用户安装。
这里我们先暂时选自己用的Qt版本,勾选MSVC编译器或MinGW以及Debug组件就可以,后面有别的需求可以通过Uninstall Qt来更改,之后就是一直下一步等待安装完成。
介绍一下 Qt 安装模块:
MSVC是指微软的VC编译器。
MinGW xxx 编译器模块,MinGW 是 Minimalist GNU for Windows 的缩写,是 Windows 平台上使用的 GNU 工具集导入库的集合。
Android 编译器模块,用于开发 Android 程序,如 Android x86 和 Android ARMv7。
Sources 模块是 Qt 的源程序。
Qt Charts 是二维图表模块,用于绘制柱状图、饼图、曲线图等常用二维图表。
Qt Data Visualization 是三维数据图表模块,用于数据的三维显示,如散点的三维空间分布、三维曲面等。
Qt Quick 3D 提供了用于基于 Qt Quick 创建 3D 内容或 UI 的高级API。提供了对现有Qt Quick场景图(scenegraph )的扩展,以及对该扩展场景图的渲染器。(Qt5.15正式加入)
Qt Scritp(Deprecated)是脚本模块,括号里的“Deprecated”表示这是已经过时的模块。
Qt Virtual Keyboard 模块,是实现不同输入法的虚拟键盘框架。
Qt WebEngine 模块,提供类和函数,实现在应用程序中嵌入网页内容。
Qt Purchasing 模块,提供一些类,在 Qt 应用程序内实现应用内购买的功能。
-
安装完成
第一次安装选择MSVC 2019 64Bit后Kit是感叹号,新建一个工程编译一大堆错误,于是又去下载了vs_professional 2019安装助手,才搞得。下载链接https://visualstudio.microsoft.com/zh-hans/vs/,安装C++这个;安装完重启下电脑,否则还是有可能无效。
新建一个Qt widgets项目
使用qmake,QWidget为基类。
按F5或者点这三角形运行按键,能弹出窗体就恭喜你。
初识Qt widgets
双击.ui文件, 进入到UI设计界面, 无论是MFC,C#控件的作用都是差不多的, Qt里面可以直接从左侧直接拖进来,双击控件即可以改控件内容文本。就是这个布局,如果真的要用这个水平,垂直布局来这么对齐,每次选择拖动都不方便,那还不如在代码实现,这里不得不说用着没VS C# UI设计方便,但是功能多了甚多。Shift + Alt + R 可以预览界面布局。
那么添加控件处理程序呢?选择控件->鼠标右击->转到槽,选择需要的信号就可以到函数了。
Qt信号与槽
Qt很NB的一个功能就是信号与槽,就是下面这个connect函数,简单理解一个发送者,发送函数,另一个接受者,接受函数。发送函数与处理函数可带形参,形参类型最好保持一致。使用disconnect函数取消关联。
定义信号规则:
- 声明在类的signals域下
- 没有返回值,void类型的函数
- 只有函数声明,没有定义
- 可以有参数,可以重载
- 通过emit关键字来触发信号,形式:emit object->sig(参数);
定义槽函数
- qt4 必须声明在 private/public/protected slots域下面,qt5之后可以声明public下,同时还可以是静态的成员函数,全局函数,lambda表达式
- 没有返回值,void类型的函数
- 不仅有声明,还得要有实现
- 可以有参数,可以重载
上面是Qt自带的帮助文件,很详细。鼠标放在函数上,按F1,F2就可。Qt的函数真的很多,自认为有一些基础都感觉不够了解,那怎么办,用到啥看啥,不懂先百度。
就比如Qt编辑框就有4种,各位看客可看帮助文档详细了解。这里我贴出他们的继承关系就可以了哈。
// class Q_WIDGETS_EXPORT QLineEdit : public QWidget
// class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea
// class Q_WIDGETS_EXPORT QPlainTextEdit : public QAbstractScrollArea
// class Q_WIDGETS_EXPORT QTextBrowser : public QTextEdit
Qt Lambda表达式
- Lambda表达式的基本构成:四个部分:[局部变量捕获列表]、(函数参数)、函数 额外属性设置opt、函数返回值->retype、{函数主体}。由于引用方式捕获对象会有 局部变量释放了而lambda函数还没有被调用的情况。如果执行lambda函数那么 引用传递方式捕获进来的局部变量的值不可预知。所以在无特殊情况下建议使用 [=](){}的形式。
[capture](parameters) opt ->retType
{
……;
}
[]表示lambda表达式不能访问外部函数体的任何局部变量
[a]在函数体内部使用值传递的方式访问a变量
[&b]在函数体内部使用引用传递的方式访问b变量
[=]函数外的所有局部变量都通过值传递的方式使用, 函数体内使用的是副本
[&]引用的方式使用lambda表达式外部的所有变量
[=, &foo] foo使用引用方式, 其余是值传递的方式
[&,foo] foo使用值传递方式, 其余是引用传递的方式
[this]在函数内部可以使用类的成员函数和成员变量,=和&形式也都会默认引入
Qt技巧
- .pro文件的规则:
1.注释:从“#”开始,到这一行结束。
2.模块引入:QT += 模块名,表示当前项目引入Qt哪些模块。
- 快捷键
运行 ctrl +R 编译 ctrl +B
帮助文档 F1 ,点击F1两次跳到帮助界面
跳到符号定义 F2 或者ctrl + 鼠标点击
注释 ctrl+/
字体缩放 ctrl + 鼠标滚轮
整行移动代码 ctrl + shift + ↑或↓
自动对齐 ctrl + i
同名之间的.h和.cpp文件跳转 F4
写个串口工具
解了一下个常见控件的基本用法,涉及基本控件,定时器,串口,文件,List,Tab Widgets等基本操作。讲一下几个注意点:
1.更改控件背景
可以添加资源文件,在ui设计器里面完成,也可以通过代码完成。代码使用setStyleSheet函数。
2.定时器两种 :
QTime类 与、QObject:: setTimer, 前者通过信号与槽可实现定时溢出处理,后者类似MFC定时器的使用,通过定时器ID在timerEnevt函数中处理。
3.串口QSerialPort :
添加这个两个头文件 #include <QSerialPort>,#include <QSerialPortInfo>,还需要.pro文件添加QT += serialport这一句。
4.文件操作 :在Open文件时就选择好操作权限既可;
5.中英文切换
- .pro文件添加 TRANSLATIONS += LanguageCH.ts \
LanguageEN.ts
- 菜单栏工具里面选择
- 去到工程文件,你会发现多了两个.ts的文件。
- 开始菜单->Qt Linguist程序,启动它
- 由于界面默认使用的英文显示,所以只对中文文件进行翻译,选择中文的ts文件 打开,翻译完成文件保存,发布。英文的ts文件打开之后直接发布。然后会得到 两个.qm的同名文件。并将两个拷贝放在Debug同级目录下,新建一个translator 文件。
- 添加头文件#include <QTranslator>,定义 QTranslator *pQTranslator指针并初始化,
在按键处理中添加;
strApplicationPath = QDir::currentPath()
if(pQTranslator->load(strApplicationPath+"//translator//LanguageEN.qm"))
{
qApp->installTranslator(pQTranslator);
ui->retranslateUi(this);
}
生成可执行文件
Qt程序写好后,按一下方法生成Release版本,去到Release文件后,你会发现双击不行运行起来,这个时候我们只需要把exe文件拷贝到一个新建文件夹,用终端命令行输入windeployqt 你新建文件夹的exe的绝对路径,就自动完成所依赖的文件拷贝,在会到文件夹就可以运行了。
未完待续....
我的疑问
Qt的中英文乱码问题真的很神奇,串口发送,写入TXT中文始终乱码,但是上位机显示正常,希望有知道的朋友告知一下,感谢。后续补充上完整测试项目代码,
void Widget::file_WriteLog(QString strFileName, QString strText)
{
if(strFileName.isEmpty() == false)
{
QFile qFile(strFileName);
if( qFile.open(QFile::ReadWrite|QFile::Append) )
{
// QTextStream stream(&qFile);
// stream << strText
QByteArray arrayData = strText.toLatin1();
char *pcData = arrayData.data();
qFile.write(pcData,strText.size());
qFile.close();
}
}
}
void Widget::serialport_send(void)
{
QString strData = tr("123写入文件测试");
qint64 len = strData.size();
QByteArray arrayData = strData.toLatin1();
char *pcData = arrayData.data();
// char *pcData = strData.toLatin1().data(); //无效
this->pQSerialPort->write(pcData,len);
strData = plainTextEdit_print_log(strData);
file_WriteLog(strFileName,strData + "\n");
}