本文用于记录学期期末实训内容,尽可能做到保姆级别的详细步骤,跟着做准能成

第一次写博客,请多担待

在整个工程中任何的路径不要有任何中文字符!!!

声明:我也只是个学习一般的学生,这是记录课上老师讲的内容,我现在只能说这么做能行,但我还不清楚为什么这样做,还在努力学习中。

目录

项目要求

安装QT

 创建工程

​编辑基本的界面布局 

 步骤

 功能实现

退出功能

绘制主界面

画线

红绿灯

该部分总代码


项目要求

·硬件使用Qt仿真,软件使用Qt

·做一个界面—界面设计、开发,信号和槽,事件,网络编程

·界面会显示车辆的运行信息,并且可以远程控制车辆的状态

安装QT

我使用的是QT5.14.2,安装前先断网

 不断网的话需要注册,比较麻烦,像这样子

然后安装

选择需要的组件,我选择了 全选

然后下一步,同意协议,下一步,开始安装即可,安装耗时大约10min~30min左右,耐心等待。 

 创建工程

文件->新建工程或项目->在项目中选择Application->QT Widgets Application

一路“下一步”到details页面,设置类名,然后基本类选QWidget,记得确定Generate form有被勾选 Kit选择Desktop Qt 5.14.2 WinGW 64-bit

点击下一步,知道完成创建

点击左下角的绿色三角,会弹出一个窗口,我们的项目就在其中实现

基本的界面布局 

先放一个大致的效果,然后咱们说步骤

 步骤

选择Form下的mainwindow.ui,双击跳转到ui编辑页面 

长这样

Button下的PushButton往里面拖几个,我拖了7个 

 双击拖进去的PushButton,修改上面的名字,我分别改成了

再拖一根Stacked Widget进去,充当不同功能的页面

 再从Containers里拖一个widget出来(注意,一定要放到第一层面板里,不要拖进stacked widget里面)

把PushButton们拖进widget里面,然后选中widget点击“水平布局”(框外那一排小按钮里) 

给widget里的PushButton们设置一下样式

 编写方式类似CSS样式表,点击”apply“

QPushButton{
height:40px;
	font: 24pt "隶书";
    color:rgb(0, 0, 0);
    background-color:rgb(38, 21, 100);

}

效果(随便弄的,有点丑,哈哈)

(出了一个小插曲 ,mian.cpp里面的这个默认MainWindow,报错了,改成Mainpage)

 选中主面板,然后设置为水平布局

拉一个弹簧(Vertical Spacer)用来隔开”系统设置“和”退出“

 接下来进一步优化按钮的效果,添加一个悬停和选中的样式改变

QPushButton{
height:40px;
	font: 24pt "隶书";
    color:rgb(0, 0, 0);
    background-color:rgb(38, 21, 100);

}
QPushButton::hover{
color:rgb(170, 0, 0);
background-color:rgbrgb(85, 255, 0);
}
QPushButton::pressed{
color:rgb(255, 170, 255);
background-color:rgbrgbrgb(255, 255, 127);
}

效果:(红配绿,哈哈哈哈)

 打开项目文件夹

将素材文件夹放入其中,以下素材是我自己找到

 推荐在阿里巴巴矢量库自行下载

网址:​​​​​iconfont-阿里巴巴矢量图标库

 那么接下来把素材导入工程

选择Qt->QT Resource File 

 点击choose然后随便起个名,下一步,完成

进入到这个界面,然后点击Add Prefix,修改前缀,放入素材,然后CTRL+S。

 

 添加完成后,我们返回UI给PushButton添加图标

 效果是这样

 最后浅浅地给标题栏添加一个图标和名称吧

放置在mainpage.cpp的Mainpage::Mainpage(QWidget *parent): QWidget(parent), ui(new Ui::Mainpage)里

    //设置文本框名称
     this->setWindowTitle(QStringLiteral("智慧交通系统"));
    // 访问到资源
    QIcon icon(":/icon/Image/mao.png");
    // 设置图标
    this->setWindowIcon(icon);

 功能实现

