基于A9和QT的调速风扇控制

219 阅读8分钟

要求:在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); // 调用控制风扇的函数,传入滑动条的值
}

moc_analogclock.cpp

该文件为 Qt 元对象编译器 (MOC) 自动生成的代码,用于支持 analogclock 类的元对象特性。。

moc_window.cpp

该文件为 Qt 元对象编译器 (MOC) 自动生成的代码,用于支持 Window 类的元对象特性。