QT QSerrialPort 串口信息获取和发送

发送/接收数据:

比较简单,一些选项可以使用下拉框或者菜单组件来选择都行,这里我个人用的菜单

首先初始化一个串口对象以及窗口,我个人比较喜欢使用QTabWidget,几个窗口切换很方便,省空间,比滚动窗口好用些,以及定义了一个错误信号字典,字典内容可能会有误差,大家看着用吧

    QSerialPort *SP_sralPort = new QSerialPort();
    QWidget *SP_Widget = new QWidget();
    QGridLayout *SP_globalGrid = new QGridLayout(SP_Widget);

    QTabWidget *SP_ToolbarTabWidget = new QTabWidget();
    QTextEdit *SP_serialInfoEdit = new QTextEdit();

    QMap<QSerialPort::SerialPortError, QString> SerialErrorMap;


cpp:
    SerialErrorMap.insert(QSerialPort::NoError, "状态正常");
    SerialErrorMap.insert(QSerialPort::DeviceNotFoundError, "试图打开不存在的设备时发生错误");
    SerialErrorMap.insert(QSerialPort::PermissionError, "试图打开另一个进程或用户没有足够的权限和凭据打开已打开的设备时发生错误");
    SerialErrorMap.insert(QSerialPort::OpenError, "试图打开此对象中已打开的设备时发生错误");
    SerialErrorMap.insert(QSerialPort::NotOpenError, "设备串口未打开,执行异常");
    SerialErrorMap.insert(QSerialPort::ParityError, "读取数据时奇偶校验错误");
    SerialErrorMap.insert(QSerialPort::FramingError, "读取数据时帧错误");
    SerialErrorMap.insert(QSerialPort::BreakConditionError, "输入线断路");
    SerialErrorMap.insert(QSerialPort::WriteError, "写入数据时发生I/O错误");
    SerialErrorMap.insert(QSerialPort::ReadError, "读取数据时发生I/O错误");
    SerialErrorMap.insert(QSerialPort::ResourceError, "资源不可用");
    SerialErrorMap.insert(QSerialPort::UnsupportedOperationError, "当前操作系统不支持或不禁止所请求的设备操作");
    SerialErrorMap.insert(QSerialPort::TimeoutError, "超时错误");
    SerialErrorMap.insert(QSerialPort::UnknownError, "发生了一个无法识别的错误");

连接信号槽:
    connect(SP_sralPort, &QSerialPort::errorOccurred, this, [&](QSerialPort::SerialPortError Error){SP_serialInfoEdit->append(SerialErrorMap[Error]);});

接着初始化一些需要使用的组件

    Nwidget *SP_configWidget = new Nwidget("SP_configWidget");
    Nlabel *SP_portLabel = new Nlabel("SP_portLabel");
    Nlabel *SP_baudLabel = new Nlabel("SP_baudLabel");
    Nlabel *SP_dtbitsLabel = new Nlabel("SP_dtbitsLabel");
    Nlabel *SP_stbitsLabel = new Nlabel("SP_stbitsLabel");
    Nlabel *SP_ckPlaceLabel = new Nlabel("SP_ckPlaceLabel");
    Nlabel *SP_scontrolLabel = new Nlabel("SP_scontrolLabel");
    QToolButton *SP_usbportBut = new QToolButton(SP_Widget);
    QToolButton *SP_dtplaceBut = new QToolButton(SP_Widget);
    QToolButton *SP_baudrateBut = new QToolButton(SP_Widget);
    QToolButton *SP_stplaceBut = new QToolButton(SP_Widget);
    QToolButton *SP_ckplaceBut = new QToolButton(SP_Widget);
    QToolButton *SP_scontrolBut = new QToolButton(SP_Widget);

    QMenu *SP_usbPortMenu = new QMenu();
    QMenu *SP_baudRateMenu = new QMenu();
    QMenu *SP_dtplaceMenu = new QMenu();
    QMenu *SP_stplaceMenu = new QMenu();
    QMenu *SP_ckplaceMenu = new QMenu();
    QMenu *SP_scontrolMenu = new QMenu();

    QAction *AS_baudr115200 = new QAction("115200", SP_baudRateMenu);
    QAction *AS_baudr57600 = new QAction("57600", SP_baudRateMenu);
    QAction *AS_baudr38400 = new QAction("38400", SP_baudRateMenu);
    QAction *AS_baudr19200 = new QAction("19200", SP_baudRateMenu);
    QAction *AS_baudr9600 = new QAction("9600", SP_baudRateMenu);
    QAction *AS_baudr4800 = new QAction("4800", SP_baudRateMenu);
    QAction *AS_baudr2400 = new QAction("2400", SP_baudRateMenu);
    QAction *AS_baudr1200 = new QAction("1200", SP_baudRateMenu);

    QAction *AS_oddParity = new QAction("奇校验", SP_ckplaceMenu);
    QAction *AS_evenParity = new QAction("偶校验", SP_ckplaceMenu);
    QAction *AS_unParity = new QAction("无校验", SP_ckplaceMenu);

    QAction *AS_dtbitsFive = new QAction("bits 5", SP_dtplaceMenu);
    QAction *AS_dtbitsSix = new QAction("bits 6", SP_dtplaceMenu);
    QAction *AS_dtbitsSeven = new QAction("bits 7", SP_dtplaceMenu);
    QAction *AS_dtbitsEight = new QAction("bits 8", SP_dtplaceMenu);

    QAction *AS_stbitsOne = new QAction("bits 1", SP_stplaceMenu);
    QAction *AS_stbitshalf = new QAction("bits 1.5", SP_stplaceMenu);
    QAction *AS_stbitsTwo = new QAction("bits 2", SP_stplaceMenu);

    QAction *AS_hardControl = new QAction("硬件控制", SP_scontrolMenu);
    QAction *AS_softControl = new QAction("软件控制", SP_scontrolMenu);
    QAction *AS_unControl = new QAction("无控制", SP_scontrolMenu);