退出功能

这个功能最简单,利用信号与槽机制,转到槽,编辑槽函数,this->close();

信号与槽机制

声明了信号的对象,当其状态改变时,信号由该对象发送出去,槽用于接收和处理信号。当一个信号被发射时,与其相关联的槽将被立刻执行,就像一个正常的函数调用一样。

这样就实现了退出的功能

绘制主界面

QT事件

在QT系统中,事件是一种对象。他代表用户的某种操作或操作系统的某种行为。当用户在窗体中做出某种操作时往往会产生事件。

发生在stacked widget上的事件

在mianpage.h中写一个函数声明

protected:
    //事件过滤器,重写stackWidget中的绘图事件
    bool eventFilter(QObject *obj,QEvent *event);
/*QObject *obj:
该参数是一个指向 QObject 类型的指针。QObject 是 Qt 框架中的基类,许多 Qt 类都继承自 QObject。obj 表示产生事件的对象,例如,在一个 GUI 应用程序中,它可以是一个按钮、标签、窗口等。当事件发生时,该参数会指向触发该事件的对象。
QEvent *event:
该参数是一个指向 QEvent 类型的指针。QEvent 是 Qt 中表示事件的基类,Qt 中存在许多派生自 QEvent 的事件类,例如 QMouseEvent(鼠标事件)、QKeyEvent(键盘事件)、QPaintEvent(绘制事件)等。event 包含了事件的详细信息,例如事件的类型、发生的位置(对于鼠标事件)、按下的键(对于键盘事件)等。*/


光标移动到eventFilter上然后Alt+enter,回车,自动把函数实现写好

返回ui修改名称,第一个page改成了page_map

点击左下角的锤子重新构建

在这里多添加一句,他的事件由我们自己来过滤

   ui->page_map->installEventFilter(this);

根据帮助手册编写函数 

选中event Filter右击,选择上下文,Object,查看

bool Mainpage::eventFilter(QObject *obj, QEvent *event)
{
    // 检查事件源对象是否为 ui->page_map
    if (obj == ui->page_map) {
        // 检查事件是否为绘制事件(QEvent::Paint)
        if (event->type() == QEvent::Paint) {
            // 创建一个 QPainter 对象,并将 ui->page_map 作为绘图设备
            QPainter painter(ui->page_map);
            // 从资源路径 :/icon/Image/RoadMap.png 加载一个 QImage 对象
            QImage img(":/icon/Image/RoadMap.png");
            // 遍历 list_road 中的每个 Road 对象
            for (auto item : list_road) {
                // 使用 painter 绘制道路,起点为 item.start,终点为 item.end
                painter.drawLine(item.start, item.end);
            }
            // 在 ui->page_map 的矩形区域内绘制图像 img
            painter.drawImage(ui->page_map->rect(), img, img.rect());
            // 表示此绘制事件已被处理,不会再传递给其他对象处理
            return true;
        } else {
            // 对于其他事件类型,不进行处理,返回 false
            return false;
        }
    } else {
        // 如果事件源对象不是 ui->page_map,则将事件传递给父类的事件过滤器进行处理
        return QWidget::eventFilter(obj, event);
    }
}

效果图

画线

让程序在地图上画线

、首先在工程文件add new,类型为C++头文件

 在当中添加代码

#ifndef COMMON_H
#define COMMON_H
#include<QPoint>
//道路的构造函数
struct Road{
public:
    Road(const int &id,QPoint &start,const QPoint &end):
    id(id),
        start(start),end(end)
    {
    }
    int id;
    QPoint start,end;
    
};
#endif // COMMON_H

在mainpage.h中添加头文件 

在这里添加一句 QList<Road>list_road;

初始化道路信息,Alt+enter

 

