QT开发:基于Qt实现的交通信号灯模拟器:实现一个带有倒计时功能的图形界面应用
介绍
本文将介绍如何使用Qt框架实现一个简单的交通信号灯控制程序。本程序包括一个图形界面,显示红、黄、绿三色信号灯,并通过定时器控制信号灯的切换。同时,我们还将实现一个带有按钮的界面,用于展示信号灯的状态。
1. 安装Qt开发环境
如果你还没有安装Qt开发环境,请前往Qt官网下载并安装最新的Qt版本。安装过程中请确保选择了Qt Creator和相应的Qt版本(如Qt 5或Qt 6)。本文所示例子基于Qt 5.12版本实现。
2. 创建新项目
2.1 打开Qt Creator
启动Qt Creator开发环境。
2.2 创建新项目
- 在Qt Creator主界面,点击
File -> New File or Project
。 - 在弹出的窗口中,选择
Application
->Qt Widgets Application
,然后点击Choose...
按钮。 - 输入项目名称,例如
trafficlightApp
,选择项目保存路径,然后点击Next
。 - 选择合适的Qt版本和编译器配置,然后点击
Next
。 - 确认类名设置,默认情况下,主窗口类名为
MainWindow
。你可以保留默认值或者修改,点击Next
。 - 点击
Finish
,Qt Creator会自动生成一个新的Qt Widgets项目。
3. 设置项目结构
3.1 添加必要文件
在项目创建完成后,你可以看到Qt Creator已经为你生成了基本的项目结构。接下来,我们需要手动添加一些文件。
- 在项目视图中右键点击项目名称(
trafficlightApp
),选择Add New...
。 - 选择
C++ Class
,然后点击Choose...
。 - 输入类名为
TrafficLightWidget
,基类选择QWidget
,然后点击Next
,再点击Finish
。 - 使用相同的方法,再添加一个类
Widget
,基类选择QWidget
。
我们的项目结构如下:
trafficlightApp/
├── images/
│ ├── green.png
│ ├── red.png
│ └── yellow.png
├── trafficlightApp.pro
├── main.cpp
├── trafficlightwidget.cpp
├── trafficlightwidget.h
├── widget.cpp
├── widget.h
└── widget.ui
4. 编写代码
4.1 修改trafficlightApp.pro
文件
编辑项目文件trafficlightApp.pro
,添加资源文件信息,若为windows系统上QT Creator创建的项目trafficlightApp.pro不要修改,会自动配置;在Ubuntu系统上需要手动在文件中添加源文件和头文件
等。
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
trafficlightwidget.cpp \
widget.cpp
HEADERS += \
trafficlightwidget.h \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
images/green.png \
images/red.png \
images/yellow.png
4.2 编写main.cpp
#include "trafficlightwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TrafficLightWidget w;
w.show();
return a.exec();
}
4.3 编写trafficlightwidget.h
#ifndef TRAFFICLIGHTWIDGET_H
#define TRAFFICLIGHTWIDGET_H
#include <QWidget>
#include <QTimer>
class TrafficLightWidget : public QWidget
{
Q_OBJECT
public:
explicit TrafficLightWidget(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
private slots:
void updateLight();
private:
QTimer *timer;
int lightIndex; // 0 for red, 1 for yellow, 2 for green
int redDuration; // Duration for red light in ms
int yellowDuration; // Duration for yellow light in ms
int greenDuration; // Duration for green light in ms
int elapsedTime; // Time elapsed since last change in ms
int remainingTime; // Remaining time for current light in seconds
int getLightDuration(int light) const; // Function to get the duration for the given light
};
#endif // TRAFFICLIGHTWIDGET_H
4.4 编写trafficlightwidget.cpp
#include "trafficlightwidget.h"
#include <QPainter>
TrafficLightWidget::TrafficLightWidget(QWidget *parent)
: QWidget(parent),
lightIndex(0), // Start with red light
redDuration(30000), // Red duration 30 seconds
yellowDuration(3000), // Yellow duration 3 seconds
greenDuration(30000), // Green duration 30 seconds
elapsedTime(0), // Reset elapsed time
remainingTime(redDuration / 1000) // Start with red light's duration
{
setFixedSize(200, 660); // Set the size of the traffic light widget to include countdown
// Set up the timer to tick every second (1000 milliseconds)
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &TrafficLightWidget::updateLight);
timer->start(1000); // Start the timer
}
void TrafficLightWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QColor lightRed(255, 0, 0, 255);
QColor lightYellow(255, 255, 0, 255);
QColor lightGreen(0, 255, 0, 255);
QColor lightOff(50, 50, 50, 255);
// Draw the traffic light frame
painter.setBrush(Qt::black);
painter.drawRect(10, 10, 180, 580);
// Draw the red light
painter.setBrush(lightIndex == 0 ? lightRed : lightOff);
painter.drawEllipse(40, 30, 120, 120);
// Draw the yellow light
painter.setBrush(lightIndex == 1 ? lightYellow : lightOff);
painter.drawEllipse(40, 180, 120, 120);
// Draw the green light
painter.setBrush(lightIndex == 2 ? lightGreen : lightOff);
painter.drawEllipse(40, 330, 120, 120);
// Draw the countdown timer
painter.setPen(Qt::white);
QFont font = painter.font();
font.setPointSize(24);
painter.setFont(font);
QString remainingTimeString = QString::number(remainingTime);
painter.drawText(QRect(40, 530, 120, 50), Qt::AlignCenter, remainingTimeString);
}
void TrafficLightWidget::updateLight()
{
// Update remaining time for the current light
remainingTime = (getLightDuration(lightIndex) - elapsedTime) / 1000;
elapsedTime += 1000; // Add 1 second to elapsed time
// Check if the current light duration has passed
if (elapsedTime >= getLightDuration(lightIndex)) {
lightIndex = (lightIndex + 1) % 3; // Cycle through the lights
elapsedTime = 0; // Reset elapsed time
remainingTime = getLightDuration(lightIndex) / 1000; // Reset remaining time
}
update(); // Request a repaint
}
int TrafficLightWidget::getLightDuration(int light) const
{
switch (light) {
case 0: return redDuration; // Red light duration
case 1: return yellowDuration; // Yellow light duration
case 2: return greenDuration; // Green light duration
default: return 0; // Default case (should not be reached)
}
}
4.5 编写widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_toolButton_clicked();
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
4.6 编写widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QGraphicsEffect>
#include<QMessageBox>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// Set up button styles
ui->pushButton->setStyleSheet("border-radius: 50%; background-color: #ff0000;");
ui->pushButton_2->setStyleSheet("border-radius: 50%; background-color: rgb(85, 255, 0);");
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_toolButton_clicked()
{
// Placeholder for tool button click event
}
void Widget::on_pushButton_clicked()
{
QMessageBox::information(this,"提示:","红灯,请等待!");
}
void Widget::on_pushButton_2_clicked()
{
QMessageBox::information(this,"提示:","绿灯,请通行!");
}
4.7 编辑widget.ui
在Qt Designer中打开widget.ui
文件:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>红绿灯模拟程序</string>
</property>
<widget class="QCheckBox" name="checkBox">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>81</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>CheckBox</string>
</property>
</widget>
<widget class="QToolButton" name="toolButton">
<property name="geometry">
<rect>
<x>710</x>
<y>0</y>
<width>71</width>
<height>31</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">border-color: rgb(0, 255, 255);
border-left-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 0, 0, 0), stop:0.52 rgba(0, 0, 0, 0), stop:0.565 rgba(82, 121, 76, 33), stop:0.65 rgba(159, 235, 148, 64), stop:0.721925 rgba(255, 238, 150, 129), stop:0.77 rgba(255, 128, 128, 204), stop:0.89 rgba(191, 128, 255, 64), stop:1 rgba(0, 0, 0, 0));</string>
</property>
<property name="text">
<string>Click Me</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>30</x>
<y>100</y>
<width>100</width>
<height>100</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background-color:white;
border-radius:5px;
border:1px solid black;
color:#587fba;</string>
</property>
<property name="text">
<string>MyButton</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>330</x>
<y>100</y>
<width>100</width>
<height>100</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background-color:rgb(85, 255, 0);
border-radius:5px;
border:1px solid black;
color:#587fba;</string>
</property>
<property name="text">
<string>MyButton</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
配置这些控件的属性,如位置、文本内容和样式表等,可以参考前面提供的widget.ui
文件内容。
5. 构建和运行项目
点击Qt Creator中的Build
按钮来构建项目。如果项目配置正确且代码无误,构建过程应能成功完成。
点击Run
按钮,运行程序。你将看到一个包含交通信号灯和两个按钮的窗口。红色、黄色、绿色信号灯会根据设定的时长自动切换。
运行结果展示:
通过上述详细步骤,你已经完成了一个基于Qt的简单交通信号灯控制程序的实现。希望这些说明对你有所帮助。