QT&3 仿真停车与红绿灯实现

仿真停车与红绿灯实现

描述,在停车场外设计红绿灯十字路口,实现两辆车A和B,A车路线过红绿灯不进停车场,B车过红绿灯且进入停车场,可循环进行
效果图
QT&3 仿真停车与红绿灯实现
红绿灯为四个或者可以成为两对,因为同一条路两边的红绿灯显示效果是一样的,红绿灯的控制函数如下

void MainWindow::wheel1(){
    QImage image6(":/picture/yellow.jpg");
    ui->Yellow_1->setPixmap(QPixmap::fromImage(image6));
    ui->Yellow_4->setPixmap(QPixmap::fromImage(image6));
    ui->Yellow_5->setPixmap(QPixmap::fromImage(image6));
    ui->Yellow->setPixmap(QPixmap::fromImage(image6));
    ui->Yellow_1->hide();
    ui->Yellow->hide();
    ui->Yellow_4->hide();
    ui->Yellow_5->hide();
    QImage image7(":/picture/green.jpg");
    ui->Green_1->setPixmap(QPixmap::fromImage(image7));
    ui->Green->setPixmap(QPixmap::fromImage(image7));
    ui->Green_4->setPixmap(QPixmap::fromImage(image7));
    ui->Green_5->setPixmap(QPixmap::fromImage(image7));
    ui->Green_1->hide();
    ui->Green->hide();
    //ui->Green_4->show();
    //ui->Green_5->show();
    QImage image8(":/picture/red.jpg");
    ui->Red_1->setPixmap(QPixmap::fromImage(image8));
    ui->Red->setPixmap(QPixmap::fromImage(image8));
    ui->Red_4->setPixmap(QPixmap::fromImage(image8));
    ui->Red_5->setPixmap(QPixmap::fromImage(image8));
    ui->Red_4->hide();
    ui->Red_5->hide();
}
void MainWindow::run()
{
   settimer1 = 20;
   settimer2 = -1;
   settimer3 = 3;
   settimer4 = 20;
   settimer5 = -1;
   settimer6 = 3;
   ui->lcdNumber_1->setDigitCount(2);
   ui->lcdNumber_1->setMode(QLCDNumber::Dec);
   ui->lcdNumber_1->setSegmentStyle(QLCDNumber::Filled);
   ui->lcdNumber->setDigitCount(2);
   ui->lcdNumber->setMode(QLCDNumber::Dec);
   ui->lcdNumber->setSegmentStyle(QLCDNumber::Filled);

   ui->lcdNumber_4->setDigitCount(2);
   ui->lcdNumber_4->setMode(QLCDNumber::Dec);
   ui->lcdNumber_4->setSegmentStyle(QLCDNumber::Filled);
   ui->lcdNumber_5->setDigitCount(2);
   ui->lcdNumber_5->setMode(QLCDNumber::Dec);
   ui->lcdNumber_5->setSegmentStyle(QLCDNumber::Filled);

   ui->lcdNumber_1->display(settimer1);
   ui->lcdNumber->display(settimer1);
   ui->lcdNumber_4->display(settimer4);
   ui->lcdNumber_5->display(settimer4);
   timer = new QTimer();
   timer->setInterval(1000);
   timer->start();

   connect(timer,SIGNAL(timeout()),this, SLOT(onTimerOutA()));
   connect(timer,SIGNAL(timeout()),this, SLOT(onTimerOutB()));
   //connect(this,SIGNAL(greenflag),this, SLOT(throughLight()));
   wheel1();

}
void MainWindow::onTimerOutA(){

   cout<<"settimer1="<<settimer1<<endl;
   cout<<"settimer2="<<settimer2<<endl;
   cout<<"settimer3="<<settimer3<<endl;

   if(settimer1==0)
    {
       settimer3--;
       ui->lcdNumber_1->display(settimer3);
       ui->Green_1->hide();
       ui->Yellow_1->show();
       ui->Red_1->hide();

       ui->lcdNumber->display(settimer3);
       ui->Green->hide();
       ui->Yellow->show();
       ui->Red->hide();
       if(settimer3==0)
       {
           ui->Green_1->show();
           //ui->red->hide();
           ui->Yellow_1->hide();
           ui->Green->show();
           //ui->red->hide();
           ui->Yellow->hide();
           settimer2 = 20;
           settimer1=-1;
           settimer3=3;
           ui->lcdNumber_1->display(settimer2);
           ui->lcdNumber->display(settimer2);
           timer->setInterval(1000);
           timer->start();
       }
   }
   else if(settimer1>0)
   {
       settimer1--;
       ui->Red_1->show();
       ui->Yellow_1->hide();
       ui->Green_1->hide();
       ui->lcdNumber_1->display(settimer1);
       ui->Red->show();
       ui->Yellow->hide();
       ui->Green->hide();
       ui->lcdNumber->display(settimer1);

   }
   if(settimer2==0)
   {
       settimer3--;
       ui->lcdNumber_1->display(settimer3);
       ui->Green_1->hide();
       ui->Yellow_1->show();
       ui->Red_1->hide();

       ui->lcdNumber->display(settimer3);
       ui->Green->hide();
       ui->Yellow->show();
       ui->Red->hide();

       if(settimer3==0)
       {
           ui->Red->show();
           //ui->red->hide();
           ui->Yellow->hide();
           ui->Red_1->show();
           //ui->red->hide();
           ui->Yellow_1->hide();


           settimer1 = 20;
           settimer2=-1;
           settimer3=3;
           ui->lcdNumber_1->display(settimer1);
           ui->lcdNumber->display(settimer1);
           timer->setInterval(1000);
           timer->start();
       }
   }
   else if(settimer2>0)
   {
       settimer2--;
       ui->lcdNumber_1->display(settimer2);
       ui->Green_1->show();
       ui->Yellow_1->hide();
       ui->Red_1->hide();

       ui->lcdNumber->display(settimer2);
       ui->Green->show();
       ui->Yellow->hide();
       ui->Red->hide();
       if(car_stateA==STOP)
       {
           car_stateA=RUN;throughLightA();
       }
   }
}
void MainWindow::onTimerOutB()
{
    cout<<"settimer4="<<settimer4<<endl;
    cout<<"settimer5="<<settimer5<<endl;
    cout<<"settimer6="<<settimer6<<endl;

    if(settimer5==0)
    {
        settimer6--;

        ui->lcdNumber_4->display(settimer6);
        ui->Red_4->hide();
        ui->Green_4->hide();
        ui->Yellow_4->show();

        ui->lcdNumber_5->display(settimer6);
        ui->Red_5->hide();
        ui->Green_5->hide();
        ui->Yellow_5->show();

        if(settimer6==0)
        {
            ui->Green_5->show();
            //ui->red->hide();
            ui->Yellow_5->hide();
            ui->Green_4->show();
            //ui->red->hide();
            ui->Yellow_4->hide();

            settimer4 = 20;
            settimer5=-1;
            settimer6=3;
            ui->lcdNumber_4->display(settimer4);
            ui->lcdNumber_5->display(settimer4);
            timer->setInterval(1000);
            timer->start();
        }
    }
    else if(settimer5>0)
    {
        settimer5--;
        ui->lcdNumber_4->display(settimer5);
        ui->Red_4->show();
        ui->Green_4->hide();
        ui->Yellow_4->hide();


        ui->lcdNumber_5->display(settimer5);
        ui->Red_5->show();
        ui->Green_5->hide();
        ui->Yellow_5->hide();

    }
    if(settimer4==0)
     {
        settimer6--;
        ui->lcdNumber_4->display(settimer6);
        ui->Red_4->hide();
        ui->Green_4->hide();
        ui->Yellow_4->show();


        ui->lcdNumber_5->display(settimer6);
        ui->Red_5->hide();
        ui->Green_5->hide();
        ui->Yellow_5->show();
        if(settimer6==0)
        {
            ui->Red_4->show();
            //ui->red->hide();
            ui->Yellow_4->hide();
            ui->Red_5->show();
            //ui->red->hide();
            ui->Yellow_5->hide();
            settimer5 = 20;
            settimer4=-1;
            settimer6=3;
            ui->lcdNumber_4->display(settimer5);
            ui->lcdNumber_5->display(settimer5);
            timer->setInterval(1000);
            timer->start();
        }
    }
    else if(settimer4>0)
    {
        settimer4--;

        ui->Red_4->hide();
        ui->Yellow_4->hide();
        ui->Green_4->show();
        ui->lcdNumber_4->display(settimer4);

        ui->Red_5->hide();
        ui->Yellow_5->hide();
        ui->Green_5->show();
        ui->lcdNumber_5->display(settimer4);
        if(car_stateB==STOP)
        {
            car_stateB=RUN;throughLightB();
        }

    }

}

