SkillAgentSearch skills...

PythonProject

python聊天室(tkinter写界面,treading,socket实现私聊群聊查看聊天记录,mysql存储数据)

Install / Use

/learn @stormzhuo0707/PythonProject
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

@[toc]

一、概述

使用==python==实现的聊天室的功能,主要功能是==群聊,私聊==两种聊天方式.实现的方式是使用==套接字编程==和==多线程treading==。

界面是用Python自带的==tkinter==模块写的,里面包含==三个界面==,分别是==登录<==,==注册==以及==聊天界面==。还有聊天界面==嵌套子窗口==,用与显示==聊天记录==。用户数据用==mysql==存储

二、mysql准备工作

先在mysql中创建一个数据库,可直接使用下面的语句

CREATE DATABASE python_chat

然后再执行下面的代码会自动创建一个表(<font color=red size=3>注意:密码记得改</font>) chat_create_mysql.py

import pymysql
Connection = pymysql.connect(host="localhost", user="root", password="jin1687062650", db="python_chat")
cursor = Connection.cursor()
sql_create_table = '''

    create table user_information
     (
      user_name varchar (20),
      
      password varchar (20),
      
      data BLOB
    )

'''
cursor.execute(sql_create_table)
cursor.close()

三、数据库模块

代码如下 chat_mysql.py

import pymysql
import sys
class LogInformation(object):
    @staticmethod  # 静态函数方便调用
    def login_check(user_name, password):  # 检查用户登录
        db = pymysql.connect(host="localhost", user="root", password="jin1687062650", db="python_chat")  # 关联数据库
        cursor = db.cursor()  # 取得数据库游标
        sql = "SELECT * FROM user_information where user_name = '%s' " % (user_name)  # 数据库语言,按id查找
        try:
            cursor.execute(sql)  # 游标执行数据库语言
            results = cursor.fetchone()  # 接受所有符合的对象
            db.close()  # 关闭数据库
            if password == results[1]:  # 如果密码相等则返回True
                return True
            else:
                return False
        except:
            return False

    @staticmethod  # 静态函数方便调用
    def create_new_user(user_name, password, file_name):  # 创建新用户
        db = pymysql.connect(host="localhost", user="root", password="jin1687062650", db="python_chat")  # 关联数据库
        cursor = db.cursor()  # 取得数据库游标
        fp = open(file_name, 'rb')  # 打开头像路径
        img = fp.read()  # 读取头像
        sql = "INSERT INTO user_information VALUES  (%s,%s,%s);"  # 数据库语言,插入用户数据
        args = (user_name, password, img)
        try:
            cursor.execute(sql, args)   # 游标执行数据库语言
            db.commit()  # 提交
            db.close()  # 关闭数据库连接
            print("插入成功")
            return "0"
        except:
            print("数据库出错")
            db.rollback()  # 发生错误时回滚
            db.close()  # 关闭数据库连接

    @staticmethod  # 静态函数方便调用
    def select_user_name(user_name):  # 检查用户名是否已存在
        db = pymysql.connect(host="localhost", user="root", password="jin1687062650", db="python_chat")  # 关联数据库
        cursor = db.cursor()  # 取得数据库游标
        sql = "SELECT * FROM user_information where user_name = '%s' " % (user_name)  # 数据库语言,按用户名查找
        try:
            cursor.execute(sql)  # 游标执行数据库语言
            results = cursor.fetchone()  # 接受所有符合的对象
            #  1代表已有用户, 0代表可以注册
            if results!=None:
                db.close()  # 关闭数据库
                return "1"
            else:
                db.close()  # 关闭数据库
                return "0"
        except:
            print("数据库出错")
            db.close()  # 关闭数据库

    @staticmethod # 静态函数方便调用
    def fing_face(user_name):  # 查找头像,用于聊天界面显示头像
        try:
            conn = pymysql.connect(host='localhost', user='root',
                               password='jin1687062650', db='python_chat')  # 关联数据库
            cursor = conn.cursor()  # 取得数据库游标
            sql = "SELECT * FROM user_information where user_name = '%s' " % (user_name)  # 数据库语言,按用户名查找
            cursor.execute(sql)   # 游标执行数据库语言
            fout = open('用户头像.png', 'wb')  # 打开存放用户头像的路径
            fout.write(cursor.fetchone()[2])  # 写头像数据
            fout.close()  # 关闭流
            cursor.close()  # 关闭游标
            conn.close()   # 关闭数据库
        except pymysql.Error as e:
            print("Error %d: %s" % (e.args[0], e.args[1]))
            sys.exit(1)

