HMI-62-【多媒体】空调部分 3

306 阅读6分钟

“我正在参加「掘金·启航计划」” 头图

前言

如果这个系列Qt 汽车 HMI 仪表文章你都看过,或者大部分看过,知道整个项目的一个大致,那么可以接着看下去,如果是第一次就直接看到了这篇文章,那么多半应该是云里雾里的,因为写到现在,基本就是开发流水账了。除了个别知识点获取有参考价值,其他的应该没有太多的价值。

如果对这个项目感兴趣,那么有两个办法

1 联系作者(也就是我),获取源码

2 把Qt 汽车 HMI 仪表从头看看,至少知道我想要做什么,才能知道我现在在做什么。

HMI-62-【多媒体】空调部分 3

今天接着昨天的思路来搞,实现空调数字模块,因为素材里面的空调是双区空调,所以我还是自定义了一个模块,这个实现不难,可以参考上一篇自定义个按钮。

今天的问题还是在于我昨天提到的那个坑,就是我用一个QList来存放索引控件,在昨天都是一个类型的时候,没有问题,那么今天又多了一个类型,或者说后面还会有更多的类型,那么我需要怎么做了,难道要建立一对QList来存放不同的控件吗,那我的逻辑控制还是需要写很多呀,那我我是怎么怎么解决的呢,看下面的内容。HMI-61-【多媒体】空调部分 2

☑当前进度

相较昨天,今天增加了两个空调的数字显示,并且可以和我们中央控制旋钮联动起来。如下图所示


HMI-62-【多媒体】空调部分 3☑当前进度1 空调数字模块1.1 头文件1.2 源文件2 解决不同类型模块索引2.1 模块初始化代码2.2 切换方式☞第三阶段成果展示☞第二阶段成果展示☞第一阶段成果展示

关键字: HMIMultifunctionQtQList收音机

1 空调数字模块

这个基本原理和昨天的自定义按钮没有太多逻辑,今天这里直接贴上代码和布局图。这个模块暂时就这样,后期随着整个空调模块的完成在调整完善。

image-20220503232455016

1.1 头文件

 #ifndef MFD_AIRCONDITIONERNUMBERCONTROL_H
 #define MFD_AIRCONDITIONERNUMBERCONTROL_H
 ​
 #include <QWidget>
 ​
 namespace Ui {
 class MFD_AirConditionerNumberControl;
 }
 ​
 class MFD_AirConditionerNumberControl : public QWidget
 {
     Q_OBJECT
 ​
 public:
     explicit MFD_AirConditionerNumberControl(QWidget *parent = nullptr);
     ~MFD_AirConditionerNumberControl();
     /**
      * @brief setAirNumber
      * @param airNumber
      * 设置空调温度
      */
     void setAirNumber(double airNumber);
 ​
     /**
      * @brief selected
      * @param select
      * 是否选中
      */
     void selected(bool select);
 ​
 signals:
     /**
      * @brief signal_AirNumber
      * @param airNumber
      * 空调温度变化信号
      */
     void signal_AirNumber(double airNumber);
 ​
 private slots:
     /**
      * @brief on_pushButton_up_pressed
      * 上按钮按下槽函数
      */
     void on_pushButton_up_pressed();
     /**
      * @brief on_pushButton_up_released
      * 上按钮松开槽函数
      */
     void on_pushButton_up_released();
     /**
      * @brief on_pushButton_down_pressed
      * 下按钮按下槽函数
      */
     void on_pushButton_down_pressed();
     /**
      * @brief on_pushButton_down_released
      * 下按钮松开槽函数
      */
     void on_pushButton_down_released();
 ​
 private:
     /**
      * @brief paintEvent
      * @param event
      * 重绘事件,用于绘制背景
      */
     void paintEvent(QPaintEvent* event);
 private:
     Ui::MFD_AirConditionerNumberControl *ui;
     double m_AirNumber = 26.0;                  // 空调温度
 };
 ​
 #endif // MFD_AIRCONDITIONERNUMBERCONTROL_H
 ​