把菜单放入QToolButton中

    SP_usbportBut->setMenu(SP_usbPortMenu);
    SP_baudrateBut->setMenu(SP_baudRateMenu);
    SP_dtplaceBut->setMenu(SP_dtplaceMenu);
    SP_stplaceBut->setMenu(SP_stplaceMenu);
    SP_ckplaceBut->setMenu(SP_ckplaceMenu);
    SP_scontrolBut->setMenu(SP_scontrolMenu);

    QFont MenuFont("youyuan", 12);
    SP_usbPortMenu->setFont(MenuFont);
    SP_baudRateMenu->setFont(MenuFont);
    SP_dtplaceMenu->setFont(MenuFont);
    SP_stplaceMenu->setFont(MenuFont);
    SP_ckplaceMenu->setFont(MenuFont);
    SP_scontrolMenu->setFont(MenuFont);

    SP_baudRateMenu->addAction(AS_baudr115200);
    SP_baudRateMenu->addAction(AS_baudr57600);
    SP_baudRateMenu->addAction(AS_baudr38400);
    SP_baudRateMenu->addAction(AS_baudr19200);
    SP_baudRateMenu->addAction(AS_baudr9600);
    SP_baudRateMenu->addAction(AS_baudr4800);
    SP_baudRateMenu->addAction(AS_baudr2400);
    SP_baudRateMenu->addAction(AS_baudr1200);

    SP_ckplaceMenu->addAction(AS_oddParity);
    SP_ckplaceMenu->addAction(AS_evenParity);
    SP_ckplaceMenu->addAction(AS_unParity);

    SP_scontrolMenu->addAction(AS_hardControl);
    SP_scontrolMenu->addAction(AS_softControl);
    SP_scontrolMenu->addAction(AS_unControl);

    SP_dtplaceMenu->addAction(AS_dtbitsFive);
    SP_dtplaceMenu->addAction(AS_dtbitsSix);
    SP_dtplaceMenu->addAction(AS_dtbitsSeven);
    SP_dtplaceMenu->addAction(AS_dtbitsEight);

    SP_stplaceMenu->addAction(AS_stbitsOne);
    SP_stplaceMenu->addAction(AS_stbitshalf);
    SP_stplaceMenu->addAction(AS_stbitsTwo);

连接信号槽

    connect(SP_usbPortMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), SerialPort);});
    connect(SP_baudRateMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), BaudRate);});
    connect(SP_dtplaceMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), DtPlace);});
    connect(SP_stplaceMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), StPlace);});
    connect(SP_ckplaceMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), CheckPlace);});
    connect(SP_scontrolMenu, &QMenu::triggered, this, [this](QAction *AC){SP_serialAttriCfg(AC->text(), Scontrol);});