代码解释如下 用户登录,注册都会向服务器发送请求,服务器收到请求后,则会调用==chat_mysql==检查用户数据是不是和数据库中的是数据相同或者插入用户数据用于注册。

四、tkinter实现三个界面

tkinter简介: <font color="red" size=4>Tkinter</font>(也叫 Tk 接口)是 Tk 图形用户界面工具包标准 的 Python 接口。Tk 是一个轻量级的跨平台图形用户界面 (GUI)开发工具。

登陆界面实现

代码如下 chat_login_panel.py

from tkinter import *  # 导入模块,用户创建GUI界面

# 登陆界面类
class LoginPanel:

    # 构造方法,参数为按钮事件处理函数,从客户端main传进来,可以实现按钮回调
    def __init__(self, handle_login, handle_register, close_login_window):
        # 初始化参数实例变量
        self.handle_login = handle_login
        self.handle_register = handle_register
        self.close_login_window = close_login_window

    # 显示登录界面的实例方法
    def show_login_panel(self):
        # 声明全局变量方便,在静态函数重调用
        global login_frame
        global frames
        global imgLabel
        global numIdx

        self.login_frame = Tk()  # 创建主窗口
        # 设置背景颜色
        self.login_frame.configure(background="white")
        login_frame = self.login_frame  # 绑定全局变量

        # 设置窗口关闭按钮回调,用于退出时关闭socket连接
        self.login_frame.protocol("WM_DELETE_WINDOW", self.close_login_window)

        # 得到屏幕宽度,高度
        screen_width = self.login_frame.winfo_screenwidth()
        screen_height = self.login_frame.winfo_screenheight()
        # 声明宽度,高度变量
        width = 503
        height = 400
        # 设置窗口在屏幕局中变量
        gm_str = "%dx%d+%d+%d" % (width, height, (screen_width - width) / 2,
                                  (screen_height - 1.2 * height) / 2)
        self.login_frame.geometry(gm_str)  # 设置窗口局中
        self.login_frame.title("登录")   # 设置窗口标题
        # 设置窗口不能改变大小
        self.login_frame.resizable(width=False, height=False)

        numIdx = 10  # gif的帧数
        # 循环遍历动图的帧
        frames = [PhotoImage(file='login.gif', format='gif -index %i' % (i)) for i in range(numIdx)]
        # 创建存放gif的标签
        imgLabel = Label(self.login_frame, height=400, width=500)
        # 设置标签的位置
        imgLabel.place(x=-252, y=-200, relx=0.5, rely=0.5, relwidth=1, relheigh=0.5)

        # 设置文本标签和位置
        Label(login_frame, text="昵称:", font=("宋体", 12), bg="white", fg="grey") \
            .place(x=110, y=230)
        Label(login_frame, text="密码:", font=("宋体", 12), bg="white", fg="grey") \
            .place(x=110, y=260)

        # 声明用户名密码变量
        self.user_name = StringVar()
        self.password = StringVar()

        # 设置输入框及位置
        self.entry1=Entry(login_frame,  textvariable=self.user_name, fg="black", width=25)
        self.entry1.place(x=180, y=230)
        self.entry2=Entry(login_frame, textvariable=self.password, show='*', fg="black", width=25)
        self.entry2.place(x=180, y=260)

        # 设置注册按钮及位置,按钮事件为handle_register函数
        self.button_register = Button(login_frame, text="注册账号", relief=FLAT, bg='white', fg='grey',
                             font=('黑体', 15), command=self.handle_register).place(x=0, y=370)

        self.login_frame.bind('<Return>', self.handle_login)  # 绑定回车键
        # 设置登录按钮及位置,按钮事件为handle_login函数
        self.button_login = Button(login_frame, text="登录", bg="#00BFFF", fg="white", width=21, height=2,
                                font=('黑体', 15), command=lambda: self.handle_login(self))
        self.button_login.place(x=160, y=300)

    # 定时器函数,用于刷新gif的帧
    @staticmethod
    def update(idx):
        frame = frames[idx]
        idx += 1  # 下一张的序号
        imgLabel.configure(image=frame)
        login_frame.after(200, LoginPanel.update, idx % numIdx)  # 200毫秒之后继续执行定时器函数

    # 调用定时器函数,执行循环mainloop显示界面实例方法
    def load(self):
        LoginPanel.update(0)
        self.login_frame.mainloop()

    # 关闭登录界面实例方法
    def close_login_panel(self):
        if self.login_frame == None:
            print("未显示界面")
        else:
            # 关闭登录界面
            self.login_frame.destroy()

    # 获取输入的用户名密码实例方法
    def get_input(self):
        return self.user_name.get(), self.password.get()

