【QT用户登录与界面跳转】
【QT用户登录与界面跳转】
- 1.前言
- 2. 项目设置
- 3.设计登录界面
- 3.1 login.pro参数
- 3.2 界面设置
- 3.2.1 登录界面
- 3.2.2 串口主界面
- 4. 实现登录逻辑
- 5.串口界面
- 6.测试功能
- 7.总结
1.前言
在Qt应用程序开发中,实现用户登录及界面跳转功能是构建交互式应用的重要步骤之一。下面将介绍如何使用Qt框架来创建一个简单的用户登录界面,并根据用户的输入信息进行验证,然后跳转到相应的【QT串口助手】主界面。
源码地址:
2. 项目设置
首先,确保你的开发环境中已安装了Qt及其相关工具(如Qt Creator),前期也安装过QT(参考博客:【Qt安装与简易串口控制Arduino开发板小灯教程】)。本文记录一下用QT Creator 写一个用户登录与界面串口助手的过程,整个工程只有几百行代码,跟着做下来对新手来说可以更快了解整个QT项目的开发过程和一些常用控件的使用方法。最好每个功能自己都试试增加自信心!
💕💕💕
先来看看作品:

3.设计登录界面
3.1 login.pro参数
- 设置login.pro参数,导入core gui serialport库
QT += core gui serialportgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0SOURCES += \main.cpp \mainwindow.cpp \serial.cppHEADERS += \mainwindow.h \serial.hFORMS += \mainwindow.ui \serial.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += targetRESOURCES += \source.qrc
3.2 界面设置
界面设置分为登录界面和串口主界面
3.2.1 登录界面

这个登录界面是为智能船舶自主航行系统设计的,提供了简洁而功能齐全的用户登录体验。界面顶部展示有系统名称,明确了这是进入系统的入口。用户需要输入账号和密码来验证身份,其中密码输入框支持显示或隐藏密码的功能以增强使用便捷性。此外,提供了一个“记住账号密码”的选项,方便用户的下次登录。整个背景采用了半透明处理的船舶图像,既美化了界面也强化了品牌形象,使得登录过程更加直观友好。底部还设有一个“忘记密码”链接,为用户提供了找回密码的途径。整体设计注重用户体验,确保了安全性和易用性的平衡。
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>MainWindow</class><widget class="QMainWindow" name="MainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>501</width><height>403</height></rect></property><property name="windowTitle"><string>MainWindow</string></property><widget class="QWidget" name="centralwidget"><widget class="QFrame" name="frame"><property name="geometry"><rect><x>30</x><y>20</y><width>431</width><height>351</height></rect></property><property name="frameShape"><enum>QFrame::StyledPanel</enum></property><property name="frameShadow"><enum>QFrame::Raised</enum></property><widget class="QGroupBox" name="groupBox"><property name="geometry"><rect><x>20</x><y>20</y><width>391</width><height>311</height></rect></property><property name="font"><font><pointsize>14</pointsize></font></property><property name="title"><string>智能船舶自主航行系统软件登录</string></property><widget class="QPushButton" name="pushButton"><property name="geometry"><rect><x>100</x><y>260</y><width>161</width><height>41</height></rect></property><property name="font"><font><pointsize>20</pointsize></font></property><property name="text"><string>登录</string></property></widget><widget class="QCheckBox" name="checkBox"><property name="geometry"><rect><x>80</x><y>230</y><width>121</width><height>21</height></rect></property><property name="font"><font><pointsize>11</pointsize></font></property><property name="text"><string>记住账号密码</string></property></widget><widget class="QCommandLinkButton" name="commandLinkButton"><property name="geometry"><rect><x>220</x><y>220</y><width>101</width><height>41</height></rect></property><property name="font"><font><family>Segoe UI</family><pointsize>11</pointsize></font></property><property name="text"><string>忘记密码</string></property></widget><widget class="QLineEdit" name="accout"><property name="geometry"><rect><x>100</x><y>90</y><width>201</width><height>31</height></rect></property></widget><widget class="QLineEdit" name="password"><property name="geometry"><rect><x>100</x><y>150</y><width>201</width><height>31</height></rect></property></widget><widget class="QLabel" name="label"><property name="geometry"><rect><x>40</x><y>90</y><width>71</width><height>31</height></rect></property><property name="font"><font><family>华文中宋</family><pointsize>14</pointsize></font></property><property name="text"><string>账号:</string></property></widget><widget class="QLabel" name="label_2"><property name="geometry"><rect><x>40</x><y>150</y><width>71</width><height>31</height></rect></property><property name="font"><font><family>华文中宋</family><pointsize>14</pointsize></font></property><property name="text"><string>密码:</string></property></widget><widget class="QRadioButton" name="radioButton"><property name="geometry"><rect><x>310</x><y>155</y><width>81</width><height>21</height></rect></property><property name="text"><string>显示</string></property></widget></widget></widget></widget></widget><resources/><connections/>
</ui>
3.2.2 串口主界面

