[应用相关] STM32遥控小车上位机部分

[复制链接]
2054|68
 楼主| 回复就哭哭 发表于 2022-2-28 15:35 | 显示全部楼层
a. 实现下拉框的自动填充
功能描述:每次弹出子窗口时,程序能自动将当前已连接的所有串口端口名自动填充到串口名下拉框中。

代码片段:

  1. newWindow::newWindow(QWidget *parent) :
  2.     QWidget(parent),
  3.     ui(new Ui::newWindow)
  4. {
  5.     ui->setupUi(this);
  6.     //获取当前已连接的串口号,并将其填入到下拉框选项中
  7.     QList<QSerialPortInfo> InfoSerialPort = QSerialPortInfo::availablePorts();
  8.     int cnt = InfoSerialPort.count();
  9.     for(int i=0; i<cnt; i++)
  10.     {
  11.         ui->CboxPortName->addItem(InfoSerialPort.at(i).portName());
  12.     }
  13. }

 楼主| 回复就哭哭 发表于 2022-2-28 15:46 | 显示全部楼层
代码说明:

代码中QSerialPortInfo::availablePorts是QSerialPortInfo中的静态变量,可不需实例化对象直接调用。availablePorts中存储的是当前已连接上的串口信息。
 楼主| 回复就哭哭 发表于 2022-2-28 15:47 | 显示全部楼层
b. 实现点击确定按钮时保存配置且关闭窗口
功能描述:点击确定按钮时,程序将当前下拉框的选项内容写到配置文件中,然后在关闭窗口。此过程的槽函数分为三步:1. 读取当前下拉框的内容,2. 写入配置文件,3. 关闭窗口。
 楼主| 回复就哭哭 发表于 2022-2-28 15:52 | 显示全部楼层
代码片段:
  1. void newWindow::on_BtnCommit_clicked()
  2. {
  3.     readCbox();
  4.     makeConfigFile();
  5.     this->close();
  6. }
  7. void newWindow::readCbox()
  8. {
  9.     mPortName = ui->CboxPortName->currentText();
  10.     ...
  11. }
  12. void newWindow::makeConfigFile()
  13. {
  14.     QSettings iniConfigFile(fileName,QSettings::IniFormat);
  15.     iniConfigFile.setValue("serialport/portname",mPortName);
  16.     ...
  17. }
 楼主| 回复就哭哭 发表于 2022-2-28 15:54 | 显示全部楼层
代码说明:

readCbox()为槽函数的第一步,调用QComboBox类的currentText()或currentIndex()以获取当前选择的内容。
makeConfigFile()为槽函数的第二步,此函数与前文主窗口的makeConfigFile()函数写法相同,此处不多解释(注:这里可能有人会问了,既然两个函数相同,为啥不写成static类型函数然后直接调用呢?原因就是这个函数对类的成员变量有操作,改成static函数类型的话需要将成员变量弄成全局变量,整个工程就要大改,有点麻烦,感兴趣的朋友可以试一试。)
this->close()为槽函数的第三步,该函数可以直接将当前窗口关闭。
 楼主| 回复就哭哭 发表于 2022-2-28 15:55 | 显示全部楼层
c. 实现点击取消按钮时关闭子窗口
功能描述:点击取消按钮时,直接等效于关闭该窗口。
代码片段:
  1. void newWindow::on_BtnCancel_clicked()
  2. {
  3.     this->close();
  4. }
 楼主| 回复就哭哭 发表于 2022-2-28 15:55 | 显示全部楼层
代码说明:

该槽函数直接调用this->close()就行,与点击确定按钮槽函数的最后一步相同。
 楼主| 回复就哭哭 发表于 2022-2-28 15:57 | 显示全部楼层
d. 开启子窗口时的初始化动作(实现当前串口配置的显示)
功能描述:每次弹出子窗口时,保证子窗口中的下拉框默认选项为当前配置选项。该过程分为两步:1. 读取配置文件,2. 将参数显示到下拉框中。要使每次初始化时都能执行此过程,将该过程添加到初始化的函数中就行。
 楼主| 回复就哭哭 发表于 2022-2-28 15:58 | 显示全部楼层
