Python之Qt打造一个聊天软件【二】

Python之Qt打造一个聊天软件【二】

编写聊天软件前的一点准备

1.首先我们需要一颗冷静下来的头脑,因为这是一个浩大的工程,因此你最好在电脑旁边准备一杯咖啡(红牛也行)。

2.在没有好的实力之前,我们最好先模仿,在模仿中不断的提升和改进自己的程序,璞玉需精雕细琢。

3.耐心的去对待它,只有持之以恒,坚持不懈,才能做好它。

4.Just Do It.

开始?

当我们嘬了一口浓浓的 coffee 后 ,与群友闲聊时,发现自己的发言属于非法言论不能发出去时,不经意间产生一个 idea ,那么我们能不能来做一个属于自己的高度定制化的聊天软件呢?答案是可以的,因为标题也告诉你了。此文呢,主要讲述的是 pc 版的 聊天软件,后续的其它文章将会补上移动端和网页端的实现过程,实现多端互通,学习多种语言,成为一名有全局眼光的程序员。

首先拿到这道题目,我们先来思考一下聊天本身,很容易我们就能想到,其实聊天的本质就是人与人之间的距离进行即时信息的传递。既然是人与人之间的信息传递,那么在这个过程中最主要的东西是什么?当人是人本身。知道了人是信息交流最主要的载体这一点之后,我们要做的就是在我们这个聊天软件里面也实现 “人” 的功能就好了,比如实现:人身份证号码(不可重复的)、人的姓名(可重复的)和人的出生日期(可重复的)等等。以上我们要实现的功能在我们这个聊天软件中我们统称为  :用户模块。当我们实现了用户模块之后,该聊天软件的其他一切功能,无非就是在此基础之上进行拓展,所以我们只要先来一步一步的实现就行。

有了上面的知识后,我们就需要来设计我们的数据库和表结构,用来存储 “人” 的相关信息,以便于对其进行 CRUD 操作。

设计数据库和表结构

我们这里采用的是多个数据库多个表的方式,其目的是为了方便以后好设计和扩展我们的程序。当然这么做有个小缺点,就是当操作 I/O 量非常大,我们采用了 redis 的时候,耗费的服务器资源相应也就更多,所以我们就要升级我们的服务器配置。逼迫我们不得不去解决而学习高并发和分布式等应对方案,哈哈,你赚到了。

我这里暂时创建了a_a、a_f、a_l 和 a_m 这四个数据库。其中 a_l 数据库用于存储用户的快速登录数据; a_a 数据库用于存储用户的全部信息;a_f 用于存储用户的朋友信息;a_m 数据库用于存储用户的消息。在 a_l 数据库中存在着一个 u_r 表,它包括的字段有:i_d、a_t、e_l、p_d、u_e、i_m 和 s_s 。之前我也写文章说过了字段名这么写的原因,这里不在赘述,其分别意为id、account、email、password、username、image 和 status。

为了方便操作,我这里简单的编写了个重置数据库操作的代码,以后我们重新创建数据库和相关的表就不用手动操作了。

在此之前我们先来创建数据库的连接配置,方便以后我们编写的程序好调用它:

DatabasesConfig.py

import pymysql
import pymysql.cursors
def getConnection(Database):
    connection = pymysql.connect(
                    host='localhost',
                    user='root',
                    password='your password',
                    db=Database,
                    charset  = "utf8mb4",
                    cursorclass=pymysql.cursors.DictCursor
    )
    return connection

然后下面是自动化数据库的操作代码:

QuickDatabases.py

import Qt5File.Public.Model.DatabasesConfig
Database = 'a_l'
connection = Qt5File.Model.DatabasesConfig.getConnection(Database)  
Cursor = connection.cursor()
CreateTBu_r = '''
                create table u_r(
                  i_d int(11) primary key auto_increment NOT NULL,
                  a_t int(7) unique NOT NULL,
                  e_l char(50) NOT NULL,
                  p_d char(32) NOT NULL,
                  u_e char(6) NOT NULL,
                  i_m char(10) NOT NULL,
                  s_s int(1) NOT NULL
                );
              '''
