import wx
import pymysql
import hashlib
import re
class LoginFrame(wx.Frame):
def __init__(self, parent, title):
super(LoginFrame, self).__init__(parent, title=title, size=(400, 320)) # 增加高度以容纳退出按钮
self.InitUI()
self.Centre()
self.Show()
# 初始化数据库连接
try:
self.db_connection = pymysql.connect(
host='localhost',
user='tester2',
password='123456',
database='databasechat',
charset='utf8mb4'
)
except pymysql.Error as e:
wx.MessageBox(f"数据库连接失败: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)
self.Destroy()
def InitUI(self):
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
# QQ号输入
wx.StaticText(panel, label="QQ号:", pos=(20, 30))
self.qq_entry = wx.TextCtrl(panel, pos=(120, 30), size=(200, -1))
# 密码输入
wx.StaticText(panel, label="密码:", pos=(20, 80))
self.password_entry = wx.TextCtrl(panel, pos=(120, 80), size=(200, -1), style=wx.TE_PASSWORD)
# 按钮容器
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
# 登录按钮
login_btn = wx.Button(panel, label="登录", size=(80, 30))
login_btn.Bind(wx.EVT_BUTTON, self.on_login)
button_sizer.Add(login_btn, 0, wx.RIGHT, 20)
# 注册按钮
register_btn = wx.Button(panel, label="注册", size=(80, 30))
register_btn.Bind(wx.EVT_BUTTON, self.on_register)
button_sizer.Add(register_btn, 0, wx.RIGHT, 20)
# 退出按钮 - 新增功能
exit_btn = wx.Button(panel, label="退出", size=(80, 30))
exit_btn.Bind(wx.EVT_BUTTON, self.on_exit)
button_sizer.Add(exit_btn)
# 添加按钮到主布局
vbox.Add(wx.StaticText(panel), 0, wx.TOP, 30)
vbox.Add(button_sizer, 0, wx.ALIGN_CENTER | wx.TOP, 30)
panel.SetSizer(vbox)
self.Bind(wx.EVT_CLOSE, self.on_close)
def on_login(self, event):
qq_number = self.qq_entry.GetValue()
password = self.password_entry.GetValue()
# 验证QQ号格式
if not re.match(r'^\d{5,15}$', qq_number):
wx.MessageBox("QQ号格式错误,应为5-15位数字", "错误", wx.OK | wx.ICON_ERROR)
return
# 密码加密
hashed_password = hashlib.sha256(password.encode()).hexdigest()
try:
with self.db_connection.cursor() as cursor:
sql = "SELECT * FROM users4 WHERE qq_number = %s AND password = %s"
cursor.execute(sql, (qq_number, hashed_password))
result = cursor.fetchone()
if result:
wx.MessageBox(f"登录成功!欢迎,{result[1]}", "成功", wx.OK | wx.ICON_INFORMATION)
else:
wx.MessageBox("QQ号或密码错误", "错误", wx.OK | wx.ICON_ERROR)
except Exception as e:
wx.MessageBox(f"数据库错误: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)
def on_register(self, event):
# 关闭登录窗口,打开注册窗口
self.Hide()
RegisterFrame(self, "用户注册")
# 新增退出功能
def on_exit(self, event):
confirm = wx.MessageDialog(self, "确定要退出程序吗?", "确认退出",
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
if confirm.ShowModal() == wx.ID_YES:
self.Close(True)
def on_close(self, event):
# 关闭数据库连接
if hasattr(self, 'db_connection') and self.db_connection:
self.db_connection.close()
self.Destroy()
class RegisterFrame(wx.Frame):
def __init__(self, parent, title):
super(RegisterFrame, self).__init__(parent, title=title, size=(450, 520)) # 增加高度容纳按钮
self.login_frame = parent
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
# 昵称
wx.StaticText(panel, label="昵称:", pos=(20, 30))
self.nickname_entry = wx.TextCtrl(panel, pos=(120, 30), size=(200, -1))
# 年龄
wx.StaticText(panel, label="年龄:", pos=(20, 80))
self.age_entry = wx.TextCtrl(panel, pos=(120, 80), size=(200, -1))
# 电话
wx.StaticText(panel, label="电话:", pos=(20, 130))
self.phone_entry = wx.TextCtrl(panel, pos=(120, 130), size=(200, -1))
# 密码
wx.StaticText(panel, label="密码:", pos=(20, 180))
self.password_entry = wx.TextCtrl(panel, pos=(120, 180), size=(200, -1), style=wx.TE_PASSWORD)
# 确认密码
wx.StaticText(panel, label="确认密码:", pos=(20, 230))
self.confirm_entry = wx.TextCtrl(panel, pos=(180, 230), size=(200, -1), style=wx.TE_PASSWORD)
# 生成QQ号按钮
self.generate_qq_btn = wx.Button(panel, label="生成QQ号", pos=(50, 280), size=(180, 30))
self.generate_qq_btn.Bind(wx.EVT_BUTTON, self.on_generate_qq)
# QQ号显示
wx.StaticText(panel, label="QQ号:", pos=(20, 330))
self.qq_display = wx.StaticText(panel, label="", pos=(120, 330))
# 按钮容器
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
# 注册按钮
register_btn = wx.Button(panel, label="注册", size=(80, 30))
register_btn.Bind(wx.EVT_BUTTON, self.on_register)
button_sizer.Add(register_btn, 0, wx.RIGHT, 20)
# 返回登录按钮
back_btn = wx.Button(panel, label="返回登录", size=(180, 30))
back_btn.Bind(wx.EVT_BUTTON, self.on_back)
button_sizer.Add(back_btn, 0, wx.RIGHT, 20)
# 退出按钮 - 新增功能
exit_btn = wx.Button(panel, label="退出", size=(80, 30))
exit_btn.Bind(wx.EVT_BUTTON, self.on_exit)
button_sizer.Add(exit_btn)
# 添加按钮到主布局
vbox.Add(wx.StaticText(panel), 0, wx.TOP, 80)
vbox.Add(button_sizer, 0, wx.ALIGN_CENTER | wx.TOP, 20)
panel.SetSizer(vbox)
self.Centre()
self.Show()
def on_generate_qq(self, event):
qq_number = self.generate_qq_number()
if qq_number:
self.qq_display.SetLabel(qq_number)
else:
wx.MessageBox("生成QQ号失败", "错误", wx.OK | wx.ICON_ERROR)
def generate_qq_number(self):
try:
with self.login_frame.db_connection.cursor() as cursor:
cursor.execute("SELECT MAX(qq_number) AS max_qq FROM users4")
result = cursor.fetchone()
max_qq = result[0] if result[0] else 10000
return str(int(max_qq) + 1)
except Exception as e:
wx.MessageBox(f"生成QQ号错误: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)
return None
def nickname_exists(self, nickname):
try:
with self.login_frame.db_connection.cursor() as cursor:
sql = "SELECT COUNT(*) AS count FROM users4 WHERE username = %s"
cursor.execute(sql, (nickname,))
result = cursor.fetchone()
return result[0] > 0
except Exception as e:
wx.MessageBox(f"数据库错误: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)
return True
def on_register(self, event):
nickname = self.nickname_entry.GetValue()
password = self.password_entry.GetValue()
confirm_password = self.confirm_entry.GetValue()
age = self.age_entry.GetValue()
phone = self.phone_entry.GetValue()
qq_number = self.qq_display.GetLabel()
# 验证昵称
if not re.match(r'^[\u4e00-\u9fa5a-zA-Z0-9]{2,20}$', nickname):
wx.MessageBox("昵称格式错误,应为2-20个字符(汉字、字母、数字)", "错误", wx.OK | wx.ICON_ERROR)
return
# 验证密码
if len(password) < 8 or not re.search(r'[a-zA-Z]', password) or not re.search(r'[0-9]', password):
wx.MessageBox("密码格式错误,至少8位且包含字母和数字", "错误", wx.OK | wx.ICON_ERROR)
return
if password != confirm_password:
wx.MessageBox("两次输入的密码不一致", "错误", wx.OK | wx.ICON_ERROR)
return
# 验证年龄
if age and (not age.isdigit() or not (0 <= int(age) <= 150)):
wx.MessageBox("年龄格式错误,应是0-150的整数", "错误", wx.OK | wx.ICON_ERROR)
return
# 验证电话
if phone and not re.match(r'^\d{11}$', phone):
wx.MessageBox("电话格式错误,应为11位数字", "错误", wx.OK | wx.ICON_ERROR)
return
if not qq_number:
wx.MessageBox("请先生成QQ号", "错误", wx.OK | wx.ICON_ERROR)
return
# 检查昵称是否已存在
if self.nickname_exists(nickname):
wx.MessageBox("昵称已被使用,请更换", "错误", wx.OK | wx.ICON_ERROR)
return
# 密码加密
hashed_password = hashlib.sha256(password.encode()).hexdigest()
try:
with self.login_frame.db_connection.cursor() as cursor:
sql = """INSERT INTO users4 (username, password, age, telephone, qq_number)
VALUES (%s, %s, %s, %s, %s)"""
cursor.execute(sql, (nickname, hashed_password, age or None, phone or None, qq_number))
self.login_frame.db_connection.commit()
wx.MessageBox(f"注册成功!您的QQ号是:{qq_number}", "成功", wx.OK | wx.ICON_INFORMATION)
self.on_back(None)
except Exception as e:
wx.MessageBox(f"数据库错误: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)
def on_back(self, event):
# 返回登录窗口
self.login_frame.Show()
self.Destroy()
# 新增退出功能
def on_exit(self, event):
confirm = wx.MessageDialog(self, "确定要退出程序吗?", "确认退出",
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
if confirm.ShowModal() == wx.ID_YES:
self.login_frame.Close(True)
if __name__ == "__main__":
app = wx.App()
LoginFrame(None, "用户登录系统")
app.MainLoop()
将该程序中登录,注册,退出按钮下移至屏幕下方
最新发布