若出现B车红灯停止后绿灯在继续前进但是红绿灯静止,必然是if的逻辑出了问题
停车场的实现在上一篇博客已经挂出了代码,这里详细解释一下
栅栏开关上,出和入原理相同
首先,是判断何时开启与关闭,方法为获取小车的坐标,当期等于某一相对参考坐标时,触发FencesEnterOn();函数,开启栅栏。而何时关闭的思路和它是一样的,当小车过了栅栏到达某一相对参考坐标时,触发FencesEnterOff();
然后就是栅栏如何开启,在ui界面里,假设栅栏是line,那么通过line的height减去某一值来实现将线缩短,模拟栅栏开启,同理加上这一值恢复。这段方法里采用的是栅栏所横跨道路两边的坐标相减获取这一distance。这里要注意一下,这个值不能等于定义的栅栏的height,这样整条线就消失了,在运行时,是不会产生栅栏的长短变化的
实现其的代码如下

//红外检测入口栅栏打开
void MainWindow::FencesEnterOn()
{
    int distanceInEnterDoor = ui->Roadentance_2->y()-ui->Roadentance_1->y();

    ui->fencesEnter->setGeometry(ui->fencesEnter->x(),
                            ui->fencesEnter->y(),
                            ui->fencesEnter->width(),
                            ui->fencesEnter->height() - distanceInEnterDoor);
}