def JustJudge(DatabaseName):
    JudgeExist = f"SHOW DATABASES LIKE '{DatabaseName}'"    
    Cursor.execute(JudgeExist)
    Data = Cursor.fetchone()
    if Data:
        Cursor.execute(f"drop database {DatabaseName}")
        Cursor.execute(f"create database {DatabaseName}")
        if DatabaseName == 'a_l':
            UseDBa_l = "use a_l"            
            Cursor.execute(UseDBa_l)
            Cursor.execute(CreateTBu_r)
    else:
        Cursor.execute(f"create database {DatabaseName}")
JustJudge('a_l')
JustJudge('a_a')
JustJudge('a_m')
JustJudge('a_f')
connection.commit()
connection.close()

运行 QuickDatabases.py 我们就可以重新快速生成的一些数据库和基本表了。

然后我们开始着手于文件的命名以及存储的操作的设计,因为一个好的项目必然要有一个好的文件夹/文件的命令规则;一个好的程序,必然要有精密的思考和良好的命名及格式。

如何创建好的文件夹/文件以及命名?

我们可以通过程序界面方法来逐级创建我们的程序文件,最好使用 MVC 的规则方式来存放我们的文件夹以及文件。( MVC 是现代程序和框架的常用构架方式)。M 即 Model 意为模型,用于存放数据库配置等、V 即 Views 意为视图,用于存放视图文件等、C 即 Controller 意为控制器,用于存放逻辑代码等。因此我们的项目主目录下面主要应该有三个文件,即 Model、Views、Controller 文件。除此之外,我们还应该有一个入口文件,最好命名为 Index.py ,意思是每次我们的程序每次运行最开始都是从这个入口文件开始加载的。这个入口文件我们可以做一些检测,比如系统平台、软件版本、操作环境的检测等等。通过这个入口文件,我们将来一步步引导用户到相应的程序。比如我们默认打开的是用户登录界面,用户可以通过这个切换到注册或者找回界面进行相应的操作,还可以登录到主界面进行其他操作,比如添加/删除好友、更改个性签名、查看自己/好友的信息、与好友进行会话和访问好友空间等等功能。我们将之前的那两个关于数据库的代码文件放到 Model 下去,所以这个项目的文件结构大致应该是:

//---代表每一级目录 ++代表文件
Qt5File //主目录,名字随便起的,可自行更改
|---Model //配置、模块等资源文件
|-----DatabasesConfig.py //数据库连接配置
|-----QuickDatabases.py  //快速创建数据库及表结构
|---Views      //认证、主界面等视图文件
|---Controller //认证、主界面等控制器
|++index.py    //入口文件
|.... //其他文件或者公共配置

那么我们如何添加视图和控制器文件呢?在 Views 下面创建相应的视图文件和在 Controller 即可,为了便于识别建议在分别在各自的目录下创建不同功能的文件夹。比如我想创建一个认证系列下的登录页面和登录逻辑代码,那么就应该是这样:

//---代表每一级目录 ++代表文件
Qt5File                          //主目录,名字随便起的,可自行更改
|---Model                        //配置、模块等资源文件
|-----DatabasesConfig.py         //数据库连接配置
|-----QuickDatabases.py          //快速创建数据库及表结构
|---Views                        //认证、主界面等视图文件
|------Authencation              //认证类文件,包含登录、注册和找回功能
|---------Login                  //登陆类
|---------++LoginViews.py        //登录视图
|---Controller                   //认证、主界面等控制器
|------Authencation              //认证类文件,包含登录、注册和找回功能
|---------Login                  //登录类
|---------++LoginController.py   //登陆类逻辑代码
|++index.py                      //入口文件
|.... //其他文件或者公共配置

剖析入口文件

Index.py

from PyQt5 import  QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QCursor
from PyQt5.QtCore import Qt

...

if __name__ =='__main__': #判断是否是作为脚本被直接执行
    app = QtWidgets.QApplication(sys.argv) #每个PyQt5应用程序必须创建一个应用程序对象 
    LoginWindow = LoginViews() #实例化LoginViews类
    LoginWindow.show() #显示它
    time.sleep(1) #为避免其他错误,暂停1ms
    sys.exit(app.exec_()) #干净的退出并进入循环

首先我们先导入我们要使用的 PyQt5 的相关模块,我这里大概介绍一下它的各个模块的大概用途:

1. QtCore 模块 :涵盖了 Qt 包的核心的非 GUI 的功能,此模块被用于处理程序中涉及到 time、文件、目录、数据类型、文本流、连接、mime、进程和线程等对象。