<font color="red" size=3>注意:上面模块是给客户端调用的,单独运行没效果,后面会介绍启动方法。下面给出客户端调用登录模块显示的效果

在这里插入图片描述

代码解释如下 创建一个登陆界面模块==chat_login_panel==,里面包含一个登陆界面类==LoginPanel==,类的构造方法==init==是初始化从客户端传进来的函数,用与处理按钮事件,当用户点击按钮时便会回调给客户端处理的。

实例方法==show_login_panel==是把组件封装起来,这样用户就可以创建多个登陆界面且互不干扰,实现多人登陆,每一个实例对象都是不相同的。

实例方法==close_login_panel,get_input==分别是关闭登陆界面,获取用户输入的用户名和密码。

静态函数==update==是定时器,用于刷新gif动图。

实例方法==load==的作用是调用定时器函数==updata==和执行循环函数==login_frame.mainloop==显示在==login_show_panel==创建的界面==login_frame==

客户端调用过程: 当用户执行main模块时便会创建==LoginPanel==对象,创建对象过程会调用==init==构造方法把mian模块中的函数作为参数进行初始化变为实例变量,作为按钮的事件处理。创建完对象后就可以用对象调用对象的实例方法了。

首先调用<==ogin_show_panel==实例方法创建组件以及布局,然后调用==load==执行定时器函数刷新动图和==mainloop==循环函数显示界面。

客户端main模块后面会给出,注册界面和聊天界面跟登陆界面是一样的

注册界面实现

代码如下

chat_login_panel.py

from tkinter import *  # 导入模块,用户创建GUI界面
from PIL import Image  # 导入处理图像模块

# 注册界面类
class RegisterPanel(object):

    # 构造方法,参数为按钮事件处理函数,从客户端main传进来,可以实现按钮回调
    def __init__(self, file_open_face, close_register_window, register_submit):
        # 初始化参数实例变量
        self.file_open_face = file_open_face
        self.close_register_window = close_register_window
        self.register_submit = register_submit
        self.file_name = ""  # 文件路径

    # 显示注册界面的实例方法
    def show_register_panel(self):
        # 声明全局变量方便,在静态函数重调用
        global register_frame
        global frames
        global imgLabel
        global numIdx

        # 创建主窗口
        self.register_frame = Tk()
        register_frame = self.register_frame  # 绑定全局变量
        # 设置背景颜色
        self.register_frame.configure(background="white")
        # 得到屏幕宽度,高度
        screen_width = self.register_frame.winfo_screenwidth()
        screen_height = self.register_frame.winfo_screenheight()
        # 声明宽度,高度变量
        width = 503
        height = 400
        # 设置窗口在屏幕局中变量
        gm_str = "%dx%d+%d+%d" % (width, height, (screen_width - width) / 2,
                                  (screen_height - 1.2 * height) / 2)
        # 设置窗口局中
        self.register_frame.geometry(gm_str)
        # 设置窗口标题
        self.register_frame.title("注册")
        # 设置窗口不能改变大小
        self.register_frame.resizable(width=False, height=False)

        self.p1 = PhotoImage(file='添加头像按钮.png')  # 把图片转化为PhotoImage类型

        numIdx = 9  # gif的帧数
        # 循环遍历动图的帧
        fr

Related Skills

View on GitHub
GitHub Stars26
CategoryData
Updated9d ago
Forks1

Languages

Python

Security Score

75/100

Audited on Mar 22, 2026

No findings