QT-模拟电梯上下楼
- 一、演示效果
- 二、核心程序
- 三、下载链接
一、演示效果
二、核心程序
#include "ElevatorController.h"
#include <QGridLayout>
#include <QLabel>
#include <QGroupBox>
#include <QGridLayout>
#include <QPushButton>
#include <QDebug>
#include <QChar>
#include <QGuiApplication>
#include <QScreen>
#include <queue>ElevatorController::ElevatorController(Ui::MainWindow* u, int numElevators, int numFloors)
{// create/populate ui ComboBox elementsui = u;QStringList evs;for (int elevator = 1; elevator <= numElevators; ++elevator){evs << QString("Elevator: %1").arg(elevator);}ui->comboElevatorBox->addItems(evs);connect(ui->comboElevatorBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &ElevatorController::elevatorSelected);evs.clear();for (int floorc = 1; floorc <= numFloors; ++floorc){evs << QString("Floor: %1").arg(floorc);}ui->comboFloorBox->addItems(evs);// buttons connectedconnect(ui->pushElevatorButton, &QPushButton::clicked, this, &ElevatorController::buttonElevatorSubmit);connect(ui->pushHelpButton, &QPushButton::clicked, this, &ElevatorController::buttonElevatorHelp);connect(ui->pushPlaceButton, &QPushButton::clicked, this, &ElevatorController::buttonPlaceOnFloor);connect(ui->pushMoveButton, &QPushButton::clicked, this, &ElevatorController::buttonMoveToElevator);connect(ui->pushAdd10FloorButton, &QPushButton::clicked, this, &ElevatorController::add10ToEachFloor);connect(ui->pushBuildingEmergencyButton, &QPushButton::clicked, this, &ElevatorController::triggerBuildingEmergency);connect(ui->pushEmergencyResetAllButton, &QPushButton::clicked, this, &ElevatorController::resetAllElevatorsEmergency);connect(ui->pushLeaveButton, &QPushButton::clicked, this, &ElevatorController::buttonLeaveElevator);// spin box buttons:connect(ui->spinBoxMove, qOverload<int>(&QSpinBox::valueChanged), this, &ElevatorController::moveComboBoxChange);connect(ui->spinBoxLeaveElevator, qOverload<int>(&QSpinBox::valueChanged), this, &ElevatorController::moveLeaveElevatorBoxChange);// combo box change:connect(ui->comboFloorBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &ElevatorController::floorSelected);// keep in mind: "setWidget" and "setLayout" etc add to the ui tree, memory managed by Qt not Me :-)// widget to hold the grid layoutQWidget* elevatorWidget = new QWidget();ui->elevatorScrollArea->setWidget(elevatorWidget); // Set the content widget of the ElevatorController// QGridLayout* elevatorGridLayoutelevatorGridLayout = new QGridLayout(elevatorWidget);elevatorWidget->setLayout(elevatorGridLayout);// Add buttons or labels to the grid layout based on dimensionsfor (int floor = numFloors - 1; floor >= 0; floor--){for (int elevator = 1; elevator <= numElevators; ++elevator){// Create a QLabel for each positionQLabel* cube = new QLabel;cube->setText(" ");cube->setFixedSize(CUBE_SIZE, CUBE_SIZE);QString color = "gray";if(numFloors - floor - 1 == 0) // all ev's start at 0color = "red";cube->setStyleSheet(QString("background-color: %1").arg(color));// Add the widget to the grid layout at the specified positionelevatorGridLayout->addWidget(cube, floor, elevator);}Floor* flr = new Floor(floor + 1); // floor class is a part of the UI// Connect the signals from the Floor to the slots in the ElevatorControllerconnect(flr, &Floor::upButtonPressed, this, &ElevatorController::buttonPressedUp);connect(flr, &Floor::downButtonPressed, this, &ElevatorController::buttonPressedDown);// adds the floor at the start (far left)elevatorGridLayout->addWidget(flr, numFloors - floor - 1, 0);floors.push_back(flr);}// create elevatorsfor (int elevator = 1; elevator <= numElevators; ++elevator){Elevator* ev = new Elevator(elevator);elevators.push_back(ev);updateDisplays();// should be connecting slot in elevator to signals in elevator controllerconnect(this, &ElevatorController::resetEmergency, ev, &Elevator::resetEmergencyInElevator);connect(this, &ElevatorController::sendRequestToElevator, ev, &Elevator::pressButton);connect(this, &ElevatorController::helpButton, ev, &Elevator::helpButtonPressed);connect(this, &ElevatorController::moveElevatorToFloor, ev, &Elevator::moveTofloor);connect(this, &ElevatorController::removeElevatorPassengers, ev, &Elevator::removePassengers);connect(this, &ElevatorController::addElevatorPassengers, ev, &Elevator::addPassengers);connect(this, &ElevatorController::buildingEmergency, ev, &Elevator::emergency);connect(this, &ElevatorController::pressButton, ev, &Elevator::pressButton);connect(this, &ElevatorController::unpressButton, ev, &Elevator::unpressButton);connect(ev, &Elevator::floorChanged, this, &ElevatorController::elevatorFloorChanged);connect(ev, &Elevator::doorOpened, this, &ElevatorController::doorOpened);connect(ev, &Elevator::doorClosed, this, &ElevatorController::doorClosed);connect(ev, &Elevator::doorBlocked, this, &ElevatorController::doorBlocked);connect(ev, &Elevator::overloaded, this, &ElevatorController::overloaded);connect(ev, &Elevator::emergencyOnBoard, this, &ElevatorController::emergency);connect(ev, &Elevator::updateDisplays, this, &ElevatorController::updateDisplays);QThread* evThread = new QThread;ev->moveToThread(evThread);evThread->start();threads.push_back(evThread);}requestScanTimer = new QTimer(this);connect(requestScanTimer, &QTimer::timeout, this, &ElevatorController::scanRequestTree);requestScanTimer->start(SCAN_REQUEST_TREE_SECS); // Scan backup request tree every 15 seconds, in case overflowqDebug() << "Elevator Controller Initialized";
}ElevatorController::~ElevatorController() // clean up floors
{for(int i = 0; i < floors.size(); i++)delete floors[i];requestScanTimer->stop();delete requestScanTimer;for(int i = 0; i < threads.size(); i++){threads[i]->quit();threads[i]->wait();delete threads[i];}
}// --- UI INPUT & CALLBACK FUNCS ---void ElevatorController::handleScreenResized(int w, int h)
{int bufferGap = 10;ui->elevatorScrollArea->resize(w - ui->InputTerminal->width() - 3*bufferGap, h - bufferGap*6);qDebug() << "Reinit scale -- uiWidth: " << w << " uiHeight: " << h;ui->InputTerminal->move(ui->elevatorScrollArea->x() + w - ui->InputTerminal->width() - 2*bufferGap, ui->InputTerminal->y());ui->InputTerminal->resize(ui->InputTerminal->width(), h - bufferGap*5);
}void ElevatorController::updateDisplays()
{int ev = ui->comboElevatorBox->currentText().remove(0, 10).toInt(); // stored from 0QString buttonList = "";const std::set<int>& blist = elevators[ev - 1]->getButtonsPressed();for(const int& a : blist){buttonList += QString::number(a) + " ";}ui->textBrowserButtonsPressed->setPlainText(buttonList);const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt();ui->passengerOnFloorNumber->display(floors[flr - 1]->peopleOnFloor());ui->passengerNumber->display(elevators[ev - 1]->numPassengers());
}void ElevatorController::buttonElevatorSubmit()
{// get the int values from the combo boxesint ev = ui->comboElevatorBox->currentText().remove(0, 10).toInt();int fb = ui->comboFloorBox->currentText().remove(0, 7).toInt();qDebug() << "BUTTON - elevator submit pressed elev: " << ev << " floor button: " << fb;if(elevators[ev - 1]->getButtonsPressed().count(fb) > 0)emit unpressButton(ev, fb);elseemit pressButton(ev, fb);
}void ElevatorController::buttonPlaceOnFloor()
{qDebug() << "BUTTON buttonPlaceOnFloor.... spawning ppl on floor";const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt() - 1;floors[flr]->addPeople(ui->spinBoxPlace->value());ui->passengerOnFloorNumber->display(floors[flr]->peopleOnFloor());ui->spinBoxPlace->setValue(0);
}void ElevatorController::buttonMoveToElevator()
{qDebug() << "BUTTON: buttonMoveToElevator.... moving ppl ";const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt();int evweak = ui->comboElevatorBox->currentText().remove(0, 10).toInt() - 1; // if this is on the same floor its usedElevator* availableEv = nullptr;Elevator* weakEv = nullptr;bool potentialEvPassed = false;if(elevators[evweak]->currentFloor() == flr) // soft lock the current elevatorweakEv = elevators[evweak];for(Elevator* ev : elevators) // unless theres one that makes more sense{if(ev->currentFloor() == flr && ev->currentState() == Elevator::DoorsOpen){availableEv = ev;if(weakEv == ev && weakEv != nullptr){availableEv = weakEv;break;}}}if(!availableEv)return;const int val = ui->spinBoxMove->value(); //usr inputui->spinBoxMove->setValue(0);floors[flr - 1]->removePeople(val);// emit addElevatorPassengers(availableEv->getId(), flr, val);elevators[availableEv->getId() - 1]->addPassengers(availableEv->getId(), flr, val);// just set the combo box option to the one that people were put into automatically... for visibilityui->comboElevatorBox->setCurrentIndex(availableEv->getId() - 1);// update the floor on people displayupdateDisplays();
}void ElevatorController::buttonLeaveElevator()
{int ev = ui->comboElevatorBox->currentText().remove(0, 10).toInt();qDebug() << "BUTTON: buttonLeaveElevator.... moving ppl EV: " << ev << " FLR: " << elevators[ev - 1]->currentFloor();const int val = ui->spinBoxLeaveElevator->value(); //usr inputui->spinBoxLeaveElevator->setValue(0);emit removeElevatorPassengers(elevators[ev - 1]->getId(), elevators[ev - 1]->currentFloor(), val);floors[elevators[ev - 1]->currentFloor() - 1]->addPeople(val);// just set the combo box option to the one that people were put into automatically... for visibilityui->comboFloorBox->setCurrentIndex(elevators[ev - 1]->currentFloor() - 1);ui->passengerNumber->display(elevators[ev-1]->numPassengers());updateDisplays();const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt();if(elevators[ev - 1]->currentFloor() != flr)return;// update the floor on people displayui->passengerOnFloorNumber->display(floors[elevators[ev - 1]->currentFloor()]->peopleOnFloor());updateDisplays();controlMoveButtonActivated();
}void ElevatorController::add10ToEachFloor()
{qDebug() << "BUTTON add 10 To Each Floor.... spawning 10 ppl on each floor!";for(Floor* f : floors){f->addPeople(10);}const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt() - 1;ui->passengerOnFloorNumber->display(floors[flr]->peopleOnFloor());ui->spinBoxPlace->setValue(0);
}void ElevatorController::triggerBuildingEmergency()
{emit buildingEmergency(-1);
}void ElevatorController::buttonElevatorHelp()
{int ev = ui->comboElevatorBox->currentText().remove(0, 10).toInt();emit helpButton(ev);updateDisplays();
}void ElevatorController::resetAllElevatorsEmergency()
{emit resetEmergency(-1);updateDisplays();
}void ElevatorController::controlMoveButtonActivated(Elevator* availableEv)
{// we want to check if there is an elevator on the floor in door open state// & set the control button to active or not based on it//qDebug() << "BUTTON ACTIVATE: Activating/Deactivating the Move Button to allow moving ppl ";const int flr = ui->comboFloorBox->currentText().remove(0, 7).toInt();const int evNum = ui->comboElevatorBox->currentText().remove(0, 10).toInt();for(Elevator* ev : elevators){if(availableEv != nullptr)break;if(ev->currentFloor() == flr && ev->currentState() == Elevator::DoorsOpen || elevators[evNum - 1]->currentState() == Elevator::Overload)availableEv = ev;}if(elevators[evNum - 1]->currentState() == Elevator::DoorsOpen || elevators[evNum - 1]->currentState() == Elevator::Overload || elevators[evNum - 1]->currentState() == Elevator::Emergency)ui->pushLeaveButton->setEnabled(true);else if(ui->pushLeaveButton->isEnabled())ui->pushLeaveButton->setEnabled(false);if(availableEv != nullptr && flr == availableEv->currentFloor())ui->pushMoveButton->setEnabled(true);else if(ui->pushMoveButton->isEnabled())ui->pushMoveButton->setEnabled(false);
}void ElevatorController::elevatorSelected(int index)
{ui->passengerNumber->display(elevators[index]->numPassengers());updateDisplays();controlMoveButtonActivated(elevators[index]);qDebug() << "COMBO BOX: Elevator selected. Elevator: " << index;
}void ElevatorController::floorSelected(int index)
{// update the segment display for passangersui->passengerOnFloorNumber->display(floors[index]->peopleOnFloor());qDebug() << "COMBO BOX: Floor selected. Floor: " << index;ui->spinBoxMove->setValue(0); // wipe this since its different # pplcontrolMoveButtonActivated(); // potentially changes move buttons state
}void ElevatorController::moveComboBoxChange(int index)
{if(index > ui->passengerOnFloorNumber->value()){ui->spinBoxMove->setValue(ui->passengerOnFloorNumber->value());}
}void ElevatorController::moveLeaveElevatorBoxChange(int index)
{if(index > ui->passengerNumber->value()){ui->spinBoxLeaveElevator->setValue(ui->passengerNumber->value());}
}// --- UI UPDATE / EV SOCKET FUNCS ---void ElevatorController::elevatorFloorChanged(int floor, int ev, bool up)
{// each elevator emits this when the moved to new floorev -= 1;qDebug() << "EV signal: Elevator floor changed, floor: " << floor << " elevator: " << ev << " up dir: " << up;qDebug() << "(X, Y) : " << floor << ", " << (ev + 1);const int x = floors.size() - floor; // as the floors decrease, x increases (flr increase, x decrease)const int y = ev + 1;QLayoutItem* layoutItem = elevatorGridLayout->itemAtPosition(x, y); // check if we are looking at a valid evif (!layoutItem){qDebug() << "No layout item at this position.";return;}QWidget* widget = layoutItem->widget();if (!widget){qDebug() << "No widget at this position.";return;}const QMetaObject* metaObject = widget->metaObject();QString widgetType = QString::fromUtf8(metaObject->className());if (widgetType == "QLabel"){QLabel* square = qobject_cast<QLabel*>(widget);QLabel* squarePrev;squarePrev = qobject_cast<QLabel*>(elevatorGridLayout->itemAtPosition((x - 1 + floors.size()) % floors.size(), y)->widget());squarePrev->setStyleSheet(QString("background-color: gray;"));squarePrev = qobject_cast<QLabel*>(elevatorGridLayout->itemAtPosition((x + 1)%floors.size(), y)->widget());squarePrev->setStyleSheet(QString("background-color: gray;"));if(elevators[ev]->currentState() == Elevator::Emergency)square->setStyleSheet("background-color: yellow;");elsesquare->setStyleSheet("background-color: red;");}qDebug() << "Widget type: " << widgetType;
}void ElevatorController::doorOpened(int flr, int ev)
{// a door has openedqDebug() << "EV signal: Door opened! Elevator: " << ev;const int x = floors.size() - flr; // as the floors decrease, x increases (flr increase, x decrease)const int y = ev;if (!elevatorGridLayout->itemAtPosition(x, y)){qDebug() << "doorOpened(): No Item at position: (" << x << ", " << y << ")";return;}QWidget* wdg = elevatorGridLayout->itemAtPosition(x, y)->widget();if(QString::fromUtf8(wdg->metaObject()->className()) != "QLabel"){qDebug() << "doorOpened(): Item at position: (" << x << ", " << y << ") " << "is a: " << QString::fromUtf8(wdg->metaObject()->className());return;}QLabel* squarePrev = qobject_cast<QLabel*>(wdg);squarePrev->setStyleSheet(QString("background-color: green;"));controlMoveButtonActivated(elevators[ev - 1]);updateDisplays();
}void ElevatorController::doorClosed(int flr, int ev)
{// a door has closedqDebug() << "EV signal: Door closed!! Elevator: " << ev;const int x = floors.size() - flr; // as the floors decrease, x increases (flr increase, x decrease)const int y = ev;if (!elevatorGridLayout->itemAtPosition(x, y)){qDebug() << "doorClosed(): No Item at position: (" << x << ", " << y << ")";return;}QWidget* wdg = elevatorGridLayout->itemAtPosition(x, y)->widget();if(QString::fromUtf8(wdg->metaObject()->className()) != "QLabel"){qDebug() << "doorClosed(): Item at position: (" << x << ", " << y << ") " << "is a: " << QString::fromUtf8(wdg->metaObject()->className());return;}QLabel* squarePrev = qobject_cast<QLabel*>(wdg);squarePrev->setStyleSheet(QString("background-color: purple;"));
}void ElevatorController::doorBlocked(int flr, int ev)
{// a door has closedqDebug() << "EV signal: Alert! Door blocked... reopening door... Elevator: " << ev;const int x = floors.size() - flr; // as the floors decrease, x increases (flr increase, x decrease)const int y = ev;if (!elevatorGridLayout->itemAtPosition(x, y)){qDebug() << "doorBlocked(): No Item at position: (" << x << ", " << y << ")";return;}QWidget* wdg = elevatorGridLayout->itemAtPosition(x, y)->widget();if(QString::fromUtf8(wdg->metaObject()->className()) != "QLabel"){qDebug() << "doorBlocked(): Item at position: (" << x << ", " << y << ") " << "is a: " << QString::fromUtf8(wdg->metaObject()->className());return;}QLabel* squarePrev = qobject_cast<QLabel*>(wdg);squarePrev->setStyleSheet(QString("background-color: blue;"));
}void ElevatorController::overloaded(int flr, int ev)
{// a door has closedqDebug() << "EV signal: Elevator overloaded!! Elevator: " << ev;const int x = floors.size() - flr; // as the floors decrease, x increases (flr increase, x decrease)const int y = ev;if (!elevatorGridLayout->itemAtPosition(x, y)){qDebug() << "doorClosed(): No Item at position: (" << x << ", " << y << ")";return;}QWidget* wdg = elevatorGridLayout->itemAtPosition(x, y)->widget();if(QString::fromUtf8(wdg->metaObject()->className()) != "QLabel"){qDebug() << "overloaded(): Item at position: (" << x << ", " << y << ") " << "is a: " << QString::fromUtf8(wdg->metaObject()->className());return;}QLabel* squarePrev = qobject_cast<QLabel*>(wdg);squarePrev->setStyleSheet(QString("background-color: orange;"));
}void ElevatorController::emergency(int flr, int ev)
{// a door has closedqDebug() << "EV signal: Elevator emergency!! Elevator: " << ev;if(flr != SAFE_FLOOR)return;QLayoutItem* layoutItem = elevatorGridLayout->itemAtPosition(floors.size() - SAFE_FLOOR, ev); // check if we are looking at a valid evif (!layoutItem){qDebug() << "No layout item at this position.";return;}QWidget* widget = layoutItem->widget();if (!widget){qDebug() << "No widget at this position.";return;}const QMetaObject* metaObject = widget->metaObject();QString widgetType = QString::fromUtf8(metaObject->className());if (widgetType == "QLabel"){QLabel* square = qobject_cast<QLabel*>(widget);if(elevators[ev - 1]->currentState() == Elevator::Idle)square->setStyleSheet(QString("background-color: red;"));elsesquare->setStyleSheet(QString("background-color: yellow;"));} qDebug() << "Widget type: " << widgetType;
}// --- EV REQUEST FUNCS ---void ElevatorController::buttonPressedUp(int floor)
{// an up button on a floor has been pressedqDebug() << "Floor signal: Floor up button pressed: " << floor;handleFlrPressed(FloorDirection(floor, true));
}void ElevatorController::buttonPressedDown(int floor)
{// a down button on a floor has been pressedqDebug() << "Floor signal: Floor down button pressed: " << floor;handleFlrPressed(FloorDirection(floor, false));
}void ElevatorController::handleFlrPressed(FloorDirection fd)
{// maybe this had some use in some implementtation? ev->getNumFloorsReserved();Elevator* bestElevator = nullptr;Elevator* idleEv = nullptr; // lower priofor(Elevator* pEv : elevators){if(fd.up && pEv->lastDirMovingUp() && fd.num >= pEv->currentFloor()){bestElevator = pEv;break;}if(!fd.up && !pEv->lastDirMovingUp() && fd.num <= pEv->currentFloor()){bestElevator = pEv;break;}if(pEv->currentState() == Elevator::Idle)idleEv = pEv;}if(bestElevator)emit moveElevatorToFloor(bestElevator->getId(), fd.num);else if(idleEv)emit moveElevatorToFloor(idleEv->getId(), fd.num);elseearliestRequestTree.push(fd);
}void ElevatorController::scanRequestTree()
{// happen on a timer, scan request tree realloc elevators if freeif(AGGRESSIVE_LOGGING && !earliestRequestTree.empty())qDebug() << "scanRequestTree-> Request floor: " << earliestRequestTree.top().num << " up: " << earliestRequestTree.top().up; // << i++;if (earliestRequestTree.empty()){return;}FloorDirection fd = earliestRequestTree.top();earliestRequestTree.pop();handleFlrPressed(FloorDirection(fd.num, fd.up));
}
xt
三、下载链接
https://download.csdn.net/download/u013083044/88861542