1、常用的国内镜像网站
以下是一些常用的QT国内镜像网站:
1. **中国科学技术大学**:http://mirrors.ustc.edu.cn/qtproject/
2. **清华大学**:https://mirrors.tuna.tsinghua.edu.cn/qt/
3. **北京理工大学**:http://mirror.bit.edu.cn/qtproject/
4. **中国互联网络信息中心**:https://mirrors.cnnic.cn/qt/
5. **南京大学**:https://mirror.nju.edu.cn/qt/
6. **腾讯**:https://mirrors.cloud.tencent.com/qt/
7. **阿里云**:https://mirrors.aliyun.com/qt/
2、模拟创建一个汽车仪表盘项目(cardisp.h)
3、cardisp.h
#ifndef CARDISP_H
#define CARDISP_H
#include <QWidget>
#include <QApplication>
#include <QTimer>
#include <QPainter>
#include <QElapsedTimer>
#include <QContextMenuEvent>
#include <QLineEdit>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QMenu>
#include <QInputDialog>
#include <QRect>
#include <QtMath>
#include <QKeyEvent>
#include <QDebug>
class CarDisp : public QWidget
{
Q_OBJECT
public:
CarDisp(QWidget*parent=nullptr);
~CarDisp();
void setvalues(qreal ivalues);//当前速度值;
void paintEvent(QPaintEvent *event) override;//绘制
void setTitel(const QString& title);
private:
qreal values=0;
const static int radius;//静态的半径常数;
const static int maxv;//最大;
const static int minv;//最小;
QString m_title="SUBARU BRZ";
QLineEdit *titleEditor =nullptr;//添加标题编辑器
bool titleEditing = false;//标记是否正在编辑
void startTitleEditing();
QRect titleRect;//保存标题框位置
private slots://模拟车速变化,定时器实现
void updateSpeed();
private:
bool isThrottlePressed = false;//用于计算长按时间
QTimer *timer;
QElapsedTimer throttleTimer;//
qreal currentSpeed = 0.0;//当前速度
qreal acceleration = 2.0;
qreal deceleration = 1.0;
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event)override;//鼠标释放事件
void contextMenuEvent(QContextMenuEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
};
#endif //
4、cardisp.cpp
#include "cardisp.h"
const int CarDisp:: radius=150;//命名空间 CarDisp在前面
const int CarDisp:: maxv=200;//最大
const int CarDisp:: minv=0;//最小
void CarDisp::setTitel(const QString &title)
{
m_title=title;
update();//触发重绘制
}
CarDisp::~CarDisp(){}
void CarDisp::setvalues(qreal ivalues)
{
values=ivalues;//调用此函数时,将ivalues的值赋值给values
update();
}
void CarDisp::keyPressEvent(QKeyEvent *event)
{
if(titleEditing && event->key()==Qt::Key_Escape)
{
titleEditor->hide();
titleEditing =false;
update();
}
else if(titleEditing && event->key()==Qt::Key_Return)
{
//回车键确认编辑
titleEditor->clearFocus();
}
else
{
QWidget::keyPressEvent(event);//其它按键交给父类处理
}
}
//仪表盘半径最大最小值
void CarDisp::paintEvent(QPaintEvent *)
{
QPainter painter( this);
painter.setRenderHint(QPainter::Antialiasing);//设置抗锯齿
QPoint center(width()/2,height()/2);//对准窗口中间;
painter.save();
painter.translate(center);//绘制背景圆形
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(70,94,150));//设置背景颜色;
const int bkRadius = radius+3;//比背景半径略大
painter.drawEllipse( QPoint(),bkRadius,bkRadius);
//刻度
painter.rotate(-135);
const int longstep=10;
const int shortstep=50;
for(int i=0; i<=shortstep;i++)
{
painter.setPen((i<shortstep*0.8)? QColor(32,243,32):QColor(243,32,32)); //满足条件为绿色否则为红色
if(i%(shortstep/longstep)!=0)
{
QPoint p1(0,-(radius-8));
QPoint p2(0,-radius);
painter.drawLine(p1,p2);
}
else
{
QPoint p1(0,-(radius-14));
QPoint p2(0,-radius);
painter.drawLine(p1,p2);
}
painter.rotate(270.0/shortstep);
}
//绘制表盘名称和背景矩形
painter.restore();
QFontMetrics fm=painter.fontMetrics();
int tx=center.x();
int ty=int(center.y()+(radius/1.412));
QString title=m_title;//使用m_title自定义标题
QSize tsz=fm.size(0,title);
QRect trect(QPoint(tx-tsz.width()/2,ty-tsz.height()/2),tsz);
if(!titleEditing){
}
painter.drawText(trect,title);//绘制每个长刻度对应的文字
painter.setPen(QColor(243,243,243));
const int hand=radius-21;//表盘中心
for(int i=0; i<=longstep;i++)
{
qreal angle = qDegreesToRadians(-135.0+i*(270.0/longstep));
QString etext = QString::number(minv+i*(maxv-minv)/longstep);
QPointF dirvec(qSin(angle),-qCos(angle));
QPointF ecenter(center.x()+hand*dirvec.x(),center.y()+hand*dirvec.y());
QSize esz =fm.size(0,etext);
QRectF erect(QPointF(ecenter.x()-esz.width()/2,ecenter.y()-esz.height()/2),esz);
painter.drawText(erect,etext);
}
//绘制速度数字显示
QRect lcdRect(center.x()-50,center.y()+30,100,40);//矩形区域
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(0,0,0));//黑色背景
painter.drawRect(lcdRect);
painter.setPen(QColor(255,255,0));//黄色文字
painter.setFont(QFont("Arial",16,QFont::Bold));
painter.drawText(lcdRect,Qt::AlignHCenter,QString::number(values));
//绘制仪表盘
painter.save();
QPoint triangle[]={
{-5,0},
{0,25-radius},
{3,0}
};
qreal degree =-135.0+270*(values-minv)/(maxv-minv);
painter.translate(center);
painter.rotate(degree);
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::red);
painter.drawPolygon(triangle,3);
painter.setPen(QPen(QColor(117,0,0),2));//指针颜色
painter.drawEllipse(QPoint(),7,7);
painter.restore();
//绘制3D红色油门按钮
QPoint buttonCenter(width()-100,height()-150);
int buttonRadius=40;
//根据是否按下调整颜色
QColor baseColor = isThrottlePressed? QColor(150,0,0):QColor(255,50,50);
QRadialGradient gradient(buttonCenter,buttonRadius);
gradient.setColorAt(0,baseColor.lighter(120));
gradient.setColorAt(0,baseColor.darker(120));
painter.setPen(QPen(QColor(100,0,0),2));
painter.setBrush(gradient);
painter.drawEllipse(buttonCenter,buttonRadius,buttonRadius);
//高光效果
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(255,255,255,100));
painter.drawEllipse(buttonCenter,buttonRadius-5,buttonRadius-5);
//按钮文字
painter.setPen(Qt::white);
painter.setFont(QFont("Arial",12,QFont::Bold));
painter.drawText(QRect(buttonCenter.x()-30,buttonCenter.y()-10,60,20),Qt::AlignCenter,"油门");
qDebug()<<"Painting button at:"<< buttonCenter
<<"Widget size:"<<size();
}
void CarDisp::startTitleEditing()
{
titleEditing =true;
titleEditor->setText(m_title);
titleEditor->setGeometry(titleRect);
titleEditor->show();
titleEditor->setFocus();
update();
}
CarDisp::CarDisp(QWidget *parent):QWidget(parent)
{
values=0;
timer = new QTimer(this);
connect(timer,&QTimer::timeout,this,&CarDisp::updateSpeed);
//创建标题编辑(初始隐藏)
titleEditor=new QLineEdit(this);
titleEditor->hide();
titleEditor->setAlignment(Qt::AlignCenter);
titleEditor->setStyleSheet("QLineEdit{background:#ADA3A3; color:#F3F3F3;}");
titleEditor->setFont(QFont("Arial",12));
connect(titleEditor,&QLineEdit::editingFinished,this,[this]()
{
m_title=titleEditor->text();
titleEditor->hide();
titleEditing=false;
update();
});
}
void CarDisp::contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu(this);
QAction*renameAction = menu.addAction("修改表盘名称");
if(menu.exec(event->globalPos())==renameAction){
bool ok;
QString newTitle = QInputDialog::getText(
this,
"修改表盘名称",
"请输入新的表盘名称:",
QLineEdit::Normal,
m_title,
&ok
);
if (ok && !newTitle.isEmpty())
{
setTitel(newTitle);
}
}
}
void CarDisp::mousePressEvent(QMouseEvent *event){
//调试输出
qDebug()<<"点击检测-屏幕坐标:"<<event->pos()
<<"标题区域:"<<titleRect
<<"是否命中:"<<titleRect.contains(event->pos());
if(event->button()==Qt::LeftButton)
{
isThrottlePressed=true;
throttleTimer.start();//开始计时
timer->start(16);
}
QWidget::mousePressEvent(event);
//检测是否点击了标题框
if(titleRect.contains(event->pos()))
{
startTitleEditing();
return;//直接返回 不处理其它逻辑
}
QPoint buttoncenter(width()-100,height()-100);
int buttonRadius=40;
//计算点击位置与按钮中心的距离
QPoint clickPos = event->pos();
qreal distance = qSqrt(qPow(clickPos.x()-buttoncenter.x(),5)+ qPow(clickPos.y()-buttoncenter.y(),5));
if(distance<=buttonRadius && event->button()==Qt::LeftButton){ //只在按钮区域内响应
isThrottlePressed=true;
throttleTimer.start();
timer->start(16);
update();//重绘按钮状态
}
qDebug() << "点击位置:" <<event->pos()
<< "标题区域" <<titleRect
<< "是否命中:" <<titleRect.contains(event->pos());
QWidget::mousePressEvent(event);
}
void CarDisp::mouseReleaseEvent(QMouseEvent *event){
if(isThrottlePressed)
{
isThrottlePressed =false;
update();//重绘按钮状态;
}
QWidget::mouseReleaseEvent(event);
}
void CarDisp::updateSpeed(){
if(isThrottlePressed)
{
//计算长按时间(秒),10s对应200km/h
qreal pressTimeSec = throttleTimer.elapsed()/1000.0;
qreal targetSpeed= qMin(pressTimeSec*20,static_cast<qreal>(maxv));//线性增长
//从当前速度开始加速
currentSpeed= qMin(currentSpeed+acceleration,targetSpeed);
values=qMin(values+acceleration,currentSpeed);
//指针平滑跟随
values=qMin(values+2,static_cast<qreal>(currentSpeed));//缓冲效果
}
else
{
//松开油门时减速
currentSpeed =qMax(currentSpeed-deceleration,0.0);
values= qMax(values-deceleration,0.0);
//完全停止后关闭定时器
if(currentSpeed<0.1)
{
timer->stop();
}
update(); //触发重绘
}
}
5、简单函数和控制台输出演示
6、代码部分
#include<iostream>
using namespace std;
void printMax(int nArg1=2, int nArg2=3)
{
cout << "Max of " << nArg1 << " and " << nArg2 << " is " << ((nArg1 >= nArg2)? nArg1 : nArg2) << endl;
}
int main()
{
printMax(10,6);//形参nArg1=10,nArg2=6
printMax(5);//形参nArg1=5,nArg2为默认值3
printMax();//形参nArg1为默认值2,nArg2为默认值3
return 0;
}
7、QT串口通信类使用
8、串口示例程序(全部由AI豆包生成)
9、头文件mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_openButton_clicked();
void on_sendButton_clicked();
void readData();
void on_clearButton_clicked();
private:
Ui::MainWindow *ui;
QSerialPort *serial;
void initSerialPortSettings();
};
#endif // MAINWINDOW_H
10、Main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
11、mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QMessageBox>
#include <QDateTime>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle("Qt串口通信示例");
serial = new QSerialPort(this);
initSerialPortSettings();
connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData);
}
MainWindow::~MainWindow()
{
if (serial->isOpen()) {
serial->close();
}
delete ui;
}
void MainWindow::initSerialPortSettings()
{
// 填充串口设备列表
ui->portComboBox->clear();
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
ui->portComboBox->addItem(info.portName());
}
// 填充波特率列表
ui->baudComboBox->clear();
ui->baudComboBox->addItem("9600", QSerialPort::Baud9600);
ui->baudComboBox->addItem("115200", QSerialPort::Baud115200);
ui->baudComboBox->addItem("57600", QSerialPort::Baud57600);
ui->baudComboBox->addItem("38400", QSerialPort::Baud38400);
ui->baudComboBox->setCurrentText("115200");
// 填充数据位列表
ui->dataBitsComboBox->clear();
ui->dataBitsComboBox->addItem("8", QSerialPort::Data8);
ui->dataBitsComboBox->addItem("7", QSerialPort::Data7);
ui->dataBitsComboBox->addItem("6", QSerialPort::Data6);
ui->dataBitsComboBox->addItem("5", QSerialPort::Data5);
ui->dataBitsComboBox->setCurrentText("8");
// 填充停止位列表
ui->stopBitsComboBox->clear();
ui->stopBitsComboBox->addItem("1", QSerialPort::OneStop);
ui->stopBitsComboBox->addItem("1.5", QSerialPort::OneAndHalfStop);
ui->stopBitsComboBox->addItem("2", QSerialPort::TwoStop);
// 填充校验位列表
ui->parityComboBox->clear();
ui->parityComboBox->addItem("None", QSerialPort::NoParity);
ui->parityComboBox->addItem("Even", QSerialPort::EvenParity);
ui->parityComboBox->addItem("Odd", QSerialPort::OddParity);
ui->parityComboBox->addItem("Mark", QSerialPort::MarkParity);
ui->parityComboBox->addItem("Space", QSerialPort::SpaceParity);
}
void MainWindow::on_openButton_clicked()
{
if (serial->isOpen()) {
serial->close();
ui->openButton->setText("打开串口");
ui->statusLabel->setText("串口已关闭");
} else {
// 设置串口参数
serial->setPortName(ui->portComboBox->currentText());
serial->setBaudRate(ui->baudComboBox->currentData().toInt());
serial->setDataBits(static_cast<QSerialPort::DataBits>(ui->dataBitsComboBox->currentData().toInt()));
serial->setStopBits(static_cast<QSerialPort::StopBits>(ui->stopBitsComboBox->currentIndex()));
serial->setParity(static_cast<QSerialPort::Parity>(ui->parityComboBox->currentIndex()));
serial->setFlowControl(QSerialPort::NoFlowControl);
// 打开串口
if (serial->open(QIODevice::ReadWrite)) {
ui->openButton->setText("关闭串口");
ui->statusLabel->setText("串口已打开");
} else {
QMessageBox::critical(this, "错误", "无法打开串口: " + serial->errorString());
ui->statusLabel->setText("打开串口失败");
}
}
}
void MainWindow::on_sendButton_clicked()
{
if (serial->isOpen()) {
QString data = ui->sendTextEdit->toPlainText();
if (!data.isEmpty()) {
qint64 bytesWritten = serial->write(data.toUtf8());
if (bytesWritten == -1) {
ui->statusLabel->setText("发送失败");
} else if (bytesWritten < data.length()) {
ui->statusLabel->setText("部分数据发送失败");
} else {
ui->statusLabel->setText("数据发送成功");
// 在接收区显示发送的数据,添加时间戳
QString currentTime = QDateTime::currentDateTime().toString("HH:mm:ss");
ui->receiveTextEdit->append("[" + currentTime + " 发送] " + data);
}
}
} else {
QMessageBox::warning(this, "警告", "串口未打开");
}
}
void MainWindow::readData()
{
QByteArray data = serial->readAll();
if (!data.isEmpty()) {
// 在接收区显示接收到的数据,添加时间戳
QString currentTime = QDateTime::currentDateTime().toString("HH:mm:ss");
ui->receiveTextEdit->append("[" + currentTime + " 接收] " + QString::fromUtf8(data));
}
}
void MainWindow::on_clearButton_clicked()
{
ui->receiveTextEdit->clear();
}
12、Ui文件编辑
13、Ui设计界面
13、Ui文件
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>624</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="serialSettingsGroupBox">
<property name="title">
<string>串口设置</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="portLabel">
<property name="text">
<string>串口:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="portComboBox"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="baudLabel">
<property name="text">
<string>波特率:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="baudComboBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="dataBitsLabel">
<property name="text">
<string>数据位:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="dataBitsComboBox"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="stopBitsLabel">
<property name="text">
<string>停止位:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QComboBox" name="stopBitsComboBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="parityLabel">
<property name="text">
<string>校验位:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="parityComboBox"/>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="openButton">
<property name="text">
<string>打开串口</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="receiveGroupBox">
<property name="title">
<string>接收区</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTextEdit" name="receiveTextEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clearButton">
<property name="text">
<string>清空接收区</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="sendGroupBox">
<property name="title">
<string>发送区</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QTextEdit" name="sendTextEdit"/>
</item>
<item>
<widget class="QPushButton" name="sendButton">
<property name="text">
<string>发送数据</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="text">
<string>状态: 就绪</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>29</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="toolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
14、项目构建目录修改
15、选择对应的编译器
16、QT终端
这是 Qt 6.9.0 版本基于 MinGW 13.1.0 64 位编译器的命令行终端窗口 。其中 “Setting up environment for Qt usage...” 提示正在设置 Qt 使用环境,当前路径为 C:\Qt\6.9.0\mingw_64 。Qt 是一个跨平台的 C++ 应用程序开发框架,可用于开发图形用户界面(GUI)程序,也能用于开发非 GUI 程序,如控制台工具和服务器。MinGW(Minimalist GNU for Windows)是在 Windows 平台上使用的 GNU 工具集合,提供了一套完整的开发环境,能让开发者在 Windows 下使用 GCC 等 GNU 工具来编译和构建程序。