画道路(mainpage.cpp)

bool Mainpage::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == ui->page_map) {
             if (event->type() == QEvent::Paint) {
                // QPainter painter(ui->page_map);
                 QPainter painter;
                 QImage img(":/icon/Image/RoadMap.png");

                 painter.begin(&img);
                 
                 //画道路
                 for(auto item:list_road){
                     painter.drawLine(item.start,item.end);
                 }
                 painter.end();


                 painter.begin(ui->page_map);
                 painter.drawImage(ui->page_map->rect(),img,img.rect());
                 painter.end();


                 return true;
             } else {
                 return false;
             }
         } else {
             // pass the event on to the parent class
             return QWidget::eventFilter(obj, event);
         }
}
void Mainpage::initRoad()
{
    int id=0;

            Road road1(id++,QPoint(85,34),QPoint(756,34));
            list_road.append(road1);
            Road road2(id++,QPoint(756,65),QPoint(85,65));
            list_road.append(road2);

            Road road3(id++,QPoint(31,86),QPoint(31,332));
            list_road.append(road3);
            Road road4(id++,QPoint(62,332),QPoint(62,86));
            list_road.append(road4);

            Road road5(id++,QPoint(778,86),QPoint(778,352));
            list_road.append(road5);
            Road road6(id++,QPoint(810,332),QPoint(810,86));
            list_road.append(road6);

            Road road7(id++,QPoint(756,349),QPoint(85,349));
            list_road.append(road7);
            Road road8(id++,QPoint(85,380),QPoint(756,380));
            list_road.append(road8);

            Road road9(id++,QPoint(31,404),QPoint(31,655));
            list_road.append(road9);
            Road road10(id++,QPoint(62,655),QPoint(62,404));
            list_road.append(road10);

            Road road11(id++,QPoint(778,404),QPoint(778,655));
            list_road.append(road11);
            Road road12(id++,QPoint(810,655),QPoint(810,404));
            list_road.append(road12);

            Road road13(id++,QPoint(756,675),QPoint(85,675));
            list_road.append(road13);
            Road road14(id++,QPoint(85,706),QPoint(756,706));
            list_road.append(road14);
}

优化道路线条(在Mainpage::eventFilter中)

 QPen pen;
                 pen.setColor(QColor(0,255,0));
                 pen.setWidth(3);
                 painter.setPen(pen);

效果:

红绿灯

在common.h里添加代码

//红绿灯
struct SingalLamp{
public:
    int count;//倒计时
//    int r_duration;给一个总的持续时间
    QColor color;//信号灯的颜色
};
//路口
struct Cross{
    public:
    Road *N_exit,*N_entrance,
         *S_exit,*S_entrance,
         *E_exit,*E_entrance,
         *W_exit,*W_entrance;
    int id;
    QRect local;
    QList<SingalLamp *>list_sl;//保存路口的信号灯
    QMap<Road *,SingalLamp *>road_sl;//可以得到道路和信号灯的关系
};

在mainpage.cpp添加

    QList<Cross>list_cross;和void initCross();

void Mainpage::initCross(){
    int id = 0;
    Cross cross1(id++);
    SignalLamp *sl1 =new SignalLamp;
    SignalLamp *sl2 =new SignalLamp;
    cross1.list_sl.append(sl1);
    cross1.list_sl.append(sl2);//信号灯和路口联合起来
  //  cross1.
}

之前这里有少写东西,对照补上

该部分总代码

common.h

#ifndef COMMON_H
#define COMMON_H
#include<QPoint>
#include <qcolor.h>
#include <qmap.h>
#include <qrect.h>

// 道路的构造函数
struct Road{
public:
    // 构造函数,接收三个参数:id、起点和终点
    // 使用初始化列表初始化成员变量
    Road(const int &id,const QPoint &start,const QPoint &end):
        id(id),
        start(start),
        end(end)
    {
        // 这里可以添加更多的初始化逻辑,如果需要的话
    }
    // 道路的标识符
    int id;
    // 道路的起点
    QPoint start;
    // 道路的终点
    QPoint end;
};

