接上篇

​​​​​​基于QT的智慧交通管理系统(Day1)

基于QT的智慧交通管理系统(Day2)

基于QT的智慧交通管理系统(Day3)

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

第一次写博客,请多担待

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

目录

给VirtualCar添加图片

 让小车动起来

 小车转弯

小车的随机转向

功能按钮

综合信息

定位信息 

车辆控制


给VirtualCar添加图片

在 QWidget 的 paintEvent 中绘制图片到界面上
在 Qt 中,paintEvent 是 QWidget 及其子类的一个受保护的虚函数,用于绘制窗口部件的内容。当需要重新绘制部件时,Qt 会自动调用 paintEvent 函数。 

 然后添加图片资源

VirtualCar->右击,add new,然后像之前一样添加图片,CTRL+S保存

 打开virtualcar.h添加

protected:
    void paintEvent(QPaintEvent *e)override;

然后Alt+enter在相应位置写上

QPainter painter;
    QImage img(":/pic/lyt.jpg");
    painter.begin(this);
    painter.drawImage(this->rect(),img,img.rect());
    painter.end();

*记得添加上#include<QPainter> 

​ 

 打开VirtualCar.ui,拖俩label标签上去,还有Horizontal Spacer和Vertical Spacer。

label里添加文字road:id和duration

选中俩label标签和Horizontal Spacer,设置水平布局

然后点击QWidget,设置垂直布局

然后点击右下角的锤子构建一下

 打开virtualcar.cpp,拉到最下面写上

    ui->label->setText("road_id:"+QString::number(road_id));
    ui->label_2->setText("duration"+QString::number(duration*100.0f)+"%");

运行(文本不太清楚,可以自己设置一下样式,醒目一些)

我是这样式的:

QLabel{
 
font-size: 24px; 
font-family: ;
	font: "仿宋";
 color: white;
}

 让小车动起来

  •  要实现小车的自动移动,需要在 VirtualCar 类中添加一个定时器(QTimer)来定期更新小车的位置,并在 Mainpage 类中处理这些更新。
  • 在 VirtualCar 类中添加一个 QTimer,并在构造函数中启动它。
  • 在 VirtualCar 类中添加一个 updatePosition 方法,用于更新小车的位置。
  • 在 Mainpage 类的 eventFilter 方法中处理小车的位置更新,并重新绘制界面。 

打开virtualcar.cpp

在VirtualCar构造函数,创建一个QTimer对象

QTimer *timer=new QTimer(this);
    timer->setInterval(250);
    connect(timer,&QTimer::timeout,this,&VirtualCar::slot_move);
    timer->start();//启动定时器

打开virtualcar.h,添加slot_move(); 之后Alt+enter添加实现,运行SmartTraffic和VirtualCar,小车就能动起来了,

 

void VirtualCar::slot_move()
{
    // 模拟小车的移动,这里只是简单地增加 duration
    duration += 0.01f;
    if (duration > 1.0f) {
        duration = 1.0f;
    }

    // 发送更新后的状态
    sendState();
}

 小车转弯

打开virtualcar.h,创建路线类和节点类

truct Line{
    Line(const int &id):id(id){}
    int id;
    int start,end;
};
struct Node{
    Node(const int &id):id(id){}
    int id;
    QList<int>out_roads_id;
    QList<int>in_roads_id;
};

到virtualcar.h的最下面写上容器

在上面写一个函数 ,Alt+enter添加定义

在对应位置 写上这些,好让小车之后寻路

