基于QT的智慧交通管理系统(Day4)
接上篇本文用于记录学期期末实训内容,尽可能做到保姆级别的详细步骤,跟着做准能成第一次写博客,请多担待声明:我也只是个学习一般的学生,这是记录课上老师讲的内容,我现在只能说这么做能行,但我还不清楚为什么这样做,还在努力学习中。
接上篇
本文用于记录学期期末实训内容,尽可能做到保姆级别的详细步骤,跟着做准能成
第一次写博客,请多担待
声明:我也只是个学习一般的学生,这是记录课上老师讲的内容,我现在只能说这么做能行,但我还不清楚为什么这样做,还在努力学习中。
目录
给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());//所有小车都会收到这条消息
这就是今天的内容
更多推荐


所有评论(0)