// 红绿灯
struct SignalLamp{
public:
    // 倒计时
    int count;
    // int r_duration;给一个总的持续时间,可以根据需要添加这个成员变量
    // 信号灯的颜色
    QColor color;
};

// 路口
struct Cross{
public:
    // 构造函数,接收一个 id 作为参数,使用初始化列表初始化成员变量
    Cross(const int &id):id(id){}
    // 北方向的出口和入口道路指针
    Road *N_exit,*N_entrance,
    // 南方向的出口和入口道路指针
         *S_exit,*S_entrance,
    // 东方向的出口和入口道路指针
         *E_exit,*E_entrance,
    // 西方向的出口和入口道路指针
         *W_exit,*W_entrance;
    // 路口的标识符
    int id;
    // 路口的矩形区域,可用于表示路口的位置和范围
    QRect local;
    // 保存该路口的信号灯列表,存储 SignalLamp 指针
    QList<SignalLamp *>list_sl;
    // 存储道路和信号灯的映射关系,方便根据道路找到对应的信号灯
    QMap<Road *,SignalLamp *>road_sl;
};
#endif // COMMON_H

 mainpage.h

#ifndef MAINPAGE_H
#define MAINPAGE_H

#include "common.h"
#include <QWidget>

// Qt 的命名空间宏,开始
QT_BEGIN_NAMESPACE
namespace Ui { class Mainpage; }
// Qt 的命名空间宏,结束
QT_END_NAMESPACE

// 定义 Mainpage 类,继承自 QWidget
class Mainpage : public QWidget
{
    Q_OBJECT
public:
    // 构造函数,可传入父部件指针,默认为 nullptr
    Mainpage(QWidget *parent = nullptr);
    // 析构函数
    ~Mainpage();

protected:
    // 事件过滤器,用于处理来自 QObject 的事件,特别是重写 stackWidget 中的绘图事件
    bool eventFilter(QObject *obj,QEvent *event);

private slots:
    // 自定义的槽函数,通常用于处理按钮点击等信号,这里可能是退出按钮点击的槽函数
    void on_psbt_exit_clicked();

private:
    // 初始化道路信息的私有成员函数
    void initRoad();
    // 初始化路口信息的私有成员函数
    void initCross();
    // Qt 的 UI 类指针,用于访问 UI 界面元素
    Ui::Mainpage *ui;
    // 存储道路信息的容器,存储 Road 结构体对象
    QList<Road> list_road;
    // 存储路口信息的容器,存储 Cross 结构体对象
    QList<Cross> list_cross;
};
#endif // MAINPAGE_H

mainpage.cpp

#include "mainpage.h"
#include "ui_mainpage.h"
#include <QPainter>

// Mainpage 类的构造函数
Mainpage::Mainpage(QWidget *parent)
    : QWidget(parent)
   , ui(new Ui::Mainpage)
{
    // 调用 setupUi 函数初始化 UI 界面
    ui->setupUi(this);
    // 设置窗口的标题为 "智慧交通系统"
    this->setWindowTitle(QStringLiteral("智慧交通系统"));
    // 从资源中加载图标
    QIcon icon(":/icon/Image/mao.png");
    // 设置窗口的图标
    this->setWindowIcon(icon);
    // 为 ui->page_map 部件安装事件过滤器,事件过滤器为当前 Mainpage 对象
    ui->page_map->installEventFilter(this);
    // 调用 initRoad 函数初始化道路信息
    initRoad();
}

// Mainpage 类的析构函数
Mainpage::~Mainpage()
{
    // 释放 ui 相关资源
    delete ui;
}