1.2 源文件

 #include "mfd_airconditionernumbercontrol.h"
 #include "ui_mfd_airconditionernumbercontrol.h"
 #include <QPainter>
 #include <QDebug>
 ​
 MFD_AirConditionerNumberControl::MFD_AirConditionerNumberControl(QWidget *parent) :
     QWidget(parent),
     ui(new Ui::MFD_AirConditionerNumberControl)
 {
     ui->setupUi(this);
     ui->label_mainback->hide();
     ui->label_selected->hide();                 // 默认为非选中状态
     ui->label_buttonSelect_down->hide();
     ui->label_buttonSelect_up->hide();
 ​
     ui->pushButton_down->setStyleSheet("QPushButton{border-image: url(:/AirConditioner/Resources/MultifunctionDisplay/AirConditioner/AirConditionerNumberControl/down.png);}"
                                        "QPushButton:pressed{border-image: url(:/AirConditioner/Resources/MultifunctionDisplay/AirConditioner/AirConditionerNumberControl/down_1.png);}");
     ui->pushButton_up->setStyleSheet("QPushButton{border-image: url(:/AirConditioner/Resources/MultifunctionDisplay/AirConditioner/AirConditionerNumberControl/up.png);}"
                                      "QPushButton:pressed{border-image: url(:/AirConditioner/Resources/MultifunctionDisplay/AirConditioner/AirConditionerNumberControl/up_1.png);}");
 ​
 ​
 ​
     ui->pushButton_down->setAutoRepeat(true);
     ui->pushButton_down->setAutoRepeatDelay(400);
     ui->pushButton_down->setAutoRepeatInterval(150);
 ​
     ui->pushButton_up->setAutoRepeat(true);
     ui->pushButton_up->setAutoRepeatDelay(400);
     ui->pushButton_up->setAutoRepeatInterval(150);
 ​
 }
 ​
 MFD_AirConditionerNumberControl::~MFD_AirConditionerNumberControl()
 {
     delete ui;
 }
 ​
 void MFD_AirConditionerNumberControl::setAirNumber(double airNumber)
 {
     m_AirNumber = airNumber;
     ui->label_text->setText(QString("%1℃").arg(airNumber));
 }
 ​
 void MFD_AirConditionerNumberControl::selected(bool select)
 {
     if(select)
         ui->label_selected->show();
     else
         ui->label_selected->hide();
 }
 ​
 void MFD_AirConditionerNumberControl::paintEvent(QPaintEvent *event)
 {
     Q_UNUSED(event)
     QPainter painter;
     painter.begin(this);
     painter.drawPixmap(0,0,width(),height(), QPixmap(":/AirConditioner/Resources/MultifunctionDisplay/AirConditioner/AirConditionerNumberControl/back.png"));               // 绘制背景
     painter.end();
 }
 ​
 ​
 void MFD_AirConditionerNumberControl::on_pushButton_up_pressed()
 {
 ​
 }
 ​
 ​
 void MFD_AirConditionerNumberControl::on_pushButton_up_released()
 {
     if(m_AirNumber < 39.0)
     {
         m_AirNumber += 0.5;
         ui->label_text->setText(QString("%1℃").arg(m_AirNumber));
         emit signal_AirNumber(m_AirNumber);
     }
 }
 ​
 ​
 void MFD_AirConditionerNumberControl::on_pushButton_down_pressed()
 {
 ​
 }
 ​
 ​
 void MFD_AirConditionerNumberControl::on_pushButton_down_released()
 {
     if(m_AirNumber> 14.0)
     {
         m_AirNumber -= 0.5;
         ui->label_text->setText(QString("%1℃").arg(m_AirNumber));
         emit signal_AirNumber(m_AirNumber);
     }
 }
 ​
 ​

2 解决不同类型模块索引

这里我的方法还是比较笨的,还希望小伙伴们给点新奇的方式。先看看我的QList有什么变化,那么加上今天的两个模块,我的新QList里面应该会有两种类型的模块了,但是你,QList应该同时只能有一种类型的值吧,所以呢,我这里第一次真正使用了一个东西reinterpret_cast

image-20220503233313925

2.1 模块初始化代码

