1.服务端:
from socket import *import threading
import time
import struct
import os
user = {} # 储存用户信息
def chatRecord(dataSocket):
print("开始发送聊天记录")
with open("Version 3.0\Liaotiainjjilu.txt", 'rb') as rf:
# 持续读取文件并发送数据
for data in rf:
dataSocket.sendall(data)
dataSocket.send("gaspatlazidbaafdsfaya".encode())
print("聊天记录发送完成")
time.sleep(0.5)
def imageChat(info, dataSocket):
size_data = dataSocket.recv(4) # 以4个字节接收图像大小信息
image_size = int.from_bytes(size_data, byteorder='big') # 将字节转换为整数
timeNow = str(time.time())
image_path = 'Version 3.0\\serverlog\\{}.png'.format(timeNow)
time.sleep(0.05)
# 接收图像数据
image_data = b''
while len(image_data) < image_size:
data = dataSocket.recv(1024)
if not data:
break
image_data += data
# 将图像数据保存为文件
with open(image_path, 'wb') as file:
file.write(image_data)
print('图像接收完成')
"""---------------接收完图像后发送给所有人--------------------"""
print("开始发送")
for k in user: # 遍历user
# fs = "C " + info.split(' ', 1)[1] # 聊天内容
# user[k].send(fs.encode()) # 发送聊天内容
# Note.write(fs)
time.sleep(0.05)
texts = "IMAGE " + info.split(' ', 1)[1] + " " + timeNow
time.sleep(0.05)
user[k].send(texts.encode())
with open(image_path, 'rb') as file:
image_data = file.read()
# 发送图像大小信息
image_size = len(image_data)
size_data = image_size.to_bytes(4, byteorder='big') # 将整数转换为字节
user[k].sendall(size_data)
# 发送图像数据
user[k].sendall(image_data)
time.sleep(1)
# user[k].send("gaspatlazidbaafdsfaya".encode())
print("发送完成")
f = open('Version 3.0\Liaotiainjjilu.txt', 'a', encoding='utf-8')
f.write("IMAGERECORD " + info.split(' ', 1)[1] + " " + timeNow + " " + str(time.strftime('%Y-%m-%d %H:%M:%S')))
f.write('\n')
f.close()
print("写入完成")
def userLogin(info, dataSocket):
"""
录入用户登录业务
"""
print(info)
user_text = open(r"Version 3.0\user_text.txt", mode="r", encoding="utf-8")
lines = user_text.readlines()
IF_REG = 0
if len(info.split(' ', 2)) == 1: # 没看懂(
dataSocket.send("NO".encode())
elif info.split(' ', 2)[1] in user: # 如果这个用户名已经在user里了
dataSocket.send("NO".encode()) # 拒接注册
for user_len in range(0, len(lines)):
# print(lines[user_len].split(" ", 1)[0] + " " + lines[user_len].split(" ", 1)[1] + '\n')
if (lines[user_len].split(" ", 1)[0] == info.split(' ', 2)[1] and lines[user_len].split(" ", 1)[1] == info.split(' ', 2)[2]+'\n'):
user[info.split(' ', 2)[1]] = dataSocket # 添加用户名为键,用户连接为值
dataSocket.send("OK".encode()) # 返回"OK"
chatRecord(dataSocket)
IF_REG = 1 # 是否注册为1
for ll in user:
if (user[ll] == user[ll]):
for key in user.keys():
ppp = "R " + key
user[ll].send(ppp.encode())
# Note.write(ppp)
time.sleep(0.3)
print(user)
if IF_REG == 0:
print("NO")
dataSocket.send("NO".encode())
def UserChar(dataSocket, addr):
"""
处理用户聊天
"""
print(info.split(maxsplit=1)[1], end=" ") # 在服务端打印聊天信息
print(addr, end=" ") # 在服务端打印ip地址
print(time.strftime('%Y-%m-%d %H:%M:%S')) # 在服务端打印时间
for k in user: # 遍历user
# print(info.split(' ', 1)[1])
if user[k] != dataSocket: # 发送至所有人(除了自己)
fs = "C " + info.split(' ', 1)[1] # 聊天内容
user[k].send(fs.encode()) # 发送聊天内容
# Note.write(fs)
def Init():
while True:
dataSocket, addr = listenSocket.accept() # 获得一个客户端的连接(阻塞式,只有客户端连接后,下面才执行)
print('接受一个客户端连接:', addr)
if (1 == 1):
xd = threading.Thread(target=deal, args=(dataSocket, addr))
xd.start() # 启动一个线程
def deal(dataSocket, addr):
global recved, info
try:
while True:
recved = dataSocket.recv(1024) # 最大接收字节
info = recved.decode() # 接受的消息
if len(info) == 0: # 如果接受的消息长度为0
# UserExit(dataSocket)
# IF_REG = 0 # 是否注册为1
for key, k in list(user.items()): # 与消息长度为0一样的操作 key:键,k值
# print("user k:", k, " user:", user, " dataSocket:", dataSocket)
# 处理用户意外断开
if k == dataSocket:# user k: <socket.socket fd=188, family=2, type=1, proto=0, laddr=('192.168.0.103', 80), raddr=('119.3.215.140', 50361)> user key: Admin
# print(user[k])
del user[key]
# print(user)
for ka in user:
# print("进入循环删除")
print(key + "已退出群聊")
# user[ka].send((key + "已退出群聊").encode())
user[ka].send(("E " + key).encode())
IF_REG = 0
dataSocket.close()
break
print(user)
break
if info.split(' ', 1)[0] == "IMAGE":
print("收到请求(图片")
imageChat(info, dataSocket)
elif info.split(' ', 1)[0] == 'R':
userLogin(info, dataSocket)
elif info.split(maxsplit=1)[0] == "C": # 如果请求是聊天
UserChar(dataSocket, addr)
f = open('Version 3.0\Liaotiainjjilu.txt', 'a', encoding='utf-8')
f.write("CHATRECORD " + info.split(' ', 1)[1].split(": ", 1)[0] + " " + info.split(' ', 1)[1].split(": ", 1)[1] + " " + time.strftime('%Y-%m-%d %H:%M:%S'))
f.write('\n')
f.close()
# print("写入成功!")
except Exception as e:
print('报错:', e)
for key, k in list(user.items()): # 与消息长度为0一样的操作 key:键,k值
# print("user k:", k, " user:", user, " dataSocket:", dataSocket)
# 处理用户意外断开
if k == dataSocket:# user k: <socket.socket fd=188, family=2, type=1, proto=0, laddr=('192.168.0.103', 80), raddr=('119.3.215.140', 50361)> user key: Admin
# print(user[k])
del user[key]
# print(user)
for ka in user:
# print("进入循环删除")
print(key + "已退出群聊")
# user[ka].send((key + "已退出群聊").encode())
user[ka].send(("E " + key).encode())
IF_REG = 0
dataSocket.close()
break
print(user)
if __name__ == "__main__":
listenSocket = socket(AF_INET, SOCK_STREAM)
# listenSocket.setsockopt(SOL_SOCKET, SOCK_STREAM, True)
# listenSocket.ioctl(SIO_KEEPALIVE_VALS, (1, 60 * 1000, 30 * 1000))
# socket绑定地址和端口
listenSocket.bind(('0.0.0.0', 1234))
listenSocket.listen()
print(f'服务端启动成功,等待客户端连接...')
Init()
2.客户端:
"""
作者:Mike_python
时间:2023/2/26
完稿:2023/7/23
文件内容:客户端
"""
from tkinter import *
from ttkbootstrap import *
from tkinter import messagebox as mg
import socket
import threading
import time
import sys
import os
from tkinter.font import Font
from PIL import ImageTk, Image
from tkinter import filedialog
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def centerWindow(root, width, height):
"""
窗口居中代码
"""
screenwidth = root.winfo_screenwidth() # 获取显示屏宽度
screenheight = root.winfo_screenheight() # 获取显示屏高度
size = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2) # 设置窗口居中参数
root.geometry(size) # 让窗口居中显示
def loginSendToServer(root, passwordWar, usernameWar):
"""验证登录"""
global client
client.connect(('202.189.5.24', 49405))
client.send(("R "+usernameWar.get() + " " + passwordWar.get()).encode()) # 发送注册请求
while True:
data = client.recv(1024)
info = data.decode()
if (info == 'OK'):
login_root.withdraw()# 隐藏登录窗口
main()
break
elif (info == 'NO'):
mg.showerror("","用户名或密码错误!")
sys.exit(0)
def insert_newline(*args):
"""Control-Return后的换行"""
send_entry.insert("insert", "\n")
return "break"
def fasong_Init(*args):
"""fasong的桥梁"""
fasong()
# send_entry.delete("0.0", END) # 设置发送为空
return 'break'
def fasong(*args):
re_data = send_entry.get("1.0", END)[:-1]
if 'exit' == re_data: # 判断是否退出
client.send(("Q "+ username).encode()) # 发送退出的请求
client.close()
elif (re_data != " \n" and re_data != "\n" and re_data != "" and re_data != " "): # 判断内容不为空
time_ = time.strftime('%Y-%m-%d %H:%M:%S') # 以下为自己说的话
chat_text.config(state=NORMAL)
#f1 = Font("微软雅黑", 8)
chat_text.tag_config("tag_3", font=("微软雅黑", 9), foreground="grey")
chat_text.insert(END, time_, "tag_3") # 发送时间
chat_text.insert(END, "\n")
#f = Font("微软雅黑", 13)
chat_text.tag_config("tag_41", font=("微软雅黑", 14), foreground="#808080")
chat_text.insert(END, username + ":", "tag_41") # 发送文本内容c:\迅雷下载\SimplifiedChinese\SourceHanSansSC-Medium.otf
chat_text.insert(END, "\n")
#f = Font("微软雅黑", 12)
chat_text.tag_config("tag_4", font=("微软雅黑", 13), foreground="#2E8B57")
chat_text.insert(END, re_data, "tag_4") # 发送文本内容
chat_text.insert(END, "\n")
chat_text.update_idletasks()
chat_text.config(state=DISABLED)
chat_text.see("end") # 转到最后一行
chat_text.update_idletasks()
# send_entry.first()
# send_entry.delete(0.1,2.0) # 设置发送为空
# send_entry.insert('1 wordstart' , "s")
# time.sleep(0.1)
send_entry.delete("0.0", END) # 设置发送为空
time.sleep(0.15)
client.send(("C " + username + ": " + re_data).encode())
def sendImage():
time.sleep(1)
image_path = filedialog.askopenfilename()
if (len(image_path)>=1):
with open(image_path, 'rb') as file:
image_data = file.read()
client.send(("IMAGE " + username).encode())
# 发送图像大小信息
image_size = len(image_data)
size_data = image_size.to_bytes(4, byteorder='big') # 将整数转换为字节
client.sendall(size_data)
# 发送图像数据
client.sendall(image_data)
"""发送后将图片放到text中"""
# time_ = time.strftime('%Y-%m-%d %H:%M:%S') # 以下为自己说的话
# chat_text.config(state=NORMAL)
# #f1 = Font("微软雅黑", 8)
# chat_text.tag_config("tag_3", font=("微软雅黑", 9), foreground="grey")
# chat_text.insert(END, time_, "tag_3") # 发送时间
# chat_text.insert(END, "\n")
# #f = Font("微软雅黑", 13)
# chat_text.tag_config("tag_41", font=("微软雅黑", 14), foreground="#808080")
# chat_text.insert(END, username + ":", "tag_41") # 发送文本内容c:\迅雷下载\SimplifiedChinese\SourceHanSansSC-Medium.otf
# chat_text.insert(END, "\n")
# image = Image.open(image_path)
# pphoto = ImageTk.PhotoImage(image)
# chat_text.image_create(END, image=pphoto)#用这个方法创建一个图片对象,并插入到“END”的位置
# chat_text.insert(END, "\n")
# chat_text.image = pphoto
# chat_text.update_idletasks()
# chat_text.update()
chat_text.config(state=DISABLED)
chat_text.see("end") # 转到最后一行
# chat_text.update_idletasks()
print('图像发送完成')
mg.showinfo("", "发送图片完成")
def insert_image(canvas, image):
canvas.create_image(0, 0, anchor="nw", image=image)
ls=[]
for i in range(0, 1000):
ls.append(str(i))
i=0
def show_image(image_path):
global i
image = Image.open(image_path)
ls[i] = ImageTk.PhotoImage(image)
chat_text.image_create(END, image=ls[i])#用这个方法创建一个图片对象,并插入到“END”的位置
chat_text.tag_configure("{}".format(str(i)), wrap="none")
chat_text.insert(END, "\n")
chat_text.image = ls[i]
i+=1
def jieshou():
global i
while True:
# time.sleep(0.3)
try:
try:
data = client.recv(5000)
res = data.decode()
except UnicodeDecodeError:
# 忽略无法解码的数据
continue
if(res != ''):
# print("1")
if (res.split(" ", 2)[0]=="C"): # 如果为聊天的请求
# print(res.split(" ", 1)[0])
# print(res.split(" ", 1)[1])
# print(res)
time_ = time.strftime('%Y-%m-%d %H:%M:%S')
chat_text.config(state=NORMAL)
f1 = Font(size=10)
chat_text.tag_config("tag_1", font=("微软雅黑", 9), foreground="grey")
chat_text.insert(END, time_, "tag_1")
chat_text.insert(END, "\n")
f = Font(size=15)
chat_text.tag_config("tag", font=("微软雅黑", 14), foreground="#808080")
chat_text.insert(END, res.split(" ", 2)[1], "tag")
chat_text.insert(END, "\n")
f = Font(size=14)
chat_text.tag_config("tag_2", font=("微软雅黑", 13), foreground="black")
chat_text.insert(END, res.split(" ", 2)[2], "tag_2")
chat_text.insert(END, "\n")
chat_text.config(state=DISABLED)
chat_text.see("end")
if(res.split(" ", 1)[0]=="R"): # 在线用户请求
afd = False
print(res.split(" ", 1)[1])
for kk in range(0, online_user.size()): # 循环判断在线列表里是否有用户名
if online_user.get(kk) == (res.split(" ", 1)[1]): # 检测到是
afd = True # 判断变量为真
break # 退出
if (afd == False): # 如果判断变量为假
online_user.insert(END,res.split(" ", 1)[1]) # 插入用户名
if(res.split(" ", 1)[0]=="E"): # 退出请求
print("收到退出请求")
for kk in range(0, online_user.size()): # 循环判断要删除的用户名
if online_user.get(kk) == (res.split(" ", 1)[1]):
online_user.delete(kk) # 从在线列表去除
online_user.update()
break
if(res.split(" ", 1)[0] == "IMAGE"):
print("开始接收图像")
image_path = './log\\image\\{}.png'.format(res.split(" ", 2)[2])
size_data = client.recv(4) # 以4个字节接收图像大小信息
image_size = int.from_bytes(size_data, byteorder='big') # 将字节转换为整数
image_data = b''
while len(image_data) < image_size:
data = client.recv(1024)
if not data:
break
image_data += data
# 将图像数据保存为文件
with open(image_path, 'wb') as file:
file.write(image_data)
time_ = time.strftime('%Y-%m-%d %H:%M:%S') # 以下为别人
chat_text.config(state=NORMAL)
#f1 = Font("微软雅黑", 8)
chat_text.tag_config("tag_1", font=("微软雅黑", 9), foreground="grey")
chat_text.insert(END, time_, "tag_1")
chat_text.insert(END, "\n")
f = Font(size=15)
chat_text.tag_config("tag", font=("微软雅黑", 14), foreground="#808080")
chat_text.insert(END, res.split(" ", 2)[1], "tag")
chat_text.insert(END, "\n")
# image = Image.open(image_path)
# pphoto = ImageTk.PhotoImage(image)
# chat_text.image_create(END, image=pphoto)#用这个方法创建一个图片对象,并插入到“END”的位置
# chat_text.insert(END, "\n")
# chat_text.image = pphoto
show_image(image_path)
chat_text.update_idletasks()
chat_text.update()
chat_text.config(state=DISABLED)
chat_text.see("end") # 转到最后一行
print('图像接收完成')
# else:
# continue
except Exception as e:
print("ERROR!:", e)
#break
def receiveFile():
"""接收聊天记录"""
try:
time.sleep(0.1)
print("开始接收聊天记录")
with open("./log\\聊天记录({}).txt".format(username), 'wb') as file:
while True:
# 从客户端接收数据
data = client.recv(30000)
info = data.decode()
file.write(data)# 将接收到的数据写入文件
if ('gaspatlazidbaafdsfaya' in info):
print("exit")
file.close()
break
except:
mg.showerror("", "聊天记录读取失败(图片)")
def putChatToText():
"""将读取到的历史消息放置到聊天界面上"""
user_text = open("./log\\聊天记录({}).txt".format(username), mode="r", encoding="utf-8")
lines = user_text.readlines()
for user_len in range(0, len(lines)-1):
try:
if (lines[user_len].split(" ", 3)[0] == "CHATRECORD"):
chat_text.config(state=NORMAL)
f1 = Font(size=10)
chat_text.tag_config("tag_1", font=("微软雅黑", 9), foreground="grey")
chat_text.insert(END, lines[user_len].split(" ", 3)[3], "tag_1")
# chat_text.insert(END, "\n")
f = Font(size=15)
chat_text.tag_config("tag", font=("微软雅黑", 14), foreground="#808080")
chat_text.insert(END, lines[user_len].split(" ", 3)[1], "tag")
chat_text.insert(END, "\n")
f = Font(size=14)
chat_text.tag_config("tag_2", font=("微软雅黑", 13))
chat_text.insert(END,lines[user_len].split(" ", 3)[2], "tag_2")
chat_text.insert(END, "\n")
chat_text.config(state=DISABLED)
chat_text.see("end")
elif (lines[user_len].split(" ", 3)[0] == "IMAGERECORD"):
chat_text.config(state=NORMAL)
f1 = Font(size=10)
chat_text.tag_config("tag_1", font=("微软雅黑", 9), foreground="grey")
chat_text.insert(END, lines[user_len].split(" ", 3)[3], "tag_1")
# chat_text.insert(END, "\n")
f = Font(size=15)
chat_text.tag_config("tag", font=("微软雅黑", 14), foreground="#808080")
chat_text.insert(END, lines[user_len].split(" ", 2)[1], "tag")
chat_text.insert(END, "\n")
# image = Image.open('Version 3.0\\log\\image\\{}.png'.format(lines[user_len].split(" ", 3)[2]))
# pphoto = ImageTk.PhotoImage(image)
# chat_text.image_create(END, image=pphoto)#用这个方法创建一个图片对象,并插入到“END”的位置
# chat_text.insert(END, "\n")
# chat_text.image = pphoto
show_image('./log\\image\\{}.png'.format(lines[user_len].split(" ", 3)[2]))
chat_text.config(state=DISABLED)
chat_text.see("end")
except:
chat_text.config(state=NORMAL)
chat_text.tag_config("tag_31", font=("微软雅黑", 14), foreground="red")
chat_text.insert(END, "历史消息放置失败", "tag_31")
chat_text.insert(END, "\n")
chat_text.config(state=DISABLED)
chat_text.see("end")
chat_text.config(state=NORMAL)
chat_text.tag_config("tag_31", font=("微软雅黑", 14), foreground="blue")
chat_text.insert(END, "-----------------------以上为历史消息-----------------------", "tag_31")
chat_text.insert(END, "\n")
chat_text.config(state=DISABLED)
chat_text.see("end")
def SystemSetting():
setting_root = Toplevel(login_root)
setting_root.title("设置")
centerWindow(setting_root, 400, 200)
def main():
"""登录后主界面"""
global chat_text, send_entry, online_user, username
# root = login_root.Toplevel(themename="morph")
username = usernameWar.get()
try:
receiveFile()
except:
mg.showerror("", "聊天记录读取错误!")
root = Toplevel(login_root)
root.title("聊天界面")
centerWindow(root, 900, 600)
def exit_():
root.destroy()
os._exit(0)
new_thread = threading.Thread(target=jieshou, name="T1")
# 启动新线程
new_thread.start()
new_thread1 = threading.Thread(target=fasong, name="T2")
# 启动新线程
new_thread1.start()
"""------------------------------------------------frame左(聊天区域)------------------------------------------------左侧frame"""
centerFrame = Frame(root, width=650, height=560)
centerFrame.place(x=20, y=20)
"""------------------------------文本接收-------------------------------------------"""
text_frame = Frame(centerFrame)
text_frame.place(x = 10, y = 10)
gun_song_tiao_y = Scrollbar(text_frame, bootstyle="secondary-round")
gun_song_tiao_x = Scrollbar(text_frame, orient=HORIZONTAL, bootstyle="secondary-round")
chat_text = Text(text_frame, height=21, width=67, wrap='none', relief=GROOVE, font=('微软雅黑', 11))#, state=DISABLED
gun_song_tiao_y.pack(side=RIGHT,fill=Y)
gun_song_tiao_x.pack(side=BOTTOM, fill=X)
chat_text.pack()
gun_song_tiao_y.config(command=chat_text.yview)
gun_song_tiao_x.config(command=chat_text.xview)
chat_text.config(yscrollcommand=gun_song_tiao_y.set)
chat_text.config(xscrollcommand=gun_song_tiao_x.set)
"""------------------------------文本接收-------------------------------------------"""
"""------------------------------发送框-------------------------------------------"""
send_entry = Text(centerFrame, width=55, height=4, font=("微软雅黑", 13)) # 发送区域
send_entry.place(x=10, y=460)
send_button = Button(centerFrame, text="\n发 送\n", command=fasong_Init) # 发送按钮
send_button.place(x=585, y=460)
phtotICON = Image.open(r"./log\图片1_pic-one.png")
photowidth, photoheight = phtotICON.size
photonew_width = int(photowidth * 0.06) # 调整宽度为原始宽度的50%
photonew_height = int(photoheight * 0.06) # 调整高度为原始高度的50%
photoimage = phtotICON.resize((photonew_width, photonew_height)) # 调整图像大小
photo = ImageTk.PhotoImage(photoimage)
image_button = Button(centerFrame, image=photo, bootstyle="info-outline", command=sendImage)
image_button.place(x=575, y=530)
phtotICON1 = Image.open(r"./log\设置_setting-three.png")
photowidth1, photoheight1 = phtotICON1.size
photonew_width1 = int(photowidth1 * 0.06) # 调整宽度为原始宽度的50%
photonew_height1 = int(photoheight1 * 0.06) # 调整高度为原始高度的50%
photoimage1 = phtotICON1.resize((photonew_width1, photonew_height1)) # 调整图像大小
photo1 = ImageTk.PhotoImage(photoimage1)
settingButton = Button(centerFrame, image=photo1, bootstyle="info-outline", command=SystemSetting)
settingButton.place(x=613, y=530)
send_entry.bind("<Return>", fasong_Init)
send_entry.bind("<Control-Return>", insert_newline)
"""------------------------------发送框-------------------------------------------"""
"""------------------------------------------------右侧frame(在线列表)------------------------------------------------左侧frame"""
RightFrame = Frame(root, width=200, height=560)
RightFrame.place(x=680, y=20)
online_user = Listbox(RightFrame, height=30, width=35)
online_user.place(x=5, y=5)
online_user.config(font=("微软雅黑", 14))
putChatToText()
root.protocol("WM_DELETE_WINDOW", exit_)
root.mainloop()
def reg_():
"""注册"""
mg.showinfo("", "请前往鱼c论坛注册")
def login():
"""登录界面"""
# global passwordWar, usernameWar, root
def bind_return_key(event=None):
"""回车后进行登录验证"""
loginSendToServer(login_root, passwordWar, usernameWar)
def SetFocusToPassword(*args):
"""将焦点设置到PasswordEntry"""
passwordEntry.focus_set()
global login_root, usernameWar
global username
login_root = Window(themename="morph")
login_root.title("登录界面")
centerWindow(login_root, 500, 600)
passwordWar = StringVar()
usernameWar = StringVar()
# 用户名部分
Label(login_root, text='用户名:', font=("微软雅黑", 14)).place(x=40, y=80)
usernameEntry = Entry(login_root, font=('微软雅黑', 13), width=22, bootstyle="dark", textvariable=usernameWar)
usernameEntry.place(x=140, y=80)
usernameEntry.focus_set() # 使焦点一开始就在输入用户名上
# 密码部分
Label(login_root, text='密 码:', font=("微软雅黑", 14)).place(x=40, y=160)
passwordEntry = Entry(login_root, font=('微软雅黑', 13), width=22, show='*', bootstyle="dark", textvariable=passwordWar)
passwordEntry.place(x=140, y=160)
# 登录按钮
loginButton = Button(login_root, text="登录", bootstyle="info-outline", width=8, command=lambda: loginSendToServer(login_root, passwordWar, usernameWar))
loginButton.place(x=200, y=300)
# 注册按钮
regButton = Button(login_root, text="没有账号?点我注册", bootstyle="info-link", width=20, command=reg_).place(x=150, y=360)
usernameEntry.bind("<Return>", SetFocusToPassword) # 绑定回车到输入密码
passwordEntry.bind("<Return>", bind_return_key) # 绑定回车进行登录
login_root.mainloop()
if __name__ == "__main__":
login()
评论前必须登录!
注册