//红外检测入口栅栏关闭
void MainWindow::FencesEnterOff()
{
    int distanceInEnterDoor = ui->Roadentance_2->y()-ui->Roadentance_1->y();

    ui->fencesEnter->setGeometry(ui->fencesEnter->x(),
                            ui->fencesEnter->y(),
                            ui->fencesEnter->width(),
                            ui->fencesEnter->height()+distanceInEnterDoor);
}
//检测入口栅栏何时打开
void MainWindow::FencesPowerRu(int car_x,int car_y)
{
    int fences_x = ui->fencesEnter->x();
    int car_h = ui->Car_2->height();

    for(int i=car_x; i-car_h>fences_x+5; --i)
    {
        ui->Car_2->setGeometry(i,car_y,
                             ui->Car_2->width(),
                             ui->Car_2->height());
       sleep(20);
    }
    FencesEnterOn();
}


//红外检测入口栅栏何时关闭
void MainWindow::RedEnterCheckRu(int car_x,int car_y)
{

    if(car_x + ui->Car_2->height() == ui->enterRed->x())
        FencesEnterOff();
}

//红外检测出口栅栏打开
void MainWindow::FencesExitOn()
{
    int distanceInExitDoor = ui->Roadexit_2->y()-ui->Roadexit_1->y();

    ui->fencesExit->setGeometry(ui->fencesExit->x(),
                             ui->fencesExit->y(),
                             ui->fencesExit->width(),
                             ui->fencesExit->height()-distanceInExitDoor);
}
//红外检测出口栅栏关闭
void MainWindow::FencesExitOff()
{
    int distanceInExitDoor = ui->Roadexit_2->y()-ui->Roadexit_1->y();

    ui->fencesExit->setGeometry(ui->fencesExit->x(),
                             ui->fencesExit->y(),
                             ui->fencesExit->width(),
                             ui->fencesExit->height()+distanceInExitDoor);

}
//检测出口栅栏何时打开
void MainWindow::FencesPowerChu(int car_a,int car_b)
{
    int fences_x = ui->fencesExit->x();
    int car_h = ui->Car_2->height();

    for(int i=car_a; i-car_h>fences_x+5; --i)
    {
        ui->Car_2->setGeometry(i,car_b,
                             ui->Car_2->width(),
                             ui->Car_2->height());
       sleep(11);
    }
    FencesExitOn();
}
//红外检测出口栅栏何时关闭
void MainWindow::RedEnterCheckChu(int car_x,int car_y)
{

    if(car_x + ui->Car_2->height() == ui->exitRed->x())
        FencesExitOff();
}