代码片段:
  1. newWindow::newWindow(QWidget *parent) :
  2.     QWidget(parent),
  3.     ui(new Ui::newWindow)
  4. {
  5.     ui->setupUi(this);
  6.     //获取当前已连接的串口号,并将其填入到下拉框选项中
  7.     QList<QSerialPortInfo> InfoSerialPort = QSerialPortInfo::availablePorts();
  8.     int cnt = InfoSerialPort.count();
  9.     for(int i=0; i<cnt; i++)
  10.     {
  11.         ui->CboxPortName->addItem(InfoSerialPort.at(i).portName());
  12.     }
  13.     //设置下拉框中的默认选项为当前配置选项
  14.     readConfigFile();
  15.     setCbox();
  16. }
  17. void newWindow::readConfigFile()
  18. {
  19.     QFile file(fileName);
  20.     QSettings iniConfigFile(fileName,QSettings::IniFormat);
  21.     mPortName = iniConfigFile.value("serialport/portname").toString();
  22.         ...
  23. }
  24. void newWindow::setCbox()
  25. {
  26.     ui->CboxPortName->setCurrentText(mPortName);
  27.         ...
  28. }
 楼主| 回复就哭哭 发表于 2022-2-28 15:59 | 显示全部楼层
代码说明:

我在初试化函数中添加了两个函数过程,一个是readConfigFile(),另一个是setCbox(),分别完成读取配置文件和设置当前下拉框默认选项的动作。
readConfigFile()与主窗口的readConfigFile()一致,此处不多叙述。
setCbox()主要调用setCurrentText()来实现更改下拉框的当前选项。
 楼主| 回复就哭哭 发表于 2022-2-28 16:00 | 显示全部楼层
7. 键盘按键检测的实现
键盘按键检测并没有UI设计,因此放在最后来讲。

功能描述:该部分的功能为当连接好遥控小车时,按下键盘上的上下左右按键可以分别控制遥控小车的前进后退转向。抬起按键时遥控小车又将归位。按键逻辑如下表所示:
  1. up         :前进                Ctrl+right        :顺时针旋转
  2. down :后退                Ctrl+left        :逆时针旋转
  3. right:右转                Z        :加速               
  4. left :左转                X        :减速
 楼主| 回复就哭哭 发表于 2022-2-28 16:01 | 显示全部楼层
代码片段:
  1. // keyPressEvent()函数重写
  2. void MainWindow::keyPressEvent(QKeyEvent *event)
  3. {
  4.     if(!event->isAutoRepeat())//解释见代码说明
  5.     {
  6.         if(mKeyFlag)//判断是否按下Ctrl键
  7.         {
  8.             switch (event->key()) //判断按下的是哪个按键
  9.             {
  10.             case Qt::Key_Left:
  11.                 on_BtnCcw_clicked();
  12.                 break;
  13.             case Qt::Key_Right:
  14.                 on_BtnCw_clicked();
  15.                 break;
  16.             }
  17.         }
  18.         else
  19.         {
  20.             switch (event->key()) //判断按下的是哪个按键
  21.             {
  22.             case Qt::Key_Up:
  23.                 on_BtnGo_clicked();
  24.                 break;
  25.             case Qt::Key_Down:
  26.                 on_BtnBack_clicked();
  27.                 break;
  28.             case Qt::Key_Left:
  29.                 on_BtnLeft_clicked();
  30.                 break;
  31.             case Qt::Key_Right:
  32.                 on_BtnRight_clicked();
  33.                 break;
  34.             case Qt::Key_Z:
  35.                 on_BtnSpeedUp_clicked();
  36.                 break;
  37.             case Qt::Key_X:
  38.                 on_BtnSpeedDown_clicked();
  39.                 break;
  40.             case Qt::Key_Control:        //如果按下Ctrl键则将mKeyFlag设为true
  41.                 mKeyFlag = true;
  42.                 break;
  43.             }
  44.         }
  45.     }
  46. }
  47. // keyReleaseEvent()函数重写
  48. void MainWindow::keyReleaseEvent(QKeyEvent *event)
  49. {
  50.     if(!event->isAutoRepeat())
  51.     {
  52.         if(mKeyFlag)//判断是否按下Ctrl键
  53.         {
  54.             switch (event->key()) //判断松开的是哪个按键
  55.             {
  56.             case Qt::Key_Left:
  57.                 getStraight();
  58.                 break;
  59.             case Qt::Key_Right:
  60.                 getStraight();
  61.                 break;
  62.             case Qt::Key_Control:
  63.                 mKeyFlag = false;        //如果松开Ctrl键则将mKeyFlag设为false
  64.                 break;
  65.             }
  66.         }
  67.         else
  68.         {
  69.             switch (event->key()) //判断松开的是哪个按键
  70.             {
  71.             case Qt::Key_Up:
  72.                 on_BtnStop_clicked();
  73.                 break;
  74.             case Qt::Key_Down:
  75.                 on_BtnStop_clicked();
  76.                 break;
  77.             case Qt::Key_Left:
  78.                 getStraight();
  79.                 break;
  80.             case Qt::Key_Right:
  81.                 getStraight();
  82.                 break;
  83.             }
  84.         }
  85.     }
  86. }
 楼主| 回复就哭哭 发表于 2022-2-28 16:04 | 显示全部楼层
