feedforward 发表于 2022-6-19 13:51:20

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

在MainWindow里实现串口console网上资料已经比较多了,这里不再赘述,参加如下链接:
https://blog.csdn.net/wuweidonggmail/article/details/115912729

本文基于QT官方示例Qt Serial Port/erminal Example

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:


最终在QT右边的对象监视器里我们看到已经有一个console控件对象,它的类使我们自定义的Console:


接下来我们需要在console.cpp里重新实现:
   
virtual void keyPressEvent(QKeyEvent *e);
    virtual void mousePressEvent(QMouseEvent *e);
    virtual void mouseDoubleClickEvent(QMouseEvent *e);
    virtual void contextMenuEvent(QContextMenuEvent *e);
因为我们要将键盘输入的字符发送给串口而不是显示在界面上.
void Console::keyPressEvent(QKeyEvent *e)
{
    switch (e->key()) {
    case Qt::Key_Left:
    case Qt::Key_Right:
    case Qt::Key_Up:
    case Qt::Key_Down:
      break;
    //case Qt::Key_Backspace:
    default:
      if (localEchoEnabled)
            QPlainTextEdit::keyPressEvent(e);
      emit getData(e->text().toLocal8Bit());
    }
}


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

void Console::putData(const QByteArray &data)
{

    char temp={0};

    int count = data.count();


   for(int i = 0;i<count;i++)
   {
             temp = data;
             if((temp >= 0) && (temp <= 0x7e))
             {//ASCII
               if(temp == 0x08)
               {// '/b':backspace键
                     QPlainTextEdit::textCursor().deletePreviousChar();//删除光标后面一个字符
               }
               else if(temp == 27)//"\033[K"
               {
                  esc = 27;
               }
               else if((temp == 91)&&(esc==27))
               {
                  esc = 91;
               }
               else if((temp == 75)&&(esc==27)&&(esc==91))
               {
                  esc = 75;
                  if((esc==27)&&(esc==91)&&(esc == 75))
                  {
                      esc = 0;
                      esc = 0;
                      esc = 0;
                  }
               }
               else
               {
                  insertPlainText(QString(QLatin1String((char *)temp)));
               }
             }
   }

    QScrollBar *bar = verticalScrollBar();
    bar->setValue(bar->maximum());
}


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

最后记一个奇怪现象:
通过以下代码在
QString string(data);
insertPlainText(string);
在console中插入文本显示的话文本行距正常

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


页: [1]
查看完整版本: QT应用页面里实现串口终端