再说出入口显示的实现,由于出入口显示的思路和原理也相同,这里以入口为例。
这部分的实现在原理上有所偷懒,在小车通过扫描点的时候是才给小车加上了信息,而不是小车自带信息然后被扫描出来。核心在于信息的切割与设置扫描点。当坐标到达时进行ShowToXX();将信息展示出来

//设置小车文本信息
QString MainWindow::setCarInfo(QString carName,QString money,QString brand,QString park )
{
    QString info = carName+" "+money+" "+brand+" "+park+" ";
    //ui->Car_1->setText(info);
    return info;
}
//切割小车信息
void MainWindow::splitCarInfor(QString carInfo,vector<string>& v)
{
    string str = carInfo.toStdString();
     while(1)
     {
         int idx = str.find(" ");
         if(idx==-1)
         {
             break;
         }
         string s = str.substr(0,idx);
         v.push_back(s);
         str = str.substr(idx+1,str.length());
     }
}
//获取系统时间
string MainWindow::getSysTime()
{
    QDateTime local(QDateTime::currentDateTime());
    mLocalTime = local.toString().toStdString();
    return mLocalTime;

}
//入口扫描车的信息
void MainWindow::scanCar()
{
    QString carInfo = setCarInfo("A-00000","10RMB","BWM","P3");
    if(ui->Car_2->x() == ui->ScanBtn_1->x())
    {
//        QString carInfo = ui->Car_1->text();

        showToEnter(carInfo);
    }
}
//出口扫描仪扫描获取小车信息
void MainWindow::scanCarExit()
{
    QString carInfo = setCarInfo("A-00000","10RMB","BWM","P3");
    if(ui->Car_2->x()+ui->Car_2->height() == ui->ScanBtn_2->x())
    {
//        QString carInfo = ui->Car_1->text();
        showToExit(carInfo);
    }

}
//入口显示
void MainWindow::showToEnter(QString carInfo)
{

    vector<string> carSpliteInfo;  //小车的信息划分存储
    splitCarInfor(carInfo,carSpliteInfo);
    vector<string> v;
    v.push_back("车牌:");
    v.push_back("停车费:");
    v.push_back("车型:");
    v.push_back("车位:");

    string s ;
    string sub;
    for(int i=0;i<carSpliteInfo.size();++i)
        {
            cout<<carSpliteInfo[i]<<"   ";
            sub = v[i]+carSpliteInfo[i]+'\n';
            s += sub;
        }

//    carSpliteInfo.push_back(mLocalTime);
    s += getSysTime();
    ui->Entrancelabel->setText(s.c_str());

}
//出口显示
void MainWindow::showToExit(QString carInfo)
{

    vector<string> carSpliteInfo;  //小车的信息划分存储
    splitCarInfor(carInfo,carSpliteInfo);
    vector<string> v;
    v.push_back("车牌:");
    v.push_back("停车费:");
    v.push_back("车型:");
    v.push_back("车位:");

    string s ;
    string sub;
    for(int i=0;i<carSpliteInfo.size();++i)
        {
            cout<<carSpliteInfo[i]<<"   ";
            sub = v[i]+carSpliteInfo[i]+'\n';
            s += sub;
        }

    s += getSysTime();
    ui->Exitlabel->setText(s.c_str());

}
//停车时间
void MainWindow::stopCarTime(unsigned int msec)
{
    sleep(msec);
}

补充一点。通过前面可以看出,在小车行进的时候再触发按钮,小车极有可能会“错乱”因此,在控制小车的行动的函数开头加上

ui->CarADriveBtn->setAttribute(Qt::WA_TransparentForMouseEvents, true);
ui->CarBDriveBtn->setAttribute(Qt::WA_TransparentForMouseEvents, true);

进行按钮的“透明化”或者锁定
在行动函数的末尾加上

ui->CarADriveBtn->setAttribute(Qt::WA_TransparentForMouseEvents, false);
ui->CarBDriveBtn->setAttribute(Qt::WA_TransparentForMouseEvents, false);

进行按钮的恢复
最后控制小车行动的函数这里不再赘述,完整程序中可以自行理解。

完整程序

链接:https://pan.baidu.com/s/19HEvFLaj3_S4LY4REnwZ_g
提取码:x4ui