// 事件过滤器函数,用于处理事件
bool Mainpage::eventFilter(QObject *obj, QEvent *event)
{
    // 检查事件源对象是否为 ui->page_map
    if (obj == ui->page_map) {
        // 检查事件是否为绘制事件(QEvent::Paint)
        if (event->type() == QEvent::Paint) {
            // 创建一个 QPainter 对象,这里存在问题,未指定绘图设备
            QPainter painter;
            // 从资源路径加载图像
            QImage img(":/icon/Image/RoadMap.png");
            // 开始在 img 上进行绘制操作,这里存在问题,应在 ui->page_map 上绘制
            painter.begin(&img);
            // 创建 QPen 对象,用于绘制道路
            QPen pen;
            // 设置画笔颜色为绿色,可使用 Qt::green 常量
            pen.setColor(Qt::green);
            // 设置画笔宽度为 3
            pen.setWidth(3);
            // 将画笔设置给 painter
            painter.setPen(pen);
            // 遍历 list_road 列表,绘制道路
            for(auto item : list_road) {
                painter.drawLine(item.start, item.end);
            }
            // 结束在 img 上的绘制操作
            painter.end();
            // 开始在 ui->page_map 上进行绘制操作,这里存在问题,绘制操作混乱
            painter.begin(ui->page_map);
            // 将图像绘制在 ui->page_map 的矩形区域内
            painter.drawImage(ui->page_map->rect(), img, img.rect());
            // 结束在 ui->page_map 上的绘制操作
            painter.end();
            // 表示此绘制事件已被处理,不会再传递给其他对象处理
            return true;
        } else {
            // 对于其他事件类型,不进行处理,返回 false
            return false;
        }
    } else {
        // 将事件传递给父类的事件过滤器进行处理
        return QWidget::eventFilter(obj, event);
    }
}

// 处理退出按钮点击的槽函数,用于关闭窗口
void Mainpage::on_psbt_exit_clicked()
{
    this->close();
}

// 初始化道路信息的函数
void Mainpage::initRoad()
{
    int id=0;

            Road road1(id++,QPoint(85,34),QPoint(756,34));
            list_road.append(road1);
            Road road2(id++,QPoint(756,65),QPoint(85,65));
            list_road.append(road2);

            Road road3(id++,QPoint(31,86),QPoint(31,332));
            list_road.append(road3);
            Road road4(id++,QPoint(62,332),QPoint(62,86));
            list_road.append(road4);

            Road road5(id++,QPoint(778,86),QPoint(778,352));
            list_road.append(road5);
            Road road6(id++,QPoint(810,332),QPoint(810,86));
            list_road.append(road6);

            Road road7(id++,QPoint(756,349),QPoint(85,349));
            list_road.append(road7);
            Road road8(id++,QPoint(85,380),QPoint(756,380));
            list_road.append(road8);

            Road road9(id++,QPoint(31,404),QPoint(31,655));
            list_road.append(road9);
            Road road10(id++,QPoint(62,655),QPoint(62,404));
            list_road.append(road10);

            Road road11(id++,QPoint(778,404),QPoint(778,655));
            list_road.append(road11);
            Road road12(id++,QPoint(810,655),QPoint(810,404));
            list_road.append(road12);

            Road road13(id++,QPoint(756,675),QPoint(85,675));
            list_road.append(road13);
            Road road14(id++,QPoint(85,706),QPoint(756,706));
            list_road.append(road14);
}
// 初始化路口信息的函数
void Mainpage::initCross()
{
    int id = 0;
    // 创建 Cross 对象 cross1
    Cross cross1(id++);
    // 创建两个 SignalLamp 对象,并分配内存
    SignalLamp *sl1 = new SignalLamp;
    SignalLamp *sl2 = new SignalLamp;
    // 将 SignalLamp 对象添加到 cross1 的 list_sl 列表中
    cross1.list_sl.append(sl1);
    cross1.list_sl.append(sl2);
    // 信号灯和路口联合起来
}

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