300行代码用PyQt实现登录注册界面,并用数据库保存信息

3,971 阅读10分钟

目录

1. 前言

2. 环境配置

  1. 下载安装 python
  2. 安装配置编辑器
  3. 下载所需库

3. 主页面

      3.1. 创建一个页面
      3.2. 添加相关控件
         3.2.1. 添加标签
         3.2.2. 添加输入框
         3.2.3. 添加按钮
         3.2.4. 设置背景

4. 注册页面

界面设计

5. 逻辑关系

   5.1. 注册
   5.2. 登录


前言

上一次利用tkinter设计了一个登陆注册界面受到了很多小伙伴的关注(传送门),于是想着利用PyQt来实现,当然是因为 PyQt长的好看呀,并且这一次我们使用数据库来存储用户信息,是不是一下子比上一次逼格了不少,先看看效果吧 ![演示](img-blog.csdnimg.cn/20191127125… =600x) 下面马上开始吧


环境配置

  1. 下载安装 python
  2. 安装配置编辑器
  3. 下载所需库

前面的两个内容在之前的教程中已经解决了,接下来我们来下载安装所要使用的库, 只需要运行以下的命令便可以安装 PyQt5了,不过时间可能稍微长一点,耐心等待~~

pip install PyQt5

主页面

1. 创建一个页面

对于新手来说最简单粗暴的方法为,在这里我们使用此种方式[1]

from PyQt5.Qt import *

除此之外我们还需要导入sys模块

import sys

然后利用下面代码创建一个主页面

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.set_ui()

    def set_ui(self):
        self.resize(1000, 800) 
        self.setWindowTitle('  Login in')


app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())

在上面的代码中我们首先导入了所需要的模块

  • QApplication -> 应用程序,一个程序只能有一个应用程序接口
  • QMainWindow -> 主窗口,一个程序也只能有一个主窗口
  • sys -> 获取系统的信息,比如命令行的,并且承担关闭窗口后完全退出的责任

然后我们使用

  • resize -> 设置窗口的大小
  • setWindowTitle -> 设置窗口的标题

接着使用

  • app = QApplication(sys.argv)创建一个应用
  • 创建一个窗口window并且调用show方法来显示窗口[2]
  • app.exec_() 可以让窗口一直运行知道被关闭,类似于tkinter中的mainloop方法
  • sys.exit(app.exec_())可以用来判断程序是否正常退出

运行之后,我们可以看到以下界面,和平常所见的是不是一模一样!

创建一个页面

我们还可以使用下面的代码为我们的图像添加一个图标

 def change_icon(self):
        """用来修改图像的图标"""
        self.icon = QIcon("python-logo.png")
        self.setWindowIcon(self.icon)

添加图标之后,界面得到进一步的美化,接下来我们将对我们的界面添加一些控件与用户进行交互

2. 添加相关控件
2.1 添加标签

类似tkinter中的LabelQLabel为PyQt中提供的标签对象,我们可以使用下面的代码实现标签的添加

def add_label(self):

     self.label = QLabel(self)
     self.label.setText('username')
     self.label.setFixedSize(240, 40)
     self.label.move(120, 530)

在上述代码中,我们首先定义了一个QLabel对象,然后使用其中的方法[3] setText -> 设置文本内容 setFixedSize -> 设置不可修改的窗口大小

然后我们来设置以下字体,利用 QFont对象来创建一个字体对象,然后使用QLabel对象的setFont方法进行设置

 # 设置字体
 label_font = QFont()
 label_font.setFamily('Consolas')
 label_font.setPixelSize(35)
 self.label.setFont(label_font)

QFont中的方法[3:1]setFamily -> 设置字体 setPixelSize -> 设置字体大小

运行之后我们可以得到之下的效果 添加标签-username 然后同样的添加 password等文字标签,全部代码如下:

def add_label(self):
    """添加相应的标签"""
    # 设置字体
    label_font = QFont()
    label_font.setFamily('Consolas')
    label_font.setPixelSize(35)
    
    # 创建文本标签
    self.username_label = QLabel(self)
    self.password_label = QLabel(self)
    self.cyberits_label = QLabel(self)

    # 设置标签中的文本
    self.username_label.setText("username")
    self.password_label.setText("password")
    self.cyberits_label.setText("Cyberist--a python learner")
    
    # 设置标签的大小
    self.cyberits_label.setFixedSize(600, 40)
    self.username_label.setFixedSize(240, 40)
    self.password_label.setFixedSize(240, 40)

    # 设置标签的位置
    self.username_label.move(120, 530)
    self.password_label.move(120, 600)
    self.cyberits_label.move(280, 700)

    self.username_label.setFont(label_font)
    self.password_label.setFont(label_font)
    label_font.setPixelSize(30)
    self.cyberits_label.setFont(label_font)