其中 SP_serialAttriCfg 函数整合了所有选项了,参数:
 

QString Actext 菜单选择的选项文本
SerialAttribute Attribute  属性

属性枚举:

typedef enum {
    SerialPort,
    BaudRate,
    DtPlace,
    StPlace,
    Scontrol,
    CheckPlace
} SerialAttribute;

接下来是SP_serialAttriCfg函数代码: 

void ToolLogicCT::SP_serialAttriCfg(QString Actext, SerialAttribute Attribute){
    switch (Attribute) {
        case BaudRate:
            if (Actext == "115200")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud115200);
            }
            else if (Actext == "57600")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud57600);
            }
            else if (Actext == "38400")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud38400);
            }
            else if (Actext == "19200")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud19200);
            }
            else if (Actext == "9600")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud9600);
            }
            else if (Actext == "4800")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud4800);
            }
            else if (Actext == "2400")
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud2400);
            }
            else
            {
                SP_sralPort->setBaudRate(QSerialPort::Baud1200);
            }
            RdoMap_Serial["SQL_SRLP_BAUD"] = QString("BaudRate = '%1'").arg(Actext);
            SP_baudrateBut->setText(Actext);
            break;

        case DtPlace:
            if (Actext == "bits 5")
            {
                SP_sralPort->setDataBits(QSerialPort::Data5);
            }
            else if (Actext == "bits 6")
            {
                SP_sralPort->setDataBits(QSerialPort::Data6);
            }
            else if (Actext == "bits 7")
            {
                SP_sralPort->setDataBits(QSerialPort::Data7);
            }
            else
            {
                SP_sralPort->setDataBits(QSerialPort::Data8);
            }
            SP_dtplaceBut->setText(Actext);
            RdoMap_Serial["SQL_SRLP_DTPL"] = QString("DataPlace = '%1'").arg(Actext);
            break;

        case StPlace:
            if (Actext == "bits 1")
            {
                SP_sralPort->setStopBits(QSerialPort::OneStop);
            }
            else if (Actext == "bits 1.5")
            {
                SP_sralPort->setStopBits(QSerialPort::OneAndHalfStop);
            }
            else
            {
                SP_sralPort->setStopBits(QSerialPort::TwoStop);
            }
            SP_stplaceBut->setText(Actext);
            RdoMap_Serial["SQL_SRLP_STPL"] = QString("StopPlace = '%1'").arg(Actext);
            break;

        case Scontrol:
            if (Actext == "硬件控制")
            {
                SP_sralPort->setFlowControl(QSerialPort::HardwareControl);
            }
            else if (Actext == "软件控制")
            {
                SP_sralPort->setFlowControl(QSerialPort::SoftwareControl);
            }
            else
            {
                SP_sralPort->setFlowControl(QSerialPort::NoFlowControl);
            }
            SP_scontrolBut->setText(Actext);
            RdoMap_Serial["SQL_SRLP_SCTL"] = QString("SControl = '%1'").arg(Actext);
            break;

       case CheckPlace:
            if (Actext == "奇校验")
            {
                SP_sralPort->setParity(QSerialPort::OddParity);
            }
            else if (Actext == "偶校验")
            {
                SP_sralPort->setParity(QSerialPort::EvenParity);
            }
            else
            {
                SP_sralPort->setParity(QSerialPort::NoParity);
            }
            SP_ckplaceBut->setText(Actext);
            RdoMap_Serial["SQL_SRLP_PRTY"] = QString("CheckPlace = '%1'").arg(Actext);
            break;

        case SerialPort:
            QString portName = RdoMap_Serial[Actext];
            QFontMetrics portNameMetrics(SP_usbPortMenu->font());
            qDebug() << portNameMetrics.horizontalAdvance(portName) << SP_usbportBut->width();
            if (portNameMetrics.horizontalAdvance(Actext) <= SP_usbportBut->width())
            {
                SP_usbportBut->setText(Actext);
            }
            else
            {
                SP_usbportBut->setText(portName);
            }
            QSerialPortInfo SP_sralPortInfo(portName);
            SP_sralPort->setPort(SP_sralPortInfo);
            break;
    }
}