该串口工具界面设计用于简化与串行设备的通信过程,设计过程参考【QT串口助手】,提供直观的操作体验。界面主要分为几个关键部分:
- 串口配置区域:用户可以在此选择和配置串口参数,包括端口号、波特率、数据位、校验位以及停止位,以确保与目标设备正确匹配。
- 操作控制按钮:包含检测串口、打开/关闭串口等按钮,便于用户快速操作串口连接状态。
- 接收设置选项:允许用户根据需求调整接收数据的方式,如启用Hex显示模式、添加时间戳以及自动换行功能,方便查看接收到的数据。
- 发送设置选项:提供Hex发送模式及发送后自动换行的功能,同时支持设定自动发送间隔时间,适合需要周期性发送数据的应用场景。
- 数据交互区:分为发送数据区和接收数据显示区,前者让用户输入要发送到串口的数据,后者实时展示从串口接收到的信息,两者均配备了清空内容的快捷按钮,提升用户体验。
整体而言,此串口界面旨在为用户提供一个高效且易于使用的平台,以便于进行串口通信调试和管理,满足不同应用场景下的串口操作需求。
serial.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>Serial</class><widget class="QMainWindow" name="Serial"><property name="geometry"><rect><x>0</x><y>0</y><width>578</width><height>527</height></rect></property><property name="windowTitle"><string>MainWindow</string></property><widget class="QWidget" name="centralwidget"><widget class="QGroupBox" name="groupBox_4"><property name="geometry"><rect><x>200</x><y>10</y><width>351</width><height>481</height></rect></property><property name="title"><string>数据交互</string></property><widget class="QWidget" name="formLayoutWidget"><property name="geometry"><rect><x>0</x><y>20</y><width>341</width><height>451</height></rect></property><layout class="QFormLayout" name="formLayout"><item row="0" column="0"><widget class="QLabel" name="label_2"><property name="text"><string>发送数据</string></property></widget></item><item row="1" column="0" colspan="2"><widget class="QTextEdit" name="textEdit_send"/></item><item row="2" column="0"><widget class="QLabel" name="label"><property name="text"><string>接收数据</string></property></widget></item><item row="3" column="0" colspan="2"><widget class="QTextEdit" name="textEdit_recv"><property name="readOnly"><bool>true</bool></property></widget></item><item row="4" column="0" colspan="2"><layout class="QHBoxLayout" name="horizontalLayout_2"><item><spacer name="horizontalSpacer"><property name="orientation"><enum>Qt::Horizontal</enum></property><property name="sizeHint" stdset="0"><size><width>40</width><height>20</height></size></property></spacer></item><item><widget class="QPushButton" name="send_Bt"><property name="text"><string>发送数据</string></property></widget></item><item><spacer name="horizontalSpacer_2"><property name="orientation"><enum>Qt::Horizontal</enum></property><property name="sizeHint" stdset="0"><size><width>40</width><height>20</height></size></property></spacer></item><item><widget class="QPushButton" name="clear_send_Bt"><property name="text"><string>清空发送区</string></property></widget></item><item><spacer name="horizontalSpacer_4"><property name="orientation"><enum>Qt::Horizontal</enum></property><property name="sizeHint" stdset="0"><size><width>40</width><height>20</height></size></property></spacer></item></layout></item></layout></widget></widget><widget class="QGroupBox" name="groupBox"><property name="geometry"><rect><x>10</x><y>10</y><width>191</width><height>311</height></rect></property><property name="title"><string>串口配置</string></property><widget class="QWidget" name="gridLayoutWidget_2"><property name="geometry"><rect><x>10</x><y>20</y><width>169</width><height>281</height></rect></property><layout class="QGridLayout" name="gridLayout_2"><item row="1" column="0"><spacer name="verticalSpacer"><property name="orientation"><enum>Qt::Vertical</enum></property><property name="sizeHint" stdset="0"><size><width>20</width><height>40</height></size></property></spacer></item><item row="2" column="0"><widget class="QPushButton" name="Serial_check_Bt"><property name="minimumSize"><size><width>93</width><height>28</height></size></property><property name="text"><string>检测串口</string></property></widget></item><item row="3" column="0"><widget class="QPushButton" name="open_serial_Bt"><property name="minimumSize"><size><width>93</width><height>28</height></size></property><property name="text"><string>打开串口</string></property></widget></item><item row="0" column="0"><layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0" columnstretch="0,0"><property name="sizeConstraint"><enum>QLayout::SetDefaultConstraint</enum></property><property name="leftMargin"><number>0</number></property><property name="topMargin"><number>0</number></property><property name="rightMargin"><number>0</number></property><property name="bottomMargin"><number>0</number></property><property name="horizontalSpacing"><number>6</number></property><property name="verticalSpacing"><number>0</number></property><item row="3" column="0"><widget class="QLabel" name="label_databit"><property name="minimumSize"><size><width>72</width><height>30</height></size></property><property name="maximumSize"><size><width>76</width><height>30</height></size></property><property name="text"><string>数据位:</string></property></widget></item><item row="4" column="0"><widget class="QLabel" name="label_parity"><property name="minimumSize"><size><width>72</width><height>30</height></size></property><property name="maximumSize"><size><width>76</width><height>30</height></size></property><property name="text"><string>校验位:</string></property></widget></item><item row="1" column="1"><widget class="QComboBox" name="serial_Cb"><property name="minimumSize"><size><width>87</width><height>22</height></size></property><property name="maximumSize"><size><width>76</width><height>15</height></size></property></widget></item><item row="5" column="0"><widget class="QLabel" name="label_stopbit"><property name="minimumSize"><size><width>72</width><height>30</height></size></property><property name="maximumSize"><size><width>76</width><height>30</height></size></property><property name="text"><string>停止位:</string></property></widget></item><item row="5" column="1"><widget class="QComboBox" name="stopbit_Cb"><property name="minimumSize"><size><width>87</width><height>22</height></size></property><property name="maximumSize"><size><width>76</width><height>15</height></size></property><item><property name="text"><string>none</string></property></item><item><property name="text"><string>奇校验</string></property></item><item><property name="text"><string>偶校验</string></property></item></widget></item><item row="4" column="1"><widget class="QComboBox" name="checkbit_Cb"><property name="minimumSize"><size><width>87</width><height>22</height></size></property><property name="maximumSize"><size><width>76</width><height>15</height></size></property><item><property name="text"><string>1</string></property></item><item><property name="text"><string>1.5</string></property></item><item><property name="text"><string>2</string></property></item></widget></item><item row="2" column="1"><widget class="QComboBox" name="baundrate_Cb"><property name="minimumSize"><size><width>87</width><height>22</height></size></property><property name="maximumSize"><size><width>76</width><height>15</height></size></property><property name="currentText"><string>9600</string></property><property name="currentIndex"><number>3</number></property><item><property name="text"><string>1200</string></property></item><item><property name="text"><string>2400</string></property></item><item><property name="text"><string>4800</string></property></item><item><property name="text"><string>9600</string></property></item><item><property name="text"><string>19200</string></property></item><item><property name="text"><string>38400</string></property></item><item><property name="text"><string>57600</string></property></item><item><property name="text"><string>115200</string></property></item></widget></item><item row="1" column="0"><widget class="QLabel" name="label_serialport"><property name="minimumSize"><size><width>72</width><height>30</height></size></property><property name="maximumSize"><size><width>76</width><height>30</height></size></property><property name="text"><string>端口号:</string></property></widget></item><item row="2" column="0"><widget class="QLabel" name="label_baudrate"><property name="minimumSize"><size><width>72</width><height>30</height></size></property><property name="maximumSize"><size><width>76</width><height>30</height></size></property><property name="text"><string>波特率:</string></property></widget></item><item row="3" column="1"><widget class="QComboBox" name="databit_Cb"><property name="minimumSize"><size><width>87</width><height>22</height></size></property><property name="maximumSize"><size><width>76</width><height>15</height></size></property><property name="currentText"><string>8</string></property><item><property name="text"><string>8</string></property></item><item><property name="text"><string>7</string></property></item><item><property name="text"><string>6</string></property></item><item><property name="text"><string>5</string></property></item></widget></item></layout></item></layout></widget></widget><widget class="QGroupBox" name="groupBox_2"><property name="geometry"><rect><x>10</x><y>330</y><width>191</width><height>81</height></rect></property><property name="title"><string>接收设置</string></property><widget class="QWidget" name="formLayoutWidget_2"><property name="geometry"><rect><x>10</x><y>20</y><width>189</width><height>56</height></rect></property><layout class="QFormLayout" name="formLayout_2"><item row="0" column="0"><widget class="QPushButton" name="clear_recv_Bt"><property name="text"><string>清空接收</string></property></widget></item><item row="0" column="1"><widget class="QCheckBox" name="recv_hex_Chb"><property name="text"><string>Hex接收</string></property></widget></item><item row="1" column="0"><widget class="QCheckBox" name="recv_time_Chb"><property name="text"><string>时间戳</string></property></widget></item><item row="1" column="1"><widget class="QCheckBox" name="recv_autoline_Chb"><property name="text"><string>自动换行</string></property></widget></item></layout></widget></widget><widget class="QGroupBox" name="groupBox_3"><property name="geometry"><rect><x>10</x><y>420</y><width>191</width><height>71</height></rect></property><property name="title"><string>发送设置</string></property><widget class="QWidget" name="layoutWidget"><property name="geometry"><rect><x>10</x><y>20</y><width>183</width><height>49</height></rect></property><layout class="QGridLayout" name="gridLayout_5"><item row="0" column="0"><widget class="QCheckBox" name="send_hex_Chb"><property name="text"><string>Hex发送</string></property></widget></item><item row="0" column="1" colspan="2"><widget class="QCheckBox" name="send_line_Chb"><property name="text"><string>发送新行</string></property></widget></item><item row="1" column="0"><widget class="QCheckBox" name="autosend_Chb"><property name="text"><string>自动发送</string></property></widget></item><item row="1" column="1"><widget class="QSpinBox" name="txtSendMs"><property name="minimumSize"><size><width>60</width><height>0</height></size></property><property name="readOnly"><bool>false</bool></property></widget></item><item row="1" column="2"><widget class="QLabel" name="label_3"><property name="text"><string>ms</string></property></widget></item></layout></widget></widget></widget><widget class="QStatusBar" name="statusbar"/><widget class="QMenuBar" name="menuBar"><property name="geometry"><rect><x>0</x><y>0</y><width>578</width><height>23</height></rect></property><widget class="QMenu" name="menu"><property name="title"><string>串口工具</string></property></widget><widget class="QMenu" name="menuTCP"><property name="title"><string>TCP工具</string></property></widget><widget class="QMenu" name="menuUDP"><property name="title"><string>UDP工具</string></property></widget><widget class="QMenu" name="menuCAN"><property name="title"><string>CAN工具</string></property></widget><widget class="QMenu" name="menu_2"><property name="title"><string>画图工具</string></property></widget><addaction name="menu"/><addaction name="menuTCP"/><addaction name="menuUDP"/><addaction name="menuCAN"/><addaction name="menu_2"/></widget></widget><resources/><connections/>
</ui>
4. 实现登录逻辑
main.cpp主程序进入界面
#include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
在对应的mainwindow.cpp文件中实现登录逻辑:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "serial.h"
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), settings(new QSettings("YourCompany", "YourApp")), ui(new Ui::MainWindow)
{ui->setupUi(this);// 设置背景图片QFile file(":/ship.png"); // 如果使用资源系统,请根据实际情况调整路径if(file.exists()) {this->setStyleSheet("MainWindow { background-image: url(:/ship.png)};");} else{qDebug() << "Background image not found!";}//隐匿密码ui->password->setEchoMode(QLineEdit::Password);//登录按钮connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::login);//按钮传参显示密码按钮connect(ui->radioButton, &QPushButton::clicked, this, &MainWindow::display_psd);// 记住密码复选框connect(ui->checkBox, &QCheckBox::stateChanged, this, &MainWindow::saveSettings);loadSettings();
}MainWindow::~MainWindow()
{delete ui;delete settings;
}void MainWindow::login()
{saveSettings();QString nameString = ui->accout->text();QString pswdString = ui->password->text();// 检查用户名和密码是否匹配if ((nameString == QString::fromLocal8Bit("admin") && pswdString == QString::fromLocal8Bit("123456")) ||(nameString == QString::fromLocal8Bit("user") && pswdString == QString::fromLocal8Bit("111111"))) {Serial* w = new Serial(); // 使用 'this' 作为父对象,Qt 会自动管理其生命周期qDebug() << "Creating Software instance.";this->close();w->show();} else{QMessageBox::about(this, "警告", "用户名或密码错误");}
}void MainWindow::display_psd(bool checked)
{if (checked) {//显示密码ui->password->setEchoMode(QLineEdit::Normal);}else {//密文显示ui->password->setEchoMode(QLineEdit::Password);}
}void MainWindow::saveSettings()
{bool remember = ui->checkBox->isChecked();QString username = ui->accout->text();QString password = ui->password->text();settings->setValue("remember", remember);if (remember) {settings->setValue("username", username);settings->setValue("password", password);} else {settings->remove("username");settings->remove("password");}
}
void MainWindow::loadSettings()
{bool remember = settings->value("remember", false).toBool();QString username = settings->value("username", "").toString();QString password = settings->value("password", "").toString();ui->checkBox->setChecked(remember);ui->accout->setText(username);ui->password->setText(password);
}
这段代码实现了一个简单的登录窗口,具备记住密码、显示/隐藏密码和基本的用户验证功能。以下是各部分的功能概述:
-
构造函数
MainWindow::MainWindow:- 初始化主窗口,设置背景图片(如果存在),并初始化一些UI元素。
- 为密码输入框设置密码模式(即隐藏输入字符)。
- 连接按钮和复选框到相应的槽函数,以便处理用户的交互操作。
- 调用
loadSettings()函数加载上次保存的设置。
-
析构函数
MainWindow::~MainWindow:- 清理资源,包括删除UI对象和设置对象。
-
login函数:- 验证用户名和密码是否正确。如果匹配,则关闭当前登录窗口,并打开一个新的
Serial窗口。 - 如果不匹配,弹出一个警告消息框提示用户名或密码错误。
- 验证用户名和密码是否正确。如果匹配,则关闭当前登录窗口,并打开一个新的
-
display_psd函数:- 根据复选框的状态切换密码输入框的显示模式:如果选中则显示密码文本,否则隐藏(以圆点形式显示)。
-
saveSettings和loadSettings函数:saveSettings:根据复选框状态决定是否保存用户名和密码。如果用户选择了“记住密码”,则将这些信息保存到应用设置中;否则,从设置中移除这些信息。loadSettings:在启动时读取保存的设置,并根据这些设置更新UI组件(例如,自动填写用户名和密码,以及勾选“记住密码”复选框)。
整体来说,这段代码主要实现了以下功能:
- 提供了一个图形界面用于用户登录。
- 支持记住用户凭据的功能,方便用户下次登录。
- 提供了显示/隐藏密码选项,增加了用户体验。
- 在验证用户身份后,可以跳转到另一个应用界面(
Serial窗口)。
请注意,直接存储密码的做法存在安全风险,在实际应用中应采用更安全的方式处理用户认证信息。
mainwindow.h预定义槽函数,导入QT相关的库
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QMessageBox>
#include <QSettings>
#include <QFile>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();QSettings *settings;private slots:void login();void saveSettings();void loadSettings();void display_psd(bool checked);private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
5.串口界面
serial.h预定义串口相关功能函数,导入串口的库文件
#ifndef SERIAL_H
#define SERIAL_H#include <QMainWindow>
#include <QSerialPort>
#include <QString>
#include <QSerialPortInfo>
#include <QMessageBox>
#include <QTimer>
#include <QTime>
#include <QPainter>
#include <QDebug>
namespace Ui {
class Serial;
}class Serial : public QMainWindow
{Q_OBJECTpublic:explicit Serial(QWidget *parent = nullptr);~Serial();QSerialPort *serialPort;//定义串口指针private slots:// void on_button_openserial_clicked();/*手动连接槽函数*/void manual_serialPortReadyRead();void on_chkTimSend_stateChanged(int arg1);/*以下为mainwindow.ui文件中点击“转到槽”自动生成的函数*/void on_Serial_check_Bt_clicked();void on_open_serial_Bt_clicked();void on_send_Bt_clicked();void on_clear_recv_Bt_clicked();void on_clear_send_Bt_clicked();
private:Ui::Serial *ui;// 发送、接收字节计数long sendNum, recvNum;QLabel *lblSendNum;QLabel *lblRecvNum;QLabel *lblPortState;void setNumOnLabel(QLabel *lbl, QString strS, long num);// 定时发送-定时器QTimer *timSend;};#endif // SERIAL_H
serial.cpp实现定义串口相关功能函数
#include "serial.h"
#include "ui_serial.h"
#include "QSerialPortInfo"
#include <QSerialPort>
#include <QMessageBox>
#include <QDateTime>
#include <QStatusBar>
Serial::Serial(QWidget *parent) :QMainWindow(parent),ui(new Ui::Serial)
{ui->setupUi(this);QStringList serialNamePort;serialPort = new QSerialPort(this);connect(serialPort,SIGNAL(readyRead()),this,SLOT(manual_serialPortReadyRead()));/*手动连接槽函数*//*找出当前连接的串口并显示到serailCb*/on_Serial_check_Bt_clicked();// 发送、接收计数清零sendNum = 0;recvNum = 0;// 状态栏QStatusBar *sBar = statusBar();// 状态栏的收、发计数标签lblSendNum = new QLabel(this);lblRecvNum = new QLabel(this);lblPortState = new QLabel(this);lblPortState->setText("Connected");//设置串口状态标签为绿色 表示已连接状态lblPortState->setStyleSheet("color:red");// 设置标签最小大小lblSendNum->setMinimumSize(100, 20);lblRecvNum->setMinimumSize(100, 20);lblPortState->setMinimumSize(550, 20);setNumOnLabel(lblSendNum, "S: ", sendNum);setNumOnLabel(lblRecvNum, "R: ", recvNum);// 从右往左依次添加sBar->addPermanentWidget(lblPortState);sBar->addPermanentWidget(lblSendNum);sBar->addPermanentWidget(lblRecvNum);// 定时发送-定时器timSend = new QTimer;timSend->setInterval(1000);// 设置默认定时时长1000msconnect(timSend, &QTimer::timeout, this, [=](){on_send_Bt_clicked();});}Serial::~Serial()
{if(ui != nullptr){delete ui;delete serialPort;delete timSend;delete lblSendNum;delete lblRecvNum;delete lblPortState;}}void Serial::on_Serial_check_Bt_clicked()
{ui->serial_Cb->clear();//通过QSerialPortInfo查找可用串口foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){ui->serial_Cb->addItem(info.portName());}}void Serial::on_open_serial_Bt_clicked()
{/*串口初始化*/QSerialPort::BaudRate baudRate;QSerialPort::DataBits dataBits;QSerialPort::StopBits stopBits;QSerialPort::Parity checkBits;baudRate=QSerialPort::Baud9600;dataBits=QSerialPort::Data8;stopBits=QSerialPort::OneStop;checkBits = QSerialPort::NoParity;// 获取串口波特率// baudRate = ui->baundrate_Cb->currentText().toInt();直接字符串转换为 int 的方法if(ui->baundrate_Cb->currentText()=="1200")baudRate=QSerialPort::Baud1200;else if(ui->baundrate_Cb->currentText()=="2400")baudRate=QSerialPort::Baud2400;else if(ui->baundrate_Cb->currentText()=="4800")baudRate=QSerialPort::Baud4800;else if(ui->baundrate_Cb->currentText()=="9600")baudRate=QSerialPort::Baud9600;else if(ui->baundrate_Cb->currentText()=="19200")baudRate=QSerialPort::Baud19200;else if(ui->baundrate_Cb->currentText()=="38400")baudRate=QSerialPort::Baud38400;else if(ui->baundrate_Cb->currentText()=="57600")baudRate=QSerialPort::Baud57600;else if(ui->baundrate_Cb->currentText()=="115200")baudRate=QSerialPort::Baud115200;// 获取串口数据位if(ui->databit_Cb->currentText()=="5")dataBits=QSerialPort::Data5;else if(ui->databit_Cb->currentText()=="6")dataBits=QSerialPort::Data6;else if(ui->databit_Cb->currentText()=="7")dataBits=QSerialPort::Data7;else if(ui->databit_Cb->currentText()=="8")dataBits=QSerialPort::Data8;// 获取串口停止位if(ui->stopbit_Cb->currentText()=="1")stopBits=QSerialPort::OneStop;else if(ui->stopbit_Cb->currentText()=="1.5")stopBits=QSerialPort::OneAndHalfStop;else if(ui->stopbit_Cb->currentText()=="2")stopBits=QSerialPort::TwoStop;// 获取串口奇偶校验位if(ui->checkbit_Cb->currentText() == "none"){checkBits = QSerialPort::NoParity;}else if(ui->checkbit_Cb->currentText() == "奇校验"){checkBits = QSerialPort::OddParity;}else if(ui->checkbit_Cb->currentText() == "偶校验"){checkBits = QSerialPort::EvenParity;}// 初始化串口属性,设置 端口号、波特率、数据位、停止位、奇偶校验位数serialPort->setPortName(ui->serial_Cb->currentText());serialPort->setBaudRate(baudRate);serialPort->setDataBits(dataBits);serialPort->setStopBits(stopBits);serialPort->setParity(checkBits);// 根据初始化好的串口属性,打开串口// 如果打开成功,反转打开按钮显示和功能。打开失败,无变化,并且弹出错误对话框。if(ui->open_serial_Bt->text() == "打开串口"){if(serialPort->open(QIODevice::ReadWrite) == true){//QMessageBox::ui->open_serial_Bt->setText("关闭串口");// 让端口号下拉框不可选,避免误操作(选择功能不可用,控件背景为灰色)ui->serial_Cb->setEnabled(false);}else{QMessageBox::critical(this, "错误提示", "串口打开失败!!!\r\n该串口可能被占用\r\n请选择正确的串口");}//statusBar 状态栏显示端口状态QString sm = "%1 OPENED, %2, 8, NONE, 1";QString status = sm.arg(serialPort->portName()).arg(serialPort->baudRate());lblPortState->setText(status);lblPortState->setStyleSheet("color:green");}else{serialPort->close();ui->open_serial_Bt->setText("打开串口");// 端口号下拉框恢复可选,避免误操作ui->serial_Cb->setEnabled(true);//statusBar 状态栏显示端口状态QString sm = "%1 CLOSED";QString status = sm.arg(serialPort->portName());lblPortState->setText(status);lblPortState->setStyleSheet("color:red");}}void Serial::on_send_Bt_clicked()
{QByteArray array;//Hex复选框if(ui->send_hex_Chb->checkState() == Qt::Checked){//array = QString2Hex(data); //HEX 16进制array = QByteArray::fromHex(ui->textEdit_send->toPlainText().toUtf8()).data();}else{//array = data.toLatin1(); //ASCIIarray = ui->textEdit_send->toPlainText().toLocal8Bit().data();}if(ui->send_line_Chb->checkState() == Qt::Checked){array.append("\r\n");}// 如发送成功,会返回发送的字节长度。失败,返回-1。int a = serialPort->write(array);// 发送字节计数并显示if(a > 0){// 发送字节计数sendNum += a;// 状态栏显示计数值setNumOnLabel(lblSendNum, "S: ", sendNum);}
}void Serial::on_clear_recv_Bt_clicked()
{ui->textEdit_recv->clear();// 清除接收字节计数sendNum = 0;// 状态栏显示计数值setNumOnLabel(lblSendNum, "S: ", sendNum);
}void Serial::on_clear_send_Bt_clicked()
{ui->textEdit_send->clear();// 清除发送字节计数sendNum = 0;// 状态栏显示计数值setNumOnLabel(lblSendNum, "S: ", sendNum);
}// 定时发送开关 选择复选框
void Serial::on_chkTimSend_stateChanged(int arg1)
{// 获取复选框状态,未选为0,选中为2if(arg1 == 0){timSend->stop();// 时间输入框恢复可选ui->txtSendMs->setEnabled(true);}else{// 对输入的值做限幅,小于10ms会弹出对话框提示if(ui->txtSendMs->text().toInt() >= 10){timSend->start(ui->txtSendMs->text().toInt());// 设置定时时长,重新计数// 让时间输入框不可选,避免误操作(输入功能不可用,控件背景为灰色)ui->txtSendMs->setEnabled(false);}else{ui->autosend_Chb->setCheckState(Qt::Unchecked);QMessageBox::critical(this, "错误提示", "定时发送的最小间隔为 10ms\r\n请确保输入的值 >=10");}}
}/*手动实现接收数据函数*/
void Serial::manual_serialPortReadyRead()
{QByteArray recBuf = serialPort->readAll();QString str_rev;// 接收字节计数recvNum += recBuf.size();// 状态栏显示计数值setNumOnLabel(lblRecvNum, "R: ", recvNum);if(ui->recv_hex_Chb->checkState() == false){if(ui->recv_time_Chb->checkState() == Qt::Checked){QDateTime nowtime = QDateTime::currentDateTime();str_rev = "[" + nowtime.toString("yyyy-MM-dd hh:mm:ss") + "] ";str_rev += QString(recBuf).append("\r\n");}else{// 在当前位置插入文本,不会发生换行。如果没有移动光标到文件结尾,会导致文件超出当前界面显示范围,界面也不会向下滚动。//ui->recvEdit->appendPlainText(buf);if(ui->recv_autoline_Chb->checkState() == Qt::Checked){str_rev = QString(recBuf).append("\r\n");}else{str_rev = QString(recBuf);}}}else{// 16进制显示,并转换为大写QString str1 = recBuf.toHex().toUpper();//.data();// 添加空格QString str2;for(int i = 0; i<str1.length (); i+=2){str2 += str1.midRef (i,2);str2 += " ";}if(ui->recv_time_Chb->checkState() == Qt::Checked){QDateTime nowtime = QDateTime::currentDateTime();str_rev = "[" + nowtime.toString("yyyy-MM-dd hh:mm:ss") + "] ";str_rev += str2.append("\r\n");}else{if(ui->recv_autoline_Chb->checkState() == Qt::Checked)str_rev += str2.append("\r\n");elsestr_rev = str2;}}ui->textEdit_recv->insertPlainText(str_rev);ui->textEdit_recv->moveCursor(QTextCursor::End);}// 状态栏标签显示计数值
void Serial::setNumOnLabel(QLabel *lbl, QString strS, long num)
{// 标签显示QString strN;strN.sprintf("%ld", num);QString str = strS + strN;lbl->setText(str);
}
6.测试功能

运行此代码,弹出登录界面

| 输入用户 | 密码 |
|---|---|
| admin | 123456 |
| user | 111111 |
这里有两个账号,点击记住密码,下次就可以不输入密码直接登录就接入串口界面


然后配置串口参数打开串口,这就可以正常收发啦!
7.总结
以上就是使用Qt实现基本的用户登录以及界面跳转的过程。实际开发过程中,你可能还需要考虑更多细节,比如数据加密存储、网络通信安全等。此外,对于多窗口的应用程序,良好的架构设计有助于管理不同窗口之间的交互和状态维护。
🛹🛹🛹从而实现对外部世界进行感知,充分认识这个有机与无机的环境🥳🥳🥳科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣
如果你有任何问题,可以通过下面的二维码加入鹏鹏小分队,期待与你思维的碰撞😘😘😘
参考文献:
相关好文推荐:
- QT初体验:手把手带你写一个自己的串口助手
- 【Qt安装与简易串口控制Arduino开发板小灯教程】
- 【QT串口助手】
相关文章:
【QT用户登录与界面跳转】
【QT用户登录与界面跳转】 1.前言2. 项目设置3.设计登录界面3.1 login.pro参数3.2 界面设置3.2.1 登录界面3.2.2 串口主界面 4. 实现登录逻辑5.串口界面6.测试功能7.总结 1.前言 在Qt应用程序开发中,实现用户登录及界面跳转功能是构建交互式应用的重要步骤之一。下…...
记录一次关于spring映射postgresql的jsonb类型的转化器事故,并使用hutool的JSONArray完成映射
事件的起因是这样的,那次事故发生的起因是因为WebFlux和postgreSQL去重新做鱼皮的鱼图图项目(鱼图图作业)。 在做到picture表的时候,发现postgreSQL中有个jsonb的类型可以更好的支持json数组。 出于锻炼新技术的目的,…...
基于 HTML5 Canvas 制作一个精美的 2048 小游戏--day2
为了使 2048 游戏的设计更加美观和用户友好,我们可以进行以下几项优化: 改善颜色方案:使用更温馨的颜色组合。添加动画效果:为方块的移动和合并添加渐变效果。优化分数显示:在分数增加时使用动画效果。 以下是改进后…...
Django框架:python web开发
1.环境搭建: (a)开发环境:pycharm (b)虚拟环境(可有可无,优点:使用虚拟环境可以把使用的包自动生成一个文件,其他人需要使用时可以直接选择导入包ÿ…...
MySQL、HBase、ES的特点和区别
MySQL:关系型数据库,主要面向OLTP,支持事务,支持二级索引,支持sql,支持主从、Group Replication架构模型(本文全部以Innodb为例,不涉及别的存储引擎)。 HBase࿱…...
联发科MTK6762/MT6762安卓核心板_4G智能模块应用
MT6762安卓核心板是一款工业级高性能、可运行 android9.0 操作系统的 4G智能模块。MT6762平台打造具备 AI 体验、先进双摄像头拍摄效果且具备丰富连接功能的智能手机主板。 MT6762安卓核心板 是一款髙性能低功耗的 4G 全网通安卓智能模块。此模块支持 2G/3G/4G 移动,…...
Windows7系统下载安装Source Code Pro字库
Source Code Pro字库介绍 Source Code Pro是由Adobe推出的一款专为代码展示和编写设计的开源等宽字体。它不仅在编程社区中广受好评,还被广泛应用于各种编辑器环境中,以提升代码的可读性和编程体验。 Source Code Pro的设计充分考虑了编程符号的呈…...
Navicat 17 功能简介 | 商业智能 BI
Navicat 17 功能简介 | 商业智能BI 随着 17 版本的发布,Navicat 也带来了众多的新特性,包括兼容更多数据库、全新的模型设计、可视化智能 BI、智能数据分析、可视化查询解释、高质量数据字典、增强用户体验、扩展 MongoDB 功能、轻松固定查询结果、便捷U…...
C# winodw TableLayoutPanel 料盒生产状态UI自动生成
料盒生产状态UI自动生成,效果如下 以前公司项目的这些都是手动拖控件做的。每个设备的料盒数量不一样,层数不一样时都要发好几个小时去改相关细节和代码。上次改了一次。这个又来了。上次就有想法做成根据参数自动生成。但项目时间有限有没有去深入思路和…...
提示词的艺术----AI Prompt撰写指南(个人用)
提示词的艺术 写在前面 制定提示词就像是和朋友聊天一样,要求我们能够清楚地表达问题。通过这个过程,一方面要不断练习提高自己地表达能力,另一方面还要锻炼自己使用更准确精炼的语言提出问题的能力。 什么样的提示词有用? 有…...
哪些前端打印插件可以实现监听用户选择了打印还是取消
在前端实现监听用户是否选择了打印还是取消的功能,确实是一个挑战,因为浏览器的打印行为是通过原生对话框处理的,而这些对话框的行为无法直接被 JavaScript 控制或监听。不过,有一些插件和方法可以帮助你更接近这个目标࿱…...
【PyCharm】连接Jupyter Notebook
【PyCharm】相关链接 【PyCharm】连接 Git【PyCharm】连接Jupyter Notebook【PyCharm】快捷键使用【PyCharm】远程连接Linux服务器【PyCharm】设置为中文界面 【PyCharm】连接Jupyter Notebook PyCharm连接Jupyter Notebook的过程可以根据不同的需求分为 本地连接 和 远程连…...
【Linux系统编程】—— 深入理解Linux中的环境变量与程序地址空间
文章目录 环境变量常见的环境变量查看环境变量环境变量的修改与使用环境变量的组织⽅式环境变量的命令通过代码如何获取环境变量环境变量的继承 前言:在Linux系统中,环境变量和程序地址空间是系统管理和进程运行的重要组成部分。本文将详细探讨环境变量的…...
Spark常见面试题-部分待更新
1. 简述hadoop 和 spark 的不同点(为什么spark更快) Hadoop是一个分布式管理、存储、计算的生态系统,包括HDFS(分布式文件系统)、MapReduce(计算引擎)和YARN(资源调度器)…...
Android BitmapShader实现狙击瞄具十字交叉线准星,Kotlin
Android BitmapShader实现狙击瞄具十字交叉线准星,Kotlin <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.…...
linux通过web向mac远程传输字符串,mac收到后在终端中直接打印。
要通过Web从Linux向Mac远程传输字符串,并在Mac的终端中直接打印,可以使用以下方法。这里假设Linux作为服务器,Mac作为客户端。 方法 1:使用Python的HTTP服务器 在Linux上启动一个简单的HTTP服务器,Mac通过curl获取字符…...
海云安开发者安全智能助手D10荣膺 “ AI标杆产品 ” 称号,首席科学家齐大伟博士入选2024年度 “ 十大杰出青年 ”
2024年12月27日,粤港澳大湾区AI领袖峰会在深圳成功举办,大会表彰了在人工智能技术创新、应用实践和产业发展等方面取得优异成绩的企业和个人,深圳海云安网络安全技术有限公司开发者安全智能助手D10荣膺“AI标杆产品”称号。同时,公…...
Spring Boot + Apache POI 实现 Excel 导出:BOM物料清单生成器(支持中文文件名、样式美化、数据合并)
目录 引言 Apache POI操作Excel的实用技巧 1.合并单元格操作 2.设置单元格样式 1. 创建样式对象 2. 设置边框 3. 设置底色 4. 设置对齐方式 5. 设置字体样式 6.设置自动换行 7. 应用样式到单元格 3. 定位和操作指定单元格 4.实现标签-值的形式 5.列宽设置 1. 设…...
ReactiveSwift 简单使用
记录 ReactiveSwift 简单使用 导入 ReactiveSwift 库创建 TestViewModel 文件 enum JKTypeType: Int {case cloudcase devicecase weater }// 通过监听属性变化 class TestViewModel: NSObject {lazy var recordType: Property<JKTypeType> {return Property(recordTy…...
CSS 的基础知识及应用
前言 CSS(层叠样式表)是网页设计和开发中不可或缺的一部分。它用于描述网页的视觉表现,使页面不仅实现功能,还能提供吸引人的用户体验。本文将介绍 CSS 的基本概念、语法、选择器及其在提升网页美观性方面的重要性。 什么是 CSS&…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
Mac flutter环境搭建
一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...
JavaScript 标签加载
目录 JavaScript 标签加载script 标签的 async 和 defer 属性,分别代表什么,有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...
Ubuntu 可执行程序自启动方法
使用 autostart(适用于桌面环境) 适用于 GNOME/KDE 桌面环境(如 Ubuntu 图形界面) 1. 创建 .desktop 文件 sudo vi ~/.config/autostart/my_laser.desktop[Desktop Entry] TypeApplication NameMy Laser Program Execbash -c &…...