在创建控件的参数中加入另外一个控件(此处为self)可以将创建的参数视为子控件,没有外围的放大关闭等按钮,否则显示的时候需要调用本身的show方法

2.2 添加输入框

PyQt5中提供了QLineEdit可以实现获取用户的输入,使用下面的方法便可以实现对输入框的添加

def add_line_edit(self):
    """添加输入框"""
    line_edit_font = QFont()
    line_edit_font.setFamily('Consolas')
    line_edit_font.setPixelSize(30)
    
    # 创建
    self.username_edit = QLineEdit(self)
    self.password_edit = QLineEdit(self)

    # 设置密码格式
    self.password_edit.setEchoMode(QLineEdit.Password)

    # 设置字体
    self.username_edit.setFont(line_edit_font)
    self.password_edit.setFont(line_edit_font)

    # 设置占位符
    self.username_edit.setPlaceholderText("username")
    self.password_edit.setPlaceholderText("password")

    # 设置大小
    self.username_edit.setFixedSize(350, 40)
    self.password_edit.setFixedSize(350, 40)

    # 设置位置
    self.username_edit.move(320, 530)
    self.password_edit.move(320, 600)

在上述代码中 QLineEdit -> 定义一个输入框对象 setEchoMode(QLineEdit.Password)-> 设置输入的时候显示的为我们平常所见的小圆点,无法看到其中的文本内容 setText -> 对其中的文本进行设置 setPlaceholderText -> 设置其中的占位符,相当于提示信息 setFixedSize -> 设置固定的大小 move -> 定位 于是,我们便可以获得下面的效果 输入框

2.3 添加按钮

QPushButton可以帮我们实现按钮的功能,其使用方法和之前的标签,输入框的使用是类似的,在这里不再赘述,直接上代码:

def add_button(self):
     """添加按钮"""
     button_font = QFont()
     button_font.setFamily('Consolas')
     button_font.setPixelSize(30)

     # 创建按钮对象
     self.login_button = QPushButton("Login", self)
     self.sign_button = QPushButton(self)

     # 修改大小且不可变
     self.login_button.setFixedSize(160, 50)
     self.sign_button.setFixedSize(160, 50)

     # 设置字体
     self.login_button.setFont(button_font)
     self.sign_button.setFont(button_font)

     # 设置位置
     self.login_button.move(750, 530)
     self.sign_button.move(750, 600)

     # 设置文本提示内容
     self.login_button.setText("Login in")
     self.sign_button.setText("Sign up")

     # 实现功能,按钮点击之后执行的动作
     self.login_button.clicked.connect(self.login)
     self.sign_button.clicked.connect(self.sign_up_window)

上面值得注意的是使用了信号和槽,当按钮被用户clicked的时候便会执行参数中的动作,在这里分别为登录和注册功能,此外还有许多的信号,在之后的专栏中会提到,届时谢谢关注

2.4 设置背景

设置背景的时候,我们可以使用QFrame对象,并在其上设置一下背景图片,如果直接设置的话,可能不太好操作和理解,但是注意,在绘制中,首先绘制的会在窗口的后端,后绘制的会在前端,所以要先创建背景,然后在设置之前的效果,否则可能出现意想不到的效果[4],实现代码如下:

def set_background_image(self):
    """添加背景图片"""
    self.frame = QFrame(self)
    self.frame.resize(1000, 520)
    self.frame.move(40, 150)
    self.frame.setStyleSheet(
        'background-image: url("./python.png"); background-repeat: no-repeat; text-align:center;')

首先创建一个QFrame对象,然后控制其大小和位置,最后使用setStyleSheet对其进行设置,其参数可以是类似css样式的字符串,或者说是qss[5]

到这里,我们对主页面的外观设置已经完成了,样式如图(个人觉得比tkinter好看多了): Login in


注册页面

界面设计

注册页面和主页面比较相似,先看看实现之后的样式吧: main window 具体的代码如下,这里不再赘述,和登录的主页面实现是完全类似的