可以看到,代码中设置了 比特率、数据位、停止位、校验位、流控制以及串口名

其中串口名在最初切换到工具的时候已经获取了

    } else if ( RdoMap_Integer["ViewIndex"] == 3 ) {
        PBL_centraStackWidget->setCurrentWidget(SP_Widget);
        FL_fileaddBut->setVisible(false);
        TR_actionBut->setVisible(false);
        AS_assistBut->setVisible(false);
        VW_viewcutBut->setText("当前窗口-[串口工具]");
        DT_execBut->setText("连接");
        DT_scviewBut->setText("连接列表");
        DT_rsviewBut->setText("命令列表");
        QList<QSerialPortInfo> portInfoList = QSerialPortInfo::availablePorts();
        foreach(QSerialPortInfo port, portInfoList)
        {
            QString SerialInfo = port.description() + " " + port.portName();
            RdoMap_Serial[SerialInfo] = port.portName();
            SPActionList.append(new QAction(SerialInfo, SP_usbPortMenu));
        }
        SP_usbPortMenu->addActions(SPActionList);
        QStringList i = RdoMap_Serial.keys();
        SP_usbportBut->setText(i[0]);
        RdoMap_String["FunctionName"] = "SerialCTTools";
        SerialDelayCheckTimer->start();
        SP_setToolmenuActionAdjustSize(SP_usbportBut);
        SP_setToolmenuActionAdjustSize(SP_baudrateBut);
        SP_setToolmenuActionAdjustSize(SP_dtplaceBut);
        SP_setToolmenuActionAdjustSize(SP_stplaceBut);
        SP_setToolmenuActionAdjustSize(SP_ckplaceBut);
        SP_setToolmenuActionAdjustSize(SP_scontrolBut);

主要部分是QSerialPortInfo::availablePorts()列表中的 port.portName(),在后续的打开串口中就需要用到这个端口名了,我这里把 port.description() 加上了,因为这是个串口的简要描述,个人喜好而已,然后把拼凑的信息和原始的端口名放入字典中,

SPActionList.append(new QAction(SerialInfo, SP_usbPortMenu));  是为了后续更新串口的时候或者关闭程序的时候把 QAction 销毁掉,保险些,同时也是为了将选项加入菜单组件

SP_usbPortMenu->addActions(SPActionList);

后续选择串口的时候通过 RdoMap_Serial 字典就可以得到端口名了

SP_setToolmenuActionAdjustSize 函数是我自定义的函数,用来设置菜单宽的,因为发现直接使用样式固定死的话会导致要不就是太宽了,不好看,要不就是太窄了,展示不全,需要用菜单做组件的可以将就用着

void ToolWin::SP_setToolmenuActionAdjustSize(QToolButton *Button){
    QMenu *Menu = Button->menu();
    QList<QAction *> SelectionList = Menu->actions();
    QList<int> SelectionLenList;
    if (!SelectionList.isEmpty())
    {
        foreach(QAction *Actext, SelectionList)
        {
            QFontMetrics Metrics(Menu->font());
            SelectionLenList.append(Metrics.horizontalAdvance(Actext->text()));
        }
        int maxTextSize = EXD.Max(SelectionLenList);
        int buttonSize = Button->width();
        if (maxTextSize > buttonSize)
        {
            Menu->setFixedWidth(maxTextSize);
        }
        else
        {
            Menu->setFixedWidth(buttonSize);
        }
    }
}

看情况如果不是用的QToolButton 组件可以把参数改为QMenu就行了

EXD.Max(SelectionLenList); 比较简单

int Extend::Max(QList<int> _T){
    int CS = _T.first();
    foreach(int ele, _T){if (ele > CS) CS = ele;}
    return CS;
}

根据所选项获取对应的保存好的端口名,设置端口,我这里不想显示文字太长了把组件拉长很难看,所以判断了下

打开端口,我这里包含了数据库部分的,主要是前面的open:

void ToolLogicCT::SP_serialConnect(){
    LogNbase7Send("-----start-----", LogType::Debug)
    if (!RdoMap_Switch[KEY_ATTRIBUTE.UPD_SERIAL_STATE])
    {
        if (SP_sralPort->open(QIODevice::ReadWrite))
        {
            SP_connectBut->setText("连接成功");
            RdoMap_Switch[KEY_ATTRIBUTE.UPD_SERIAL_STATE] = true;
            if (!RdoMap_SerialSql["NikeName"].isEmpty())
            {
                QString NikeName = RdoMap_SerialSql["NikeName"][RdoMap_Integer["serialSqlIndex"]];
                if (!NikeName.isEmpty())
                {
                    Query->exec(QString("UPDATE SPINFO SET Apply=%1 WHERE NikeName!='%2'").arg(
                                QString::number(false), NikeName));
                    Query->exec(QString("UPDATE SPINFO SET Apply=%1 WHERE NikeName='%2'").arg(
                                QString::number(true), NikeName));
                }
            }
        }
        else
        {
            SP_connectBut->setText("连接失败");
            RdoMap_Switch[KEY_ATTRIBUTE.UPD_SERIAL_STATE] = false;
            SpcnetDelayRcvTimer.start();
        }
    }
    else
    {
        SP_sralPort->close();
        SP_connectBut->setText("连接断开");
        RdoMap_Switch[KEY_ATTRIBUTE.UPD_SERIAL_STATE] = false;
        SpcnetDelayRcvTimer.start();

    }
}

这时候需要把串口数据获取并显示到文本框中,所以需要连接信号槽,获取到串口信息并给它加上时间,获取串口信息时经常会碰到一个完整字符串会分开两次输出的情况,因此以下代码针对该情况做了对应的解决,焦点跟随代码则写在了自定义的文本框组件中了,获取部分就写好了。

connect(SP_sralPort, &QSerialPort::readyRead, this, &SignalTool::SP_FollowScEdit);




void ToolLogicCT::SP_FollowScEdit(){
    QString DateTimeFormat = "hh:mm:ss";
    QString FORMATDATE = QDateTime::currentDateTime().toString(DateTimeFormat);
    QString TimeStemp = QString("[%1]%2");
    QString readContent = SP_sralPort->readAll();
    QTextCodec *textCode = QTextCodec::codecForName("TSCII");
    //#优化字符拼接断续的问题
    if (!readContent.simplified().isEmpty())
    {
        //# 字符中间换行标识 isCentraWordSwap 与末尾换行标识 isEndWordSwap
        bool isCentraWordSwap = QRegularExpression("\r|\n").match(readContent.trimmed()).capturedTexts().isEmpty();
        bool isEndWordSwap = QRegularExpression("[\n|\r]$").match(readContent).capturedTexts().isEmpty();
        //# 如果字符串中间不存在换行操作
        if (isCentraWordSwap)
        {
            //#并且上一个字符串不存在末尾换行。则正常拼接字符串,保证其完整性
            if (RdoMap_Switch["isEndWordSwap"])
            {
                SP_serialInfoEdit->insertPlainText(textCode->fromUnicode(readContent));
            }
            //#如果上一个字符串存在末尾换行,即当前行为新的起始行,则添加时间戳
            else
            {
                SP_serialInfoEdit->insertPlainText(TimeStemp.arg(FORMATDATE, "  ") + textCode->fromUnicode(readContent));
            }
        }
        //#如果字符串存在中间换行操作,即该字符串为较长字符串
        else
        {
            //#如果字符串不存在末尾换行 并且 isEndWordSwap KEY 存在于字典中,即已经存在过赋值操作,则正常拼接字符串,保证其完整性
            if (isEndWordSwap && RdoMap_Switch.contains("isEndWordSwap"))
            {
                SP_serialInfoEdit->insertPlainText(textCode->fromUnicode(readContent));
            }
            //#如果存在末尾换行
            else
            {
                //#如果上一个字符串不存在末尾换行,则正常拼接字符串,保证其完整性
                if (RdoMap_Switch["isEndWordSwap"])
                {
                    SP_serialInfoEdit->insertPlainText(textCode->fromUnicode(readContent));
                }
                //#否则添加时间戳明显和标识,并在末尾增加换行以方便区分较长字符串
                else
                {
                    SP_serialInfoEdit->insertPlainText(TimeStemp.arg(FORMATDATE, " ⬇⬇⬇⬇⬇\n") + textCode->fromUnicode(readContent) + "\n");
                }
            }
        }
        //# 如果文本不为空,再进行末尾换行标识的字典赋值,否则为空一般为\R\N字符,影响实际判断,导致结果不正确
        if (!readContent.simplified().isEmpty()) RdoMap_Switch["isEndWordSwap"] = isEndWordSwap;
    }
}

顺便放一下文本框组件的代码吧,该文本框加了默认文本跟随,滚轮上滑则取消跟随,滚轮滚至文本框最底部或按ENTER键则恢复跟随,看数据比较方便些,以及按住ctrl键 + 鼠标滚轮调整字体大小,其他拖拽部分的代码不理它删掉就行了

class NTextEdit : public QTextEdit{

    Q_OBJECT

public:

    NTextEdit(QString ObjectName,
                QWidget *parent = nullptr);

    void insertPlainText(const QString &Text);


    void dragEnterEvent(QDragEnterEvent *Event);


    void dropEvent(QDropEvent *Event);


    void dragLeaveEvent(QDragLeaveEvent *Event);


    void mouseReleaseEvent(QMouseEvent *Event);


    void setRGLRLMAP(QMap<QString, QMap<QString, QString>> &_RGLRLSMAP_);


    void setWheelFontBlock(int block);


    void wheelEvent(QWheelEvent *Event);


    void keyPressEvent(QKeyEvent *Event);


    void keyReleaseEvent(QKeyEvent *Event);

private:
    Extend EXD;
    QMap<QString, QMap<QString, int>> RdoMap_Integer;
    QMap<QString, QMap<QString, bool>> RdoMap_Switch;
    QMap<QString, QMap<QString, QString>> *RGLRLSMAP;

signals:
    void SourceDropEvent(pair<bool, QStringList>);
    void MouseClickEvent(bool);
    void MouseWheelEvent(int);
};



cpp文件
NTextEdit::NTextEdit(QString ObjectName,
                     QWidget *parent){
    RdoMap_Integer[ObjectName]["Size-W"] = this->size().width();
    RdoMap_Integer[ObjectName]["Size-H"] = this->size().height();
    RdoMap_Switch[ObjectName].insert("FollowCursor", true);
    RdoMap_Integer[ObjectName].insert("VerticalScrollValue", 0);
    setObjectName(ObjectName);
    setUndoRedoEnabled(false);
    setOverwriteMode(false);
    setTabChangesFocus(false);
    setParent(parent);
}


void NTextEdit::insertPlainText(const QString &Text){
    QTextEdit::insertPlainText(Text);
    if (RdoMap_Switch[objectName()]["FollowCursor"])
    {
        QTextCursor Cursor = textCursor();
        Cursor.movePosition(QTextCursor::End);
        setTextCursor(Cursor);
    }
}


void NTextEdit::dragEnterEvent(QDragEnterEvent *Event){
    if (!Event->mimeData()->text().isEmpty()){
         //重要的一行代码,与hastext相关联,是显示文件接受图标是否正常的标志,但对实际操无影响
         Event->accept();
     } else {
         Event->ignore();
    }
}


void NTextEdit::dropEvent(QDropEvent *Event){
    QString AbsforSuffix;
    QString AbsPreviousSuffix;
    if (!(*RGLRLSMAP)["REGEXP"]["AbsforSuffix"].isEmpty() &&
        !(*RGLRLSMAP)["REGEXP"]["AbsPreviousSuffix"].isEmpty())
    {
        AbsforSuffix = (*RGLRLSMAP)["REGEXP"]["AbsforSuffix"].arg(6);
        AbsPreviousSuffix = (*RGLRLSMAP)["REGEXP"]["AbsPreviousSuffix"];
    }
    else
    {
        AbsforSuffix = "[a-zA-Z]\\s*:\\s*[\\|/].*?\\..{3,%1}";
        AbsPreviousSuffix = "[a-zA-Z]\\s*:\\s*[\\\\|/]";
    }
    QStringList DspsPath = EXD.ExtractPath(Event->mimeData()->text(),
                                           AbsforSuffix.arg(6),
                                           AbsPreviousSuffix);
    emit SourceDropEvent(make_pair(true, DspsPath));
}


void NTextEdit::dragLeaveEvent(QDragLeaveEvent*){
    emit SourceDropEvent(make_pair(false, QStringList()));
}


void NTextEdit::mouseReleaseEvent(QMouseEvent*){
    emit MouseClickEvent(true);
}


void NTextEdit::setRGLRLMAP(QMap<QString, QMap<QString, QString>> &_RGLRLSMAP_){
    if (!_RGLRLSMAP_["REGEXP"]["AbsforSuffix"].isEmpty() &&
        !_RGLRLSMAP_["REGEXP"]["AbsPreviousSuffix"].isEmpty())
    {
        RGLRLSMAP = &_RGLRLSMAP_;
    }
}


void NTextEdit::setWheelFontBlock(int block){
    RdoMap_Integer[objectName()]["FontBlock"] = block;
}


void NTextEdit::wheelEvent(QWheelEvent *Event){
    if (Event->angleDelta().y() > 0)
    {
        RdoMap_Switch[objectName()]["FollowCursor"] = false;
        if (RdoMap_Switch[objectName()]["Ctrl-Enter"])
        {
            QFont curFont(font());
            int fontSize = curFont.pointSize();
            if (fontSize <=RdoMap_Integer[objectName()]["FontBlock"]) curFont.setPointSize(fontSize + 1);
            setFont(curFont);
        }
    }
    else
    {
        if (RdoMap_Switch[objectName()]["Ctrl-Enter"])
        {
            QFont curFont(font());
            if (curFont.pointSize() > 0) curFont.setPointSize(curFont.pointSize() - 1);
            setFont(curFont);
        }
        if (verticalScrollBar()->sliderPosition() == verticalScrollBar()->maximum())
        {
            QTextCursor Cursor = textCursor();
            Cursor.movePosition(QTextCursor::End);
            setTextCursor(Cursor);
            RdoMap_Switch[objectName()]["FollowCursor"] = true;
        }
    }
    if (!RdoMap_Switch[objectName()]["Ctrl-Enter"]) QTextEdit::wheelEvent(Event);
}


void NTextEdit::keyPressEvent(QKeyEvent *Event){
    //#Enter Key
   if(QList<int>({16777220, 16777221}).contains(Event->key()) ||
      Event->text() == "\r")
    {
        QTextCursor Cursor = textCursor();
        Cursor.movePosition(QTextCursor::End);
        setTextCursor(Cursor);
        RdoMap_Switch[objectName()]["FollowCursor"] = true;
    }
    else if (Event->key() == 16777249)
    {
        RdoMap_Switch[objectName()]["Ctrl-Enter"] = true;
    }
    QTextEdit::keyPressEvent(Event);
}


void NTextEdit::keyReleaseEvent(QKeyEvent *Event){
    //# CTRL Key
    if (Event->key() == 16777249)
    {
        RdoMap_Switch[objectName()]["Ctrl-Enter"] = false;
    }
    QTextEdit::keyReleaseEvent(Event);
}


接下来是发送信息部分,发送串口数据,比如命令往往是需要 加回车换行的

而write函数中是没有这部分代码的,仅仅是发送。因此,需要设备收到命令并执行的话还需要加上回车换行,我的代码包含文本框命令发送和列表命令发送,所以多了个标识,以isEditSend为True来看就好了,代码:

void ToolLogicCT::SP_commandSend(bool isEditSend){
    LogNbase7Send("-----start-----", LogType::Debug)
    QStringList commandCodeList;
    if (isEditSend)
    {
        commandCodeList = SP_commandEdit->text().split("->");
    }
    else
    {
        if (RdoMap_ToolType[KEY_ATTRIBUTE.CUT_EXBUTCHANGE] == NT::CUT_COMMANDLIST)
        {
            commandCodeList.append(RdoMap_String[KEY_ATTRIBUTE.UPD_ODLIST_ITEMS].split("&&"));
        }
    }
    SP_sralPort->clear();
    foreach(QString commandCode, commandCodeList)
    {
        QByteArray btcommandCode = commandCode.trimmed().toLocal8Bit();
        if (SP_newlineCheckBox->isChecked()) btcommandCode.append("\r\n");
        qint64 exec = SP_sralPort->write(btcommandCode);
        if (exec >= 0)
        {
            SP_sralPort->flush();
            SP_sralPort->waitForBytesWritten(10);
        }
    }
}

基本功能就是这样了,并不复杂,其他一些功能怎么方便怎么加就好了,有兴趣可以把连接或者命令数据写入数据库,这样工具更好用些,我个人代码爱好者,偶尔敲着玩,欢迎评论区讨论
 

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值