代码说明:

因为要进行键盘按键检测,故我使用的是QT自带的QKeyEvent类来实现,使用方法为:现在mainWindow头文件中导入QKeyEvent类,再在cpp文件中重写keyPressEvent()和keyReleaseEvent()函数。在QKeyEvent的逻辑中,当键盘事件触发时,程序会回调这两个函数(即keyPressEvent和keyReleaseEvent),而QKeyEvent的定义中本身并没有这两个函数的内容,即回调之后又会立马退出这两个函数,像无事发生一样。故我们只需要在主窗口文件中对这两个函数进行重写,让程序做一些事情,即可实现键盘的按键检测的功能。
 楼主| 回复就哭哭 发表于 2022-2-28 16:05 | 显示全部楼层
代码中判断按键键值前,有2个if判断语句,第一个是!event->isAutoRepeat(),判断按键来源是否是键盘自动重复按下信号发出的,第二个是mKeyFlag,该信号为mainWindow类的成员变量,初始化时设置为false,意味着当前ctrl键并未按下。
 楼主| 回复就哭哭 发表于 2022-2-28 16:05 | 显示全部楼层
event->isAutoRepeat()函数解释:理论上讲,当按下键盘上的按键时,keyPressEvent()就会接收到一个按键信号,如果长按某一按键时,键盘就会持续发送按下的信号给keyPressEvent(),即每隔几十毫秒keyPressEvent()就会接收到一个按键被按下的信号,除了第一个按下信号是人为触发的,后面的按下信号都是键盘自动触发的。而实际上我们只想要在按下按键时程序执行按键检测函数即可,我们并不关心按了多长时间。因此我使用了按键信号event内部的函数isAutoRepeat(),该函数的返回值标志了当前按键事件是否为键盘自动触发,使用该函数就可以滤除掉那些自动触发的按键事件。
 楼主| 回复就哭哭 发表于 2022-2-28 16:08 | 显示全部楼层
mKeyFlag成员变量的解释:由于控制遥控小车自转时需要用到组合按键Ctrl+left/right,因此我用mKeyFlag来标志Ctrl键是否被按下,在Ctrl键被按下和没被按下后按方向键对应的功能不同,也即对应的程序操作不同。
 楼主| 回复就哭哭 发表于 2022-2-28 16:09 | 显示全部楼层
三、总结
到这里,整个程序就差不多完成了。**中有部分逻辑不清晰或概念讲述有问题的地方请评论指出,我会不定时查看评论并做出更改。
附:代码源码在此处:百度网盘(提取码:adm9 )
Pulitzer 发表于 2023-9-24 11:52 | 显示全部楼层

---------------------------
wpsoffice
---------------------------
对话框打开时命令无法执行。单击“确定”,然后关闭对话框再试。
---------------------------
确定   
---------------------------
万图 发表于 2023-9-25 08:11 | 显示全部楼层

ESD静电保护器基本上都是通过静电进行吸收和耗散
Uriah 发表于 2023-9-25 09:14 | 显示全部楼层

这类型灌封胶一般分为A、B双组份在进行1:1的配比后再进行灌封的操作
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部