一、QT是什么?
QT 是一个功能强大、应用广泛的跨平台 C++ 应用程序开发框架,它不仅提供了丰富多样、美观实用的图形界面组件,还具备高效灵活的信号与槽通信机制,能够帮助开发者轻松构建出复杂且性能优越的应用程序,广泛应用于桌面应用、移动应用、嵌入式系统等众多领域。
如
对比维度 | QT(基于 C++) | C# |
---|---|---|
语言类型 | C++ 是一种中级编程语言 | C# 是一种高级编程语言 |
运行平台 | 跨平台(Windows、Mac、Linux 等) | 主要在 Windows 平台上表现出色,也支持跨平台但相对较弱 |
内存管理 | 手动内存管理,需要开发者自行处理 | 自动内存管理,减少内存泄漏风险 |
性能 | 通常在性能关键型应用中表现较好 | 性能也不错,但可能略逊于 C++ 在某些场景 |
开发效率 | 相对较低,需要更多的底层代码编写 | 较高,有丰富的库和工具支持 |
语法复杂度 | 语法相对复杂 | 语法较为简洁易懂 |
应用领域 | 多用于嵌入式系统、工业控制等 | 常用于 Web 应用、Windows 桌面应用、游戏开发等 |
社区支持 | 社区活跃,资源丰富 | 社区强大,有大量的开源项目和文档 |
二、QT中需要掌握什么?
1、C++编程语言:
(1)基本语法:变量,数据类型,控制结构;
(2)理解面向对象编程的概念:类,对象,继承,多态等
(3)内存管理:指针、动态内存分配等
2、QT 框架基础知识:
(1)了解QT的架构和工作原理
(2)熟悉 QT 的信号与槽机制
(3)掌握 QT 的窗口部件(Widgets)
3、图形用户界面(GUI)设计:
(1)控件布局
(2)学会自定义窗口部件的外观和行为
4、事件处理
(1)处理各种用户交互事件,如鼠标点击、键盘输入等
(2)理解事件的传播和捕获机制
5、数据存储和处理
(1)学会使用 QT 提供的数据结构和容器,如 QList、QMap 等
(2)掌握文件读写操作,以便保存和加载数据
6、多线程编程
(1)在 QT 中创建和管理多线程,以提高程序的性能和响应性
(2)处理多线程之间的同步和通信问题
三、安装
四、实践小实验
1、UI设计
自定义窗口部件的外观和行为,添加组合框;
2、信号与槽机制和事件处理
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QTimer>
#include <QStringList>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
resize(800,600); //窗口限制
setWindowTitle("Serial_Port");
SendByte=0;ReceByte=0;
serial = new QSerialPort(this);
ui->comboBox_2->setCurrentIndex(5); //初始化
ui->comboBox_3->setCurrentIndex(3);
ui->comboBox_4->setCurrentIndex(2);
ui->comboBox_5->setCurrentIndex(0);
ui->lineEdit->setText("1000");
ui->checkBox->setCheckState(Qt::Checked);
ui->checkBox_4->setCheckState(Qt::Checked);
ui->pushButton_7->setEnabled(false);
ui->checkBox_7->setEnabled(false);
connect(serial,SIGNAL(readyRead()), //信号与槽函数
this,SLOT(serialPort_readyRead()));
Times=0;portTime=0;
lineEditData=1000;
timer = new QTimer;
timer->start(1);
//connect(timer,&QTimer::timeout,this,&Widget::TimerEvent);
connect(timer,SIGNAL(timeout()),this,SLOT(TimerEvent())); //信号与槽函数
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_2_clicked()
{
if(ui->pushButton_2->text()==QString("打开串口"))
{
//设置串口名
serial->setPortName(ui->comboBox->currentText());
//设置波特率
serial->setBaudRate(ui->comboBox_2->currentText().toInt());
//设置数据位
switch(ui->comboBox_3->currentText().toInt())
{
case 5:serial->setDataBits(QSerialPort::Data5);break;
case 6:serial->setDataBits(QSerialPort::Data6);break;
case 7:serial->setDataBits(QSerialPort::Data7);break;
case 8:serial->setDataBits(QSerialPort::Data8);break;
default:serial->setDataBits(QSerialPort::UnknownDataBits);break;
}
//设置奇偶校验位
switch(ui->comboBox_4->currentIndex())
{
case 0:serial->setParity(QSerialPort::EvenParity);break;
case 1:serial->setParity(QSerialPort::MarkParity);break;
case 2:serial->setParity(QSerialPort::NoParity);break;
case 3:serial->setParity(QSerialPort::OddParity);break;
default:serial->setParity(QSerialPort::UnknownParity);break;
}
//设置停止位
switch (ui->comboBox_5->currentIndex())
{
case 0:serial->setStopBits(QSerialPort::OneStop);break;
case 1:serial->setStopBits(QSerialPort::OneAndHalfStop);break;
case 2:serial->setStopBits(QSerialPort::TwoStop);break;
default:serial->setStopBits(QSerialPort::UnknownStopBits);break;
}
//设置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);
//打开串口
if(!serial->open(QIODevice::ReadWrite))
{
QMessageBox::about(NULL,"提示","无法打开串口");
return;
}
//下拉控件失能
ui->comboBox->setEnabled(false);
ui->comboBox_2->setEnabled(false);
ui->comboBox_3->setEnabled(false);
ui->comboBox_4->setEnabled(false);
ui->comboBox_5->setEnabled(false);
ui->pushButton->setEnabled(false);
ui->checkBox_7->setEnabled(true);
ui->pushButton_2->setText(tr("关闭串口"));
ui->pushButton_7->setEnabled(true);
}
else
{
//关闭串口
serial->close();
//下拉按键使能
ui->comboBox->setEnabled(true);
ui->comboBox_2->setEnabled(true);
ui->comboBox_3->setEnabled(true);
ui->comboBox_4->setEnabled(true);
ui->comboBox_5->setEnabled(true);
ui->pushButton->setEnabled(true);
ui->checkBox_7->setEnabled(false);
ui->pushButton_2->setText(tr("打开串口"));
//发送失能
ui->pushButton_7->setEnabled(false);
}
}
void Widget::on_pushButton_clicked() //扫描串口
{
int i,n;
ui->comboBox->clear();
portStringLine.clear();
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
portStringLine +=info.portName();
n=portStringLine.size();
for(i=0;i<n;i++)
{
serial->setPortName(portStringLine[i]);
if(!serial->open(QIODevice::ReadWrite))
{
portStringLine[i]+="(不可用)";
QVariant v(0); //禁用
ui->comboBox->setItemData(1, v, Qt::UserRole - 1);
}
else
{
QVariant v(1|32); //可用
ui->comboBox->setItemData(1, v, Qt::UserRole - 1);
}
serial->close();
}
ui->comboBox->addItems(portStringLine);
}
void Widget::serialPort_readyRead() //串口接收
{
int i,length;
QString lasttext;
if(ui->checkBox_3->checkState()!=Qt::Checked)
{
lasttext=ui->textEdit->toPlainText();
Receivetext = serial->readAll();
ReceByte+=Receivetext.length();
ui->label_10->setText(QString::number(ReceByte));
if(ui->checkBox_2->checkState()==Qt::Checked)
{
Receivetext=Receivetext.toLatin1().toHex(); //字符串转十六进制
length=Receivetext.length();
for(i=0;i<=length/2;i++)
{
Receivetext.insert((2+3*i),' '); //插入空格字符串
}
}
else
Receivetext=Receivetext.toLatin1();
lasttext=lasttext.append(Receivetext);
ui->textEdit->setText(lasttext);
}
}
void Widget::on_pushButton_7_clicked() //串口发送
{
QByteArray bytearray;
Sendtext=ui->textEdit_2->toPlainText();
if(ui->checkBox_6->checkState()==Qt::Checked)
Sendtext += '\n';
if(ui->checkBox_5->checkState()!=Qt::Checked)
bytearray = Sendtext.toLatin1();
else
bytearray = QByteArray::fromHex(Sendtext.toUtf8()); //十六进制转字符串
serial->write(bytearray);
//定长发送
//serial->write((const char *)param_data,16);
SendByte+=Sendtext.length();
ui->label_9->setText(QString::number(SendByte));
ui->textEdit_2->moveCursor(QTextCursor::End);
}
void Widget::TimerEvent() //定时事件,1ms
{
int t=500; //扫描串口时间
Times++;portTime++;
if(Times>=lineEditData) //定时发送
{
if(ui->checkBox_7->checkState()==Qt::Checked)
Widget::on_pushButton_7_clicked();
Times=0;
}
if(portTime==t) //定时扫描串口
{
QStringList newPortStringList;
newPortStringList.clear();
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
newPortStringList += info.portName();
if(newPortStringList.size() != portStringLine.size())
{
portStringLine = newPortStringList;
ui->comboBox->clear();
ui->comboBox->addItems(portStringLine);
}
portTime=0;
}
}
void Widget::on_pushButton_8_clicked() //清除计数
{
SendByte=0;
ReceByte=0;
ui->label_9->setText(QString::number(SendByte));
ui->label_10->setText(QString::number(ReceByte));
}
void Widget::on_pushButton_4_clicked() //清除接收区
{
ui->textEdit->clear();
}
void Widget::on_pushButton_6_clicked() //清除发送区
{
ui->textEdit_2->clear();
}
void Widget::on_checkBox_clicked() //文本接收
{
ui->checkBox->setCheckState(Qt::Checked);
ui->checkBox_2->setCheckState(Qt::Unchecked);
ui->checkBox_3->setCheckState(Qt::Unchecked);
}
void Widget::on_checkBox_2_clicked() //十六进制接收
{
ui->checkBox->setCheckState(Qt::Unchecked);
ui->checkBox_2->setCheckState(Qt::Checked);
ui->checkBox_3->setCheckState(Qt::Unchecked);
}
void Widget::on_checkBox_3_clicked() //暂停接收
{
ui->checkBox->setCheckState(Qt::Unchecked);
ui->checkBox_2->setCheckState(Qt::Unchecked);
ui->checkBox_3->setCheckState(Qt::Checked);
}
void Widget::on_checkBox_4_clicked() //文本发送
{
ui->checkBox_4->setCheckState(Qt::Checked);
ui->checkBox_5->setCheckState(Qt::Unchecked);
}
void Widget::on_checkBox_5_clicked() //十六进制发送
{
ui->checkBox_4->setCheckState(Qt::Unchecked);
ui->checkBox_5->setCheckState(Qt::Checked);
}
void Widget::on_pushButton_5_clicked() //打开文件
{
QString fileName = QFileDialog::getOpenFileName(this);
QFile file(fileName); //新建QFile对象
if(!file.open(QFile::ReadOnly|QFile::Text))
{
QMessageBox::warning(this,tr("多文档编辑器"),
tr("无法读取文件 %1:\n%2")
.arg(fileName,file.errorString()));
}
QTextStream in(&file); //新建文本流对象
// 鼠标指针变为等待状态
QApplication::setOverrideCursor(Qt::WaitCursor);
//读取文件的全部文本内容,并添加到编辑器中
ui->textEdit_2->setPlainText(in.readAll());
//鼠标指针恢复为原来状态
QApplication::restoreOverrideCursor();
ui->textEdit->setVisible(true);
}
void Widget::on_pushButton_3_clicked() //保存文件
{
QString fileName = QFileDialog::getSaveFileName(this);
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text))
{
// %1和%2分别对应后面arg两个参数,/n起换行的作用
QMessageBox::warning(this, tr("多文档编辑器"),
tr("无法写入文件 %1:/n %2")
.arg(fileName, file.errorString()));
}
QTextStream out(&file);
// 鼠标指针变为等待状态
QApplication::setOverrideCursor(Qt::WaitCursor);
out << ui->textEdit->toPlainText();
// 鼠标指针恢复原来的状态
QApplication::restoreOverrideCursor();
}
void Widget::on_lineEdit_editingFinished() //输入定时时间
{
if(ui->lineEdit->text().toInt()>0)
lineEditData=ui->lineEdit->text().toInt();
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QtSerialPort>
#include <QSerialPortInfo>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
int Times,portTime,lineEditData;
private:
Ui::Widget *ui;
QSerialPort *serial; //串口端口
QTimer *timer; //定时器
QString Sendtext,Receivetext; //发送、接收缓存区
long int SendByte,ReceByte; //发送、接收字符数
QStringList portStringLine; //端口链表
private slots:
void serialPort_readyRead(); //串口接收
void TimerEvent(); //定时发送、更新串口
void on_pushButton_clicked(); //扫描串口
void on_pushButton_2_clicked(); //打开串口键按下
void on_pushButton_7_clicked(); //串口发送
void on_pushButton_8_clicked(); //清除计数
void on_pushButton_4_clicked(); //清除接收区
void on_pushButton_6_clicked(); //清除发送区
void on_checkBox_clicked(); //文本接收
void on_checkBox_2_clicked(); //十六进制接收
void on_checkBox_3_clicked(); //暂停接收
void on_checkBox_4_clicked(); //文本发送
void on_checkBox_5_clicked(); //十六进制发送
void on_pushButton_5_clicked(); //打开文件
void on_pushButton_3_clicked(); //保存文件
void on_lineEdit_editingFinished(); //输入定时时间
};
#endif // WIDGET_H
并在.pro文件中添加支持
QT += serialport
3、更改样式表
/* 按键普通状态 */
QPushButton
{
width: 336px;
height: 48px;
line-height: 48px;
background: #4e6ef2;
border-radius: 10px;
box-shadow: 0 6px 16px 0 rgb(78 111 242 / 30%);
font-size: 17px;
font-weight: 800;
border: 0;
color: #fff;
cursor: pointer;
}
/* 按键按下状态 */
QPushButton:pressed
{
/*背景颜色*/
background-color:rgb(14 , 135 , 228);
/*左内边距为3像素,让按下时字向右移动3像素*/
padding-left:3px;
/*上内边距为3像素,让按下时字向下移动3像素*/
padding-top:3px;
}