2. QtGui 模块 :涵盖了多种基本图形功能的类,包括但不限于:窗口集、事件处理、2D图形、基本的图像、界面和字体文本等。

3. QtWidgets 模块 :包含了一整套 UI 元素组件,用于建立符合系统风格的 classic 界面,非常方便,可以在安装时选择是否使用此功能。

4. QtMultimedia 模块包含了一套类库,该类库被用于处理多媒体事件,通过调用 API 接口访问摄像头、 语音设备、收发消息(radio functionality)等。

5. QtBluetooth 模块包含了处理蓝牙活动的类库,它的功能包括:扫描设备、连接和交互等行为。

6. QtNetWor 模块包含了网络编程的类库,这组类程序通过提供便捷的 TCP/IP 及 UDP 的 c/s程式码集合,使得基于 Qt 的网络编程更加容易。

7. QtPositioning 模块用于获取位置信息,此模块允许使用多种方式达成定位,包括但不限于:卫星、无线网、文字信息等等。此应用一般用于网络地图定位系统。

8. Enginio 模块用于构架客户端的应用程序库,用于在运行时访问 Qt Cloud 服务器托管的应用程序。

9. QtWebSockets模块包含了一组类程序,用以实现 WebSocket 协议。

10. QtWebKit 模块包含了用于实现 WebKit2 的网络浏览器的类库。

11. QtWebKitWidgets 模块包含了用于基于 Web 浏览器实现的类,用于基于 QtWidgets 的应用程序。

12. QtXml 模块包含了用于处理 XML 的类库,此模块为 SAX 和 DOM API 的实现提供了方法。

13. QtSvg 模块通过一组类,为显示矢量图形文件的内容提供了方法。

14. QtSql 模块提供了数据库对象的接口以供使用。

15. QtTest 模块包含了可以通过单元测试,以调试 PyQt5 应用程序的功能。

我们导入相关的文件或者模块后,接下来我们要使用 QtWidgets 模块下的 QApplication去创建一个应用程序对象,然后我们编写相应的类文件和 UI 文件并导入后实例化执行它。

这里顺带说一下:一个 python 的文件有两种使用的方法,第一是直接作为脚本执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。而我们不希望这个 Index.py 文件模块被重用,故写if __name__ =='__main__':来进行判断。顺便说一下它的原理:每个 python 文件或者模块都包含一个内置变量 __name__ 当运行该文件或者模块的时候该 __name__ 其实就是等同于该运行的文件或者模块的名称 ( 同时也包括py后缀 ) ,如果是被 import 到其他文件或者模块中,那么 __name__ 等同于该运行文件或者模块的名称  ( 不包括py后缀 ) 。而 __main__ 等于当前执行文件或者模块的名称 ( 同时也包括py后缀 )。故使用全局变量可判断当前脚本被执行的情况。

那么接下来,我们先来编写认证类界面(登录,注册和找回),一步一步的实现。

认证类界面

由于我们使用的是 Qt Designer ,故我们编写 UI 文件应该是名为 filename.ui 的形式,所以我们的 UI 文件应该放在在相应的文件夹下内。接下来我们在相应的目录内创建 LoginViews.ui 文件,然后使用 Qt Designer 打开编辑它。

接下来我们来编辑一个 ui 文件,弄成自己想要的样子。可以自己右键选择控件编写其 qss 美化它。但这不是主要的,主要的是关于登录界面必须得有一些通向其他界面的控件,根据思考我们可以得知,登录界面主要可以通过两个输入框和点击登录到主界面去,其次可以跳转到注册和找回页面去。

当然我这里编写好了认证类的界面 UI,仅供参考:

12.png

13.png

14.png

我们先来创建认证类的ui文件,然后使用 Qt Designer 导入我们的 *.ui 后来,来逐个绘制我们的界面和创建相应的信号。

18.png

当我们完成界面的编写和建立相关的信号槽后(信号槽一定要拖到 mianWindow 上),接下来就来生成我们的 *.py 文件,这个操作和前面的文章中的操作是一样的,然后我们将生成好的 py 文件放入相应的 Views 文件夹用于存放相应的 *.py 视图代码内并在相应的 Controller 文件夹中创建相应的 *.py 终于存放该文件的逻辑代码。

...


回复列表



回复操作

正在加载验证码......

请先拖动验证码到相应位置

发布时间:2020-04-27 20:06:59

修改时间:2020-05-19 01:03:17

查看次数:99

评论次数:0