要求:在A9平台上完成基于QT的可视化调速风扇控制软件
注:本文以及代码仅用于学习。
main.cpp
这段代码是一个Qt框架应用程序的入口函数,其作用是启动应用程序并显示一个启动画面,然后创建一个主窗口并显示出来。
#include "ui_QtDemo.h" // 包含Qt Designer生成的ui文件头文件
#include "window.h" // 包含主窗口的头文件
//#include "analogclock.h"
#include <QApplication> // 包含Qt应用程序的头文件
#include <QPixmap> // 包含Qt图片类的头文件
#include <QSplashScreen> // 包含Qt启动画面类的头文件
#include <unistd.h> // 包含Linux下的sleep函数头文件
#include <QMovie> // 包含Qt动态图类的头文件
#include <QLabel> // 包含Qt标签类的头文件
#include <QElapsedTimer> // 包含Qt计时器类的头文件
int main(int argc, char *argv[]) {
QApplication app(argc, argv); // 创建一个Qt应用程序
QPixmap pix("splash2.gif"); // 创建一个图片对象,用于作为启动画面的背景
QSplashScreen splash(pix); // 创建一个启动画面对象,并将图片对象作为背景
QLabel splashlabel(&splash); // 创建一个标签对象,用于显示动态图
QMovie splashgif("splash2.gif"); // 创建一个动态图对象
splashlabel.setMovie(&splashgif); // 将动态图对象设置为标签的动画
splashgif.start(); // 开始播放动态图
splash.show(); // 显示启动画面
splash.setCursor(Qt::BlankCursor); // 不显示鼠标外观
int delayTime = 4; // 启动画面停留的时间
QElapsedTimer timer; // 创建一个计时器对象
timer.start(); // 开始计时
while(timer.elapsed() < (delayTime * 1000)) // 当计时器时间未达到停留时间时,循环等待
{
app.processEvents(); // 处理Qt事件
}
Window win; // 创建主窗口对象
win.show(); // 显示主窗口
splash.finish(&win); // 关闭启动画面
return app.exec(); // 开始Qt事件循环
}
其中,最重要的是创建了一个主窗口并显示出来,同时通过使用QSplashScreen类实现了一个启动画面,为应用程序增加了美观和用户友好性。
analogclock.cpp
这段程序是一个模拟时钟的小部件。它通过使用Qt的绘图功能在窗口中绘制一个模拟时钟,其中包括指向小时和分钟的指针以及时钟刻度。每秒钟刷新一次,以显示当前时间。它还包括一个标题,用于标识这是一个模拟时钟。
#include <QtGui>
#include "analogclock.h"
#include "ui_QtDemo.h"
AnalogClock::AnalogClock(QWidget *parent)
: QWidget(parent) // 构造函数,创建了一个QWidget对象
{
QTimer *timer = new QTimer(this); // 创建一个QTimer对象,定时器间隔为1秒
connect(timer, SIGNAL(timeout()), this, SLOT(update())); // 当定时器超时时,调用update()函数进行更新
timer->start(1000); // 启动定时器
setWindowTitle(tr("Analog Clock")); // 设置窗口标题
resize(200, 200); // 设置窗口大小
}
void AnalogClock::paintEvent(QPaintEvent *) // 重写paintEvent()函数,用于绘制窗口
{
static const QPoint hourHand[3] = { // 时针的三个点坐标
QPoint(7, 8),
QPoint(-7, 8),
QPoint(0, -40)
};
static const QPoint minuteHand[3] = { // 分针的三个点坐标
QPoint(7, 8),
QPoint(-7, 8),
QPoint(0, -70)
};
QColor hourColor(127, 0, 127); // 时针颜色
QColor minuteColor(0, 127, 127, 191); // 分针颜色
int side = qMin(width(), height()); // 取窗口宽度和高度中的较小值,用于计算比例缩放
QTime time = QTime::currentTime(); // 获取当前时间
QPainter painter(this); // 创建QPainter对象,指定绘图设备为当前窗口
painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿
painter.translate(width() / 2, height() / 2); // 将坐标系移到窗口中心
painter.scale(side / 200.0, side / 200.0); // 按比例缩放
painter.setPen(Qt::NoPen); // 不绘制边框
painter.setBrush(hourColor); // 设置时针颜色
painter.save(); // 保存当前状态
painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0))); // 计算时针角度并旋转
painter.drawConvexPolygon(hourHand, 3); // 绘制时针
painter.restore(); // 恢复之前保存的状态
painter.setPen(hourColor); // 设置时针颜色
for (int i = 0; i < 12; ++i) { // 绘制12条小时刻度线
painter.drawLine(88, 0, 96, 0); // 从(88, 0)到(96, 0)绘制线段
painter.rotate(30.0); // 逆时针旋转30度
}
painter.setPen(Qt::NoPen); // 不绘制边框
painter.setBrush(minuteColor); // 设置分针颜色
painter.save(); // 保存当前状态
// 以6度为单位旋转指针,角度为分钟数和秒钟数的和除以60
painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
// 绘制三角形指针
painter.drawConvexPolygon(minuteHand, 3);
// 恢复之前保存的坐标系统状态
painter.restore();
// 设置画笔颜色为分钟指针颜色
painter.setPen(minuteColor);
// 绘制时钟刻度线,共60条
for (int j = 0; j < 60; ++j) {
// 如果当前的刻度线不是小时刻度,则绘制长度较短的线段
if ((j % 5) != 0) painter.drawLine(92, 0, 96, 0);
// 以6度为单位旋转坐标系,绘制下一条刻度线
painter.rotate(6.0);
}
window.cpp
这段代码定义了一个名为Window的类,该类继承自QWidget,包含了三个自定义的槽函数:slot1、slot2和slot3。
构造函数Window::Window(QWidget *parent)用于初始化窗口界面,并且延时1秒钟。其中,ui文件的初始化使用了Qt框架中的UI设计工具生成的ui文件和setupUi函数。
自定义槽函数slot1和slot2分别输出"Calendar"和"AnalogClock"字符串。
自定义槽函数slot3带有一个int类型参数speed,它会将speed除以5的商存入beep_args的第一个元素,并将1000存入beep_args的第二个元素,最后输出on_off、beep_args[0]、beep_args[1]的值。
#include <QDebug> // 引入QDebug头文件,用于输出调试信息
#include "window.h" // 引入自定义的Window头文件
#include "ui_QtDemo.h" // 引入ui文件生成的头文件
#include <unistd.h> // 引入unistd.h头文件,用于sleep函数
Window::Window(QWidget *parent):
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this); // 使用ui文件中生成的setupUi函数进行界面初始化
sleep(1); // 延时1秒钟
}
void Window::slot1(){ // 自定义槽函数slot1
qDebug()<<"Calendar"; // 输出"Calendar"字符串
}
void Window::slot2(){ // 自定义槽函数slot2
qDebug()<<"AnalogClock"; // 输出"AnalogClock"字符串
}
void Window::slot3(int speed){ // 自定义槽函数slot3,带一个int类型参数speed
unsigned int beep_args[2]; // 定义一个长度为2的unsigned int类型数组beep_args
unsigned int on_off = speed>0?1:0; // 根据参数speed的正负来确定on_off的值
beep_args[0] = speed/5; // 将speed除以5的商存入beep_args的第一个元素
beep_args[1] = 1000; // 将1000存入beep_args的第二个元素
qDebug()<<"args"<<on_off<<beep_args[0]<<beep_args[1]; // 输出on_off、beep_args[0]、beep_args[1]的值
}
ui_QtDemo.h
这段代码是使用Qt框架编写的用户界面,主要包括了一些UI元素的创建和布局,并且实现了一些UI元素的事件响应和切换。
注:本段代码使用了Qt框架,QObject::connect()函数用于建立信号和槽之间的连接。QtCore模块提供了信号和槽的机制,它们被广泛地用于Qt应用程序的编写。
#ifndef UI_QTDEMO_H // 防止重复包含
#define UI_QTDEMO_H
#include <QtCore/QVariant> // QVariant 类型
#include <QtGui/QAction> // QAction 类型
#include <QtGui/QApplication> // QApplication 类型
#include <QtGui/QButtonGroup> // QButtonGroup 类型
#include <QtGui/QCalendarWidget> // QCalendarWidget 类型
#include <QtGui/QDial> // QDial 类型
#include <QtGui/QHeaderView> // QHeaderView 类型
#include <QtGui/QLCDNumber> // QLCDNumber 类型
#include <QtGui/QLabel> // QLabel 类型
#include <QtGui/QPushButton> // QPushButton 类型
#include <QtGui/QWidget> // QWidget 类型
#include "analogclock.h" // 头文件
QT_BEGIN_NAMESPACE
class Ui_Form // 声明一个类
{
public:
QPushButton *OffButton; // 指向 QPushButton 类型的指针
QPushButton *OnButton; // 指向 QPushButton 类型的指针
QDial *dial; // 指向 QDial 类型的指针
QLCDNumber *lcdNumber; // 指向 QLCDNumber 类型的指针
QCalendarWidget *calendarWidget; // 指向 QCalendarWidget 类型的指针
QLabel *label; // 指向 QLabel 类型的指针
AnalogClock *analogClock; // 指向 AnalogClock 类型的指针
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty()) // 如果窗体对象名称为空
Form->setObjectName(QString::fromUtf8("Form")); // 将窗体对象名称设置为 "Form"
Form->resize(389, 268); // 设置窗体大小为 (389, 268)
OffButton = new QPushButton(Form); // 创建一个QPushButton对象,并将其父窗口设置为 Form
OffButton->setObjectName(QString::fromUtf8("OffButton")); // 将按钮对象名称设置为 "OffButton"
OffButton->setGeometry(QRect(220, 210, 80, 26)); // 设置按钮的位置和大小
OnButton = new QPushButton(Form); // 创建另一个QPushButton对象,并将其父窗口设置为 Form
OnButton->setObjectName(QString::fromUtf8("OnButton")); // 将按钮对象名称设置为 "OnButton"
OnButton->setGeometry(QRect(80, 210, 80, 26)); // 设置按钮的位置和大小
dial = new QDial(Form); // 创建一个QDial对象,并将其父窗口设置为 Form
dial->setObjectName(QString::fromUtf8("dial")); // 将QDial对象名称设置为 "dial"
dial->setGeometry(QRect(280, 80, 71, 71)); // 设置QDial的位置和大小
lcdNumber = new QLCDNumber(Form); // 创建一个QLCDNumber对象,并将其父窗口设置为 Form
lcdNumber->setObjectName(QString::fromUtf8("lcdNumber")); // 将QLCDNumber对象名称设置为 "lcdNumber"
lcdNumber->setGeometry(QRect(280, 40, 71, 23)); // 设置QLCDNumber的位置和大小
calendarWidget = new QCalendarWidget(Form); // 创建一个QCalendarWidget对象,并将其父窗口设置为 Form
calendarWidget->setObjectName(QString::fromUtf8("calendarWidget")); // 将QCalendarWidget对象名称设置为 "calendarWidget"
calendarWidget->setGeometry(QRect(0, 0, 264, 163)); // 设置QCalendarWidget的位置和大小
label = new QLabel(Form); // 创建一个QLabel对象,并将其父窗口设置为 Form
label->setObjectName(QString::fromUtf8("label")); // 将QLabel对象名称设置为 "label"
label->setGeometry(QRect(280, 10, 81, 16)); // 设置QLabel的位置和大小
analogClock = new AnalogClock(Form); // 创建一个AnalogClock对象,并将其父窗口设置为 Form
analogClock->setObjectName(QString::fromUtf8("analogClock")); // 将AnalogClock对象名称设置为 "analogClock"
analogClock->setGeometry(QRect(60, 10, 141, 141)); // 设置AnalogClock的位置和大小
analogClock->raise(); // 将AnalogClock窗口置于最前面
calendarWidget->raise(); // 将日历控件置于最上层
OffButton->raise(); // 将关闭按钮置于最上层
OnButton->raise(); // 将打开按钮置于最上层
dial->raise(); // 将旋转控件置于最上层
lcdNumber->raise(); // 将数字显示控件置于最上层
label->raise(); // 将标签控件置于最上层
QWidget::setTabOrder(OnButton, OffButton); // 设置按Tab键的顺序,按下Tab键后光标从打开按钮移动到关闭按钮
retranslateUi(Form); // 重新翻译UI界面,将各个控件的文字翻译成目标语言
QObject::connect(OnButton, SIGNAL(clicked()), Form, SLOT(slot1())); // 当打开按钮被点击时,调用Form的slot1()函数
QObject::connect(OffButton, SIGNAL(clicked()), Form, SLOT(slot2())); // 当关闭按钮被点击时,调用Form的slot2()函数
QObject::connect(dial, SIGNAL(valueChanged(int)), lcdNumber, SLOT(display(int))); // 当旋转控件的值变化时,显示在数字显示控件中
QObject::connect(OnButton, SIGNAL(clicked()), calendarWidget, SLOT(show())); // 当打开按钮被点击时,显示日历控件
QObject::connect(OffButton, SIGNAL(clicked()), calendarWidget, SLOT(hide())); // 当关闭按钮被点击时,隐藏日历控件
QObject::connect(OnButton, SIGNAL(clicked()), analogClock, SLOT(hide())); // 当打开按钮被点击时,隐藏模拟时钟控件
QObject::connect(OffButton, SIGNAL(clicked()), analogClock, SLOT(show())); // 当关闭按钮被点击时,显示模拟时钟控件
QObject::connect(dial, SIGNAL(valueChanged(int)), Form, SLOT(slot3(int))); // 当旋转控件的值变化时,调用Form的slot3()函数
QMetaObject::connectSlotsByName(Form); // 自动连接由UI文件中的QObject::connectSlotsByName()指定的所有控件和槽函数
void retranslateUi(QWidget *Form)
{
// 设置窗口标题,参数依次为窗口对象、翻译文本、上下文、编码格式
Form->setWindowTitle(QApplication::translate("Form", "Best Fan Controller", 0, QApplication::UnicodeUTF8));
// 设置关闭按钮的文本,参数依次为按钮对象、翻译文本、上下文、编码格式
OffButton->setText(QApplication::translate("Form", "Clock", 0, QApplication::UnicodeUTF8));
// 设置打开按钮的文本,参数依次为按钮对象、翻译文本、上下文、编码格式
OnButton->setText(QApplication::translate("Form", "Calendar", 0, QApplication::UnicodeUTF8));
// 设置标签的文本,参数依次为标签对象、翻译文本、上下文、编码格式
label->setText(QApplication::translate("Form", "Fan Speed", 0, QApplication::UnicodeUTF8));
#ifndef QT_NO_TOOLTIP
// 如果系统支持鼠标悬停提示,则设置鼠标悬停提示文本,参数依次为部件对象、翻译文本、上下文、编码格式
analogClock->setToolTip(QApplication::translate("Form", "The current time", 0, QApplication::UnicodeUTF8));
#endif // QT_NO_TOOLTIP
#ifndef QT_NO_WHATSTHIS
// 如果系统支持 What's This 帮助,则设置 What's This 帮助文本,参数依次为部件对象、翻译文本、上下文、编码格式
analogClock->setWhatsThis(QApplication::translate("Form", "The analog clock widget displays the current time.", 0, QApplication::UnicodeUTF8));
#endif // QT_NO_WHATSTHIS
} // retranslateUi
前后端数据交互
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) // MainWindow 类的构造函数,参数为 QWidget 类型的指针 parent,用于初始化基类。
, ui(new Ui::MainWindow) // 调用 QMainWindow 的构造函数,将传入的 parent 指针传递给基类,以初始化基类。
{
ui->setupUi(this); //创建一个名为 ui 的新的 Ui::MainWindow 类型的指针,用于管理当前窗口的 UI。
setStyleSheet("background-color: black;"); // 设置窗口背景色为黑色
connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(ctrlFan())); // 连接滑动条的值改变信号和控制风扇槽函数
connect(this, SIGNAL(slierValueChanged(double)), ui->gaugepanel, SLOT(updateValue(double))); // 连接当前窗口发出的滑动条值改变信号和仪表盘更新函数
}
void MainWindow::ctrlFan() // 定义控制风扇槽函数
{
int value = ui->horizontalSlider->value(); // 获取滑动条当前的值
emit slierValueChanged(1.0 * value); // 发出当前滑动条值的信号
control_fan(value); // 调用控制风扇的函数,传入滑动条的值
}