class SignWindow(QWidget):
    def __init__(self):
        super(SignWindow, self).__init__()
        self.setWindowTitle("Sign up")  # 设置标题
        self.resize(1000, 800)  # 设置窗口的大小
        self.set_ui()  # 调用其他的设计方法

    def set_ui(self):  # 集合所有的设计
        self.add_line_edit()
        self.add_button()
        self.add_label()

    def add_label(self):
        """添加相应的标签"""
        # 设置文本的字体
        label_font = QFont()
        label_font.setFamily('Consolas')
        label_font.setPixelSize(35)

        # 创建三个对应的标签,父窗口为 self
        self.username_label = QLabel(self)
        self.password_label = QLabel(self)
        self.cyberits_label = QLabel(self)
        self.confirm_label = QLabel(self)

        # 相应的标签设置文本
        self.username_label.setText("username")
        self.password_label.setText("password")
        self.confirm_label.setText("confirmed")
        self.cyberits_label.setText("Cyberist--a python learner")

        # 控制label的大小  fixedSize表示之后无法修改
        self.cyberits_label.setFixedSize(600, 40)
        self.username_label.setFixedSize(240, 40)
        self.password_label.setFixedSize(240, 40)
        self.confirm_label.setFixedSize(240, 40)

        # 设置对应的位置,注意move不是移动多少,而是直接移动到
        self.username_label.move(120, 530)
        self.password_label.move(120, 600)
        self.cyberits_label.move(280, 730)
        self.confirm_label.move(120, 670)

        # 设置字体
        self.username_label.setFont(label_font)
        self.password_label.setFont(label_font)
        self.confirm_label.setFont(label_font)

        # 将字体调小
        label_font.setPixelSize(30)
        self.cyberits_label.setFont(label_font)

    def add_line_edit(self):
        """添加输入框"""
        line_edit_font = QFont()
        line_edit_font.setFamily('Consolas')
        line_edit_font.setPixelSize(30)

        # 创建三个输入框,父窗口为 self
        self.username_edit = QLineEdit(self)
        self.password_edit = QLineEdit(self)
        self.confirm_edit = QLineEdit(self)

        # 设置密码格式,输入密码的时候不可见密码
        self.password_edit.setEchoMode(QLineEdit.Password)
        self.confirm_edit.setEchoMode(QLineEdit.Password)

        # 设置一下字体
        self.username_edit.setFont(line_edit_font)
        self.password_edit.setFont(line_edit_font)
        self.confirm_edit.setFont(line_edit_font)

        # 设置输入框中的占位符
        self.username_edit.setPlaceholderText("username")
        self.password_edit.setPlaceholderText("password")
        self.confirm_edit.setPlaceholderText('password again')

        # 控制大小
        self.username_edit.setFixedSize(350, 40)
        self.password_edit.setFixedSize(350, 40)
        self.confirm_edit.setFixedSize(350, 40)

        # 控制位置
        self.username_edit.move(320, 530)
        self.password_edit.move(320, 600)
        self.confirm_edit.move(320, 670)

    def add_button(self):
        """添加按钮"""
        button_font = QFont()
        button_font.setFamily('Consolas')
        button_font.setPixelSize(30)

        self.sign_button = QPushButton(self)
        self.sign_button.setFixedSize(160, 50)
        self.sign_button.setFont(button_font)
        self.sign_button.move(750, 600)
        self.sign_button.setText("Sign up")

        self.sign_button.setShortcut('Return')

我们把它保存到另外一个文件Sign_Up.py,如果我们要使用,调用该模块就可以了


逻辑关系

1. 注册

当用户输入账号密码的时候,我们首先获取用户的输入

username = self.username_edit.text()
password = self.password_edit.text()
confirm = self.confirm_edit.text()

然后对输入进行判断,首先应该判断是否为空,如果为空,提示输入,如果不为空,再检查是否存在该用户,如果没有在检查两次输入的密码是否一致,如果一致,写入数据库,如果不是提示密码不一致

if not password or not confirm:  # 如果有一个密码或者密码确认框为空
     QMessageBox.information(self, 'Error', 'The password is empty', QMessageBox.Yes)
 elif self.is_has(username): # 如果用户名已经存在
     QMessageBox.information(self, 'Error', 'The username already exists', QMessageBox.Yes)
 else:
     if password == confirm and password:  # 如果两次密码一致,并且不为空
         connect = sqlite3.connect('./data.db')
         cursor = connect.cursor()
         sql = 'INSERT INTO data (username, password) VALUES(?,?)'  # 添加入数据库
         cursor.execute(sql, (username, password))
         connect.commit()
         cursor.close()
         connect.close()
         QMessageBox.information(self, 'Successfully', 'Sign up successfully'.format(username),
                                 QMessageBox.Yes)
         self.close()  # 注册完毕之后关闭窗口

     else:
         QMessageBox.information(self, 'Error', 'The password is not equal', QMessageBox.Yes)

