请选择 进入手机版 | 继续访问电脑版

前馈科技

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 353|回复: 0

QT应用页面里实现串口终端

[复制链接]

97

主题

97

帖子

539

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
539
发表于 2022-6-19 13:51:20 | 显示全部楼层 |阅读模式
在MainWindow里实现串口console网上资料已经比较多了,这里不再赘述,参加如下链接:
https://blog.csdn.net/wuweidonggmail/article/details/115912729

本文基于QT官方示例Qt Serial Port/[url=]erminal Example[/url]

https://doc.qt.io/qt-5/qtserialport-terminal-example.html

在QT应用程序的某个页面实现一个串口终端,但相对于官方例程增加对backspace键的支持.终端主界面都是通过继承QPlainTextEdit的Console类来实现的

官方例程是在MainWindow的构造函数中通过console = new Console;来建立terminal界面, 并setCentralWidget(console);将terminal放在MainWindow的中
央,但由于我们串口终端不再MainWindow中,因此无法使用setCentralWidget,此外放console的界面还有别的控件,因此用console = new Console来在页面
生成terminal界面不太好布局, 还是在我们熟悉的ui例设置布局比较方便.但ui里的在可视化编辑控件的操作中,所有控件都是⾃带的控件,那么怎么才能像
动态添加控件那样使⽤⾃定义的类(控件)?答案是使用"控件提升":
右键页面上的QPlainTextEdit选择Promoted Widgets, 设置基类为QPlainTextEdit,派生类为Console, 头文件为console.h:
Screenshot from 2022-06-19 13-09-18.png

最终在QT右边的对象监视器里我们看到已经有一个console控件对象,它的类使我们自定义的Console:
Screenshot from 2022-06-19 13-14-49.png

接下来我们需要在console.cpp里重新实现:
   
  1. virtual void keyPressEvent(QKeyEvent *e);
  2.     virtual void mousePressEvent(QMouseEvent *e);
  3.     virtual void mouseDoubleClickEvent(QMouseEvent *e);
  4.     virtual void contextMenuEvent(QContextMenuEvent *e);
复制代码

因为我们要将键盘输入的字符发送给串口而不是显示在界面上.
  1. void Console::keyPressEvent(QKeyEvent *e)
  2. {
  3.     switch (e->key()) {
  4.     case Qt::Key_Left:
  5.     case Qt::Key_Right:
  6.     case Qt::Key_Up:
  7.     case Qt::Key_Down:
  8.         break;
  9.     //case Qt::Key_Backspace:
  10.     default:
  11.         if (localEchoEnabled)
  12.             QPlainTextEdit::keyPressEvent(e);
  13.         emit getData(e->text().toLocal8Bit());
  14.     }
  15. }
复制代码



实现串口返回数据在在terminal界面上的显示,这里需要单独解析backspace键和vt100里的特殊操作/"\033[K" :

  1. void Console::putData(const QByteArray &data)
  2. {

  3.     char temp[10]={0};

  4.     int count = data.count();


  5.    for(int i = 0;i<count;i++)
  6.    {
  7.              temp[0] = data;
  8.              if((temp[0] >= 0) && (temp[0] <= 0x7e))
  9.              {//ASCII
  10.                  if(temp[0] == 0x08)
  11.                  {// '/b':backspace键
  12.                      QPlainTextEdit::textCursor().deletePreviousChar();//删除光标后面一个字符
  13.                  }
  14.                  else if(temp[0] == 27)//"\033[K"
  15.                  {
  16.                     esc[0] = 27;
  17.                  }
  18.                  else if((temp[0] == 91)&&(esc[0]==27))
  19.                  {
  20.                     esc[1] = 91;
  21.                  }
  22.                  else if((temp[0] == 75)&&(esc[0]==27)&&(esc[1]==91))
  23.                  {
  24.                     esc[2] = 75;
  25.                     if((esc[0]==27)&&(esc[1]==91)&&(esc[2] == 75))
  26.                     {
  27.                       esc[0] = 0;
  28.                       esc[1] = 0;
  29.                       esc[2] = 0;
  30.                     }
  31.                  }
  32.                  else
  33.                  {
  34.                     insertPlainText(QString(QLatin1String((char *)temp)));
  35.                  }
  36.              }
  37.    }

  38.     QScrollBar *bar = verticalScrollBar();
  39.     bar->setValue(bar->maximum());
  40. }
复制代码



完成console在大页面里的接口后我们编译,但有无法找到console.h的错误,
解决⽅法⼀:
⼿动修改(ui_pageterminal.h)关于这个⾃定义类的路径,问题是重新构建之后⼜要重新修改,因为ui_pageterminal.h是自动生产的.
解决⽅法之⼆:
把路径在.pro⽂件⾥include进去 :INCLUDEPATH += ./pages

最后记一个奇怪现象:
通过以下代码在
  1. QString string(data);
  2. insertPlainText(string);
复制代码

在console中插入文本显示的话文本行距正常

用insertPlainText(QString(QLatin1String((char *)temp)));或QPlainTextEdit::textCursor().insertText(temp);在console中插入文本显示
文本行距步正常,行与行之间会空一行.
实现的界面如下所示:
Screenshot from 2022-06-19 13-47-55.png

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|计算机控制

GMT+8, 2024-3-29 23:43 , Processed in 0.054140 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表