【QT用户登录与界面跳转】
【QT用户登录与界面跳转】
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 serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += 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.0
SOURCES += \
main.cpp \
mainwindow.cpp \
serial.cpp
HEADERS += \
mainwindow.h \
serial.h
FORMS += \
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 += target
RESOURCES += \
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_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
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_OBJECT
public:
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);// 设置默认定时时长1000ms
connect(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(); //ASCII
array = 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,选中为2
if(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");
else
str_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实现基本的用户登录以及界面跳转的过程。实际开发过程中,你可能还需要考虑更多细节,比如数据加密存储、网络通信安全等。此外,对于多窗口的应用程序,良好的架构设计有助于管理不同窗口之间的交互和状态维护。
🛹🛹🛹从而实现对外部世界进行感知,充分认识这个有机与无机的环境🥳🥳🥳科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣
如果你有任何问题,可以通过下面的二维码加入鹏鹏小分队,期待与你思维的碰撞😘😘😘
参考文献:
相关好文推荐:
原文地址:https://blog.csdn.net/vor234/article/details/145229792
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!