void VirtualCar::init()
{
    int node_id=0;
    Node node0(node_id++);
    Node node1(node_id++);
    Node node2(node_id++);
    Node node3(node_id++);
    Node node4(node_id++);
    Node node5(node_id++);

    int line_id=0;
    Line line0(line_id++);
    Line line1(line_id++);
    Line line2(line_id++);
    Line line3(line_id++);
    Line line4(line_id++);
    Line line5(line_id++);
    Line line6(line_id++);
    Line line7(line_id++);
    Line line8(line_id++);
    Line line9(line_id++);
    Line line10(line_id++);
    Line line11(line_id++);
    Line line12(line_id++);
    Line line13(line_id++);

    line0.end=0;line0.start=1;
    line1.end=1;line1.start=0;
    line2.end=2;line2.start=0;
    line3.end=0;line3.start=2;
    line4.end=3;line4.start=1;
    line5.end=1;line5.start=3;
    line6.end=2;line6.start=3;
    line7.end=3;line7.start=2;
    line8.end=4;line8.start=2;
    line9.end=2;line9.start=4;
    line10.end=5;line10.start=3;
    line11.end=3;line11.start=5;
    line12.end=4;line12.start=5;
    line13.end=5;line13.start=4;
 
    //0号入口
    node0.in_roads_id.append(-1);node0.in_roads_id.append(0);
    node0.in_roads_id.append(3);node0.in_roads_id.append(-1);
    node0.out_roads_id.append(-1);node0.out_roads_id.append(1);
    node0.out_roads_id.append(2);node0.out_roads_id.append(-1);
    //1号入口
    node1.in_roads_id.append(-1);node1.in_roads_id.append(-1);
    node1.in_roads_id.append(5);node1.in_roads_id.append(1);
    node1.out_roads_id.append(-1);node1.out_roads_id.append(-1);
    node1.out_roads_id.append(4);node1.out_roads_id.append(0);
    //2号入口
    node2.in_roads_id.append(2);node2.in_roads_id.append(6);
    node2.in_roads_id.append(9);node2.in_roads_id.append(-1);
    node2.out_roads_id.append(3);node2.out_roads_id.append(7);
    node2.out_roads_id.append(8);node2.out_roads_id.append(-1);
    //3号入口
    node3.in_roads_id.append(4);node3.in_roads_id.append(-1);
    node3.in_roads_id.append(11);node3.in_roads_id.append(7);
    node3.out_roads_id.append(5);node3.out_roads_id.append(-1);
    node3.out_roads_id.append(10);node3.out_roads_id.append(6);
    //4号入口
    node4.in_roads_id.append(8);node4.in_roads_id.append(12);
    node4.in_roads_id.append(-1);node4.in_roads_id.append(-1);
    node4.out_roads_id.append(9);node4.out_roads_id.append(13);
    node4.out_roads_id.append(-1);node4.out_roads_id.append(-1);
    //5号入口
    node5.in_roads_id.append(10);node5.in_roads_id.append(-1);
    node5.in_roads_id.append(-1);node5.in_roads_id.append(13);
    node5.out_roads_id.append(11);node5.out_roads_id.append(-1);
    node5.out_roads_id.append(-1);node5.out_roads_id.append(12);


    list_line.append(line0);
    list_line.append(line1);
    list_line.append(line2);
    list_line.append(line3);
    list_line.append(line4);
    list_line.append(line5);
    list_line.append(line6);
    list_line.append(line7);
    list_line.append(line8);
    list_line.append(line9);
    list_line.append(line10);
    list_line.append(line11);
    list_line.append(line12);
    list_line.append(line13);
    
    list_node.append(node0);
    list_node.append(node1);
    list_node.append(node2);
    list_node.append(node3);
    list_node.append(node4);
    list_node.append(node5);

}

往上翻回到void VirtualCar::slot_move(),修改成这样

void VirtualCar::slot_move()
{
    duration += 0.05f;
    if(duration > 1.0f){
       // duration = 1.0f;
        int i;
        int node = list_line[road_id].end;
        for(i = 0;i <4; i++){
            int line = list_node[node].in_roads_id[i];
            if(line >= 0 && list_line[line].id == road_id){
                break;
            }

        }
        if(i >= 4){
            duration = 1.0f;
        } else {
            i = (i+2)%4;
            int road = list_node[node].out_roads_id[i];
            if(road >= 0) road_id = road;
            duration= 0.0f;

}

    }
    sendState();

}

然后调用init();

 好滴,恭喜你的小车会过马路了

小车的随机转向

要实现让每一个小车都可以独自在图上随机转向(直行,转向,掉头),并且考虑转向有没有路,我们需要对 VirtualCar::slot_move 函数进行修改。

判断是否到达路口:
使用 list_line 和 list_node 来确定小车是否到达路口。
如果到达路口,进入转向逻辑。
随机转向决策:
使用 rand() 生成随机数来决定小车的转向行为。
直行、左转、右转、掉头的概率可以根据需要调整。
发送状态更新:
在每次移动后,发送小车的状态更新。

