自学内容网 自学内容网

【QT用户登录与界面跳转】

1.前言

在Qt应用程序开发中,实现用户登录及界面跳转功能是构建交互式应用的重要步骤之一。下面将介绍如何使用Qt框架来创建一个简单的用户登录界面,并根据用户的输入信息进行验证,然后跳转到相应的【QT串口助手】主界面。
源码地址:

2. 项目设置

首先,确保你的开发环境中已安装了Qt及其相关工具(如Qt Creator),前期也安装过QT(参考博客:【Qt安装与简易串口控制Arduino开发板小灯教程】)。本文记录一下用QT Creator 写一个用户登录与界面串口助手的过程,整个工程只有几百行代码,跟着做下来对新手来说可以更快了解整个QT项目的开发过程和一些常用控件的使用方法。最好每个功能自己都试试增加自信心!
💕💕💕
先来看看作品:
在这里插入图片描述

3.设计登录界面

3.1 login.pro参数

  1. 设置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);
}

这段代码实现了一个简单的登录窗口,具备记住密码、显示/隐藏密码和基本的用户验证功能。以下是各部分的功能概述:

  1. 构造函数 MainWindow::MainWindow

    • 初始化主窗口,设置背景图片(如果存在),并初始化一些UI元素。
    • 为密码输入框设置密码模式(即隐藏输入字符)。
    • 连接按钮和复选框到相应的槽函数,以便处理用户的交互操作。
    • 调用 loadSettings() 函数加载上次保存的设置。
  2. 析构函数 MainWindow::~MainWindow

    • 清理资源,包括删除UI对象和设置对象。
  3. login 函数

    • 验证用户名和密码是否正确。如果匹配,则关闭当前登录窗口,并打开一个新的 Serial 窗口。
    • 如果不匹配,弹出一个警告消息框提示用户名或密码错误。
  4. display_psd 函数

    • 根据复选框的状态切换密码输入框的显示模式:如果选中则显示密码文本,否则隐藏(以圆点形式显示)。
  5. saveSettingsloadSettings 函数

    • 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.测试功能

在这里插入图片描述
运行此代码,弹出登录界面
在这里插入图片描述

输入用户密码
admin123456
user111111

这里有两个账号,点击记住密码,下次就可以不输入密码直接登录就接入串口界面
在这里插入图片描述

在这里插入图片描述
然后配置串口参数打开串口,这就可以正常收发啦!

7.总结

以上就是使用Qt实现基本的用户登录以及界面跳转的过程。实际开发过程中,你可能还需要考虑更多细节,比如数据加密存储、网络通信安全等。此外,对于多窗口的应用程序,良好的架构设计有助于管理不同窗口之间的交互和状态维护。
🛹🛹🛹从而实现对外部世界进行感知,充分认识这个有机与无机的环境🥳🥳🥳科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣

如果你有任何问题,可以通过下面的二维码加入鹏鹏小分队,期待与你思维的碰撞😘😘😘

参考文献:
相关好文推荐:

  1. QT初体验:手把手带你写一个自己的串口助手
  2. 【Qt安装与简易串口控制Arduino开发板小灯教程】
  3. 【QT串口助手】

原文地址:https://blog.csdn.net/vor234/article/details/145229792

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!