数据库的操作可以看看我的另一篇 文章 操作 其中的is_has代码如下:

 @staticmethod
 def is_has(username):
     """判断数据库中是否含有用户名"""
     connect = sqlite3.connect('./data.db')
     cursor = connect.cursor()
     sql = 'SELECT * FROM data WHERE username=?'
     result = cursor.execute(sql, (username,))  # 执行sqlite语句
     connect.commit()
     data = result.fetchall()  # 获取所有的内容
     cursor.close()
     connect.close()
     if data:
         return True
     else:
         return False

代码中的QMessageBox是PyQt5中提供的与用户进行交互的信息窗口,information只是其中的一个,另外还有question, warning, critical,使用方法一样,所接受的参数如下

QMessageBox.information(self, QWidget,p_str, p_str_1, buttons, QMessageBox_StandardButtons=None, QMessageBox_StandardButton=None, *args, **kwargs)

QWidget -> 承载窗口 p_str -> 标题 p_str_1 -> 提示文本 buttons -> 弹窗的按钮,比如Ok, Cancel等 QMessageBox_StandardButtons 等 -> 为默认的按钮 实际上使用的时候参数对应可能有所不同,比如对应的参数不会是p_str

另外当该窗口关闭的同时,我们应该将输入框中的文本清空,以免对下一次的输入造成影响,读者也可以自己试试 关闭窗口后清空输入框,只要重写关闭事件[6]方法便可以了,代码如下:

def closeEvent(self, event):
     """关闭之后将输入框清空"""
     self.username_edit.setText('')
     self.confirm_edit.setText('')
     self.password_edit.setText('')
2. 登录

实现了注册功能之后,实现登录功能就很简单了,我们只需要从数据库中查找对应的用户数据,如果没有查找到,则提示用户不存在,否则判断密码是否正确,正确的话则登录成功,不正确提示密码错误

def login(self):
    """登录功能"""
    connect = sqlite3.connect('./data.db')  # 链接数据库
    cursor = connect.cursor()
    username = self.username_edit.text()   # 获取账号
    password = self.password_edit.text()  # 获取密码
    sql = 'SELECT username, password FROM data WHERE username=?'  # 从数据库中读取数据
    result = cursor.execute(sql, (username,))
    data = result.fetchall()
    if username and password:  # 如果两个都不空
        if data:
            if str(data[0][1]) == password:
                QMessageBox.information(self, 'Successfully', 'Login in successful \n Welcome {}'.format(username),
                                        QMessageBox.Yes | QMessageBox.No)
            else:
                QMessageBox.information(self, 'Failed', 'Password is wrong, try again',
                                        QMessageBox.Yes | QMessageBox.No)

        else:
            QMessageBox.information(self, 'Error', 'No such username', QMessageBox.Yes | QMessageBox.No)
    elif username:  # 如果用户名填了
        QMessageBox.information(self, 'Error', 'Input your password', QMessageBox.Yes | QMessageBox.No)
    else:
        QMessageBox.information(self, 'Error', 'Fill in the blank', QMessageBox.Yes | QMessageBox.No)

经过上面的操作,我们终于完成了登录,注册界面的设置,以及相关逻辑功能的实现,但是其实上面的很多代码都是比较冗余的,有兴趣的小伙伴可以再修改修改。 在公众号Cyberist中提供源码, 回复PyQt登录界面即可获取下载地址

在之后会在该代码的基础之上添加更多的功能,并且使其更加结构化


  1. 在作者写的代码中导入是逐个逐个导入的,这样对资源的消耗量小 ↩︎

  2. 因为它没有父窗口,如果有父窗口的话只需要调用父窗口的show方法 ↩︎

  3. 当然这只是其中众多方法的一部分,更多方法之后会有专栏进行讲解 ↩︎ ↩︎

  4. 比如输入框无法用鼠标点击,按钮无法用鼠标点击 ↩︎

  5. 更多内容在这里不详细介绍了,届时请关注专栏 ↩︎

  6. PyQt5中提供了许多事件消息,该事件是窗口关闭之后执行的动作 ↩︎