这个也是就上篇中的initMyPushButtons函数,因为增加了新的模块,再叫initMyPushButtons,可能有点不妥当,所以就更名了。代码如下

 void MFD_AirConditioner::initModules()
 {
     m_ModulesList.clear();
 ​
     ui->myPushButton_auto->setText("AUTO");
     m_ModulesList.append(ui->myPushButton_auto);
 ​
     ui->myPushButton_ac->setText("AC");
     m_ModulesList.append(ui->myPushButton_ac);
 ​
     ui->myPushButton_maxAC->setText("MAX A/C");
     m_ModulesList.append(ui->myPushButton_maxAC);
 ​
     ui->myPushButton_cycle->setPicText(":/AirConditioner/Resources/MultifunctionDisplay/AirConditioner/AirConditionerPushButton/cycle.png",
                                        ":/AirConditioner/Resources/MultifunctionDisplay/AirConditioner/AirConditionerPushButton/cycle_1.png");
     m_ModulesList.append(ui->myPushButton_cycle);
 ​
     ui->myPushButton_aqs->setText("AQS");
     m_ModulesList.append(ui->myPushButton_aqs);
 ​
     ui->myPushButton_dual->setText("DUAL");
     m_ModulesList.append(ui->myPushButton_dual);
 ​
 ​
     m_ModulesList.append(reinterpret_cast<MFD_AirConditioner_PushButon*>(ui->airConditionerNumberControl_L));
     m_ModulesList.append(reinterpret_cast<MFD_AirConditioner_PushButon*>(ui->airConditionerNumberControl_R));
 ​
     ui->myPushButton_rear->setText("REAR");
     m_ModulesList.append(ui->myPushButton_rear);
 ​
     ui->myPushButton_rear->setICON(":/AirConditioner/Resources/MultifunctionDisplay/AirConditioner/AirConditionerPushButton/lock.png");
 ​
     ui->myPushButton_ion->setText("ION");
     m_ModulesList.append(ui->myPushButton_ion);
 ​
 }

核心代码

image-20220503233708877

2.2 切换方式

那么怎么使用了,因为我的两个模块里面有一个函数是一样的,包括内部实现,突然感觉这里是不是可以用多态来实现呢。暂时还没有彻底考虑好,还是先说我现在的处理方法吧,就是在切换索引的函数里面根据索引值在手动切换指针类型。代码如下:

 void MFD_AirConditioner::updateSelect()
 {
 ​
     /**
      * 这里使用迭代器有点问题,因为m_ModulesList有多个类型了
      */
     //    QListIterator<MFD_AirConditioner_PushButon*> list(m_ModulesList);
     //    while (list.hasNext()) {
     //        list.next()->selected(false);
     //    }
 ​
     for(auto i = 0;i< m_ModulesList.count();i++)
     {
 ​
         if(i == AirConditionerIndex::AC_number_L || i == AirConditionerIndex::AC_number_R)
         {
             reinterpret_cast<MFD_AirConditionerNumberControl*>(m_ModulesList[i])->selected(false);
         }
         else
             m_ModulesList[i]->selected(false);
     }
 ​
 ​
     if(m_SelectIndex == AirConditionerIndex::AC_number_L || m_SelectIndex == AirConditionerIndex::AC_number_R)
     {
         reinterpret_cast<MFD_AirConditionerNumberControl*>(m_ModulesList[m_SelectIndex])->selected(true);
     }
     else
         m_ModulesList[m_SelectIndex]->selected(true);
 }

核心代码

image-20220503233940893

这就是今天的基本内容了,现在是晚上的11点40 ,珍爱生命,远离熬夜,祝大家做个好梦。

image-20220503234047993


☞第三阶段成果展示

目前已完成液晶仪表三种模式的初步显示,小模块后期根据精力更新了,主要还得找美术来搞资源,自己能力不够。暂未跟新计划。展示如下:

[video(video-yznBr6e3-1648369267384)(type-bilibili)(url-player.bilibili.com/player.html…img-blog.csdnimg.cn/img_convert…基于Qt的汽车仪表模拟 3.0)]

✈B站链接:www.bilibili.com/video/BV1WS…


☞第二阶段成果展示

目前以完成HUD界面及接口开发,液晶仪表舒适模式和运动模式的开发。视频展示如下:

[video(video-2AqJ88TY-1645273728489)(type-bilibili)(url-player.bilibili.com/player.html…img-blog.csdnimg.cn/img_convert…基于Qt的汽车仪表模拟 2.0)]

✈B站链接:www.bilibili.com/video/BV1aq…


☞第一阶段成果展示

目前以完成HUD界面及接口开发,液晶仪表舒适模式开发。展示如下:

[video(video-ArCvRvBQ-1642664938100)(type-bilibili)(url-player.bilibili.com/player.html…img-blog.csdnimg.cn/img_convert…基于Qt的汽车仪表模拟 1.0))]

✈B站链接:www.bilibili.com/video/BV1qJ…


说明:

本项目中所使借鉴原型来自:[吉利] 博瑞GE | 仪表HMI设计吉利汽车HMI项目

多媒体部分是来自吉利博瑞2017旗舰版界面所有权和解释权都归吉利汽车所有。

设计图的所有权和解释权都归吉利汽车所有。

本项目所有资源文件均由**打不死的小海**复刻制作。

本项目代码暂时不会开源,有需要的源码的可与我联系,左上角二维码加微信。

本项目仅限学习交流、禁止商业使用。