void VirtualCar::slot_move()
{
    duration += 0.05f;
    if(duration > 1.0f)
    {
        int i;
        int node = list_line[road_id].end;
        for(i = 0; i < 4; i++)
        {
            int line = list_node[node].in_roads_id[i];
            if(line >= 0 && list_line[line].id == road_id)
            {
                break;
            }
        }
        if(i >= 4)
        {
            duration = 1.0f;
        }
        else
        {
            i = (i + 4) % 4;
            // 直行 +2,左转 +1,右转 -1,掉头什么都不做
            // 让小车随机转向
            // 考虑转向有没有路
            int road;
            if (i == 0) // 直行
            {
                road = list_node[node].out_roads_id[(i + 2) % 4];
            }
            else if (i == 1) // 左转
            {
                road = list_node[node].out_roads_id[(i + 1) % 4];
            }
            else if (i == 2) // 右转
            {
                road = list_node[node].out_roads_id[(i - 1) % 4];
            }
            else // 掉头
            {
                road = list_node[node].out_roads_id[i];
            }
            if(road >= 0)
            {
                road_id = road;
            }
            else // 如果road=-1,说明直线行驶没有路,进行掉头
            {
                road_id = list_node[node].out_roads_id[i];
            }
            duration = 0.0f;
        }
    }
    sendState();
}

功能按钮

综合信息,全部显示

定位信息,隐藏道路

道路信息,隐藏红绿灯和道路

路口信息:显示红绿灯

打开mainpage.h添加几个参数
打开mainpage.cpp,找到event Filter函数,修改成

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);

                 //画道路

                 painter.save();
                 if(showRoad){
                 QPen pen;
                // pen.setColor(QColor(0,255,0));
                 pen.setColor(Qt::green);
                 pen.setWidth(3);
                 painter.setPen(pen);
                 for(auto item:list_road){
                     painter.drawLine(item.start,item.end);
                 }
                 painter.restore();
}

                 //画路口
                 if(showCross){

                 for(auto item:list_cross){
                     painter.drawRect(item.local);
                     //画红绿灯
                     for(auto key:item.road_sl.keys()){
                         painter.save();
                         SignalLamp *sl = item.road_sl.value(key);

                         painter.setBrush(QBrush(QColor(sl->color)));//给灯填充颜色
                         painter.drawEllipse(key->end,8,8);

                         painter.drawText(key->end-QPoint(5,5),QString::number(sl->count));

                         painter.restore();
                        // painter.drawEllipse(key->end,5,5);
                     }
                 }
}

                 //画小车
                 if(showCar){
                         QImage carImage(":/icon/Image/car.png");
                         for(auto item:list_car){
                             if(item.road==nullptr)continue;//判断道路是不是空指针
                             QPoint pos=item.road->start-(item.road->start-item.road->end)*item.duration;
                             painter.drawImage(QRect(pos-QPoint(15,15),QSize(30,30)),
                                               carImage,carImage.rect());
                         }
}
                 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);
         }
}

综合信息

 打开mainpage.ui找到“综合信息”右击转到槽

 添加槽函数

ui->stackedWidget->setCurrentWidget(ui->page_map);
    showCar=showRoad=showCross=true;
    ui->page_map->update();

定位信息 

 打开mainpage.ui找到“定位信息”右击转到槽,添加槽函数

ui->stackedWidget->setCurrentWidget(ui->page_map);
    showRoad=showCross=false;
    showCar=true;
    ui->page_map->update();

车辆控制

打开mianpage.ui,将page_2修改为page_car

点击车辆控制按钮转到槽,添加槽函数

ui->stackedWidget->setCurrentWidget(ui->page_car);

回到mainpage.ui,点击page_car,添加一些组件并布局(自由布置)

组件包括 label、combobox、pushbutton

将combobox重新命名,我命名成了cmx_carId(修改完成以后记得重新编译一下)

然后打开mainpage.cpp 找到slot_addCar添加

    ui->cmx_carId->addItem(QString::number(id));

 运行

 点击熄火按钮右键转到槽(图示是错的,在旁边)

对应槽函数 

    //车辆熄火
    int carId=ui->cmx_carId->currentText().toInt();
    ns.sendStopToCar(carId);

打开netserver.h,声明sendStopToCar

然后Alt+enter添加定义 ,再回到头文件(按F4)写一个容器

再回到槽函数

    QJsonObject obj;
    obj.insert("code",10003);//发送小车停止信息
    obj.insert("id",carId);
    for(auto item:list_socket){
        item->write(QJsonDocument(obj).toJson());//所有小车都会收到这条消息

 这就是今天的内容

Logo

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

更多推荐