Python聊天室?guī)Ы缑鎸?shí)現(xiàn)的示例代碼(tkinter,Mysql,Treading,socket)
一、前言
我用的是面向?qū)ο髮懙?,把界面功能模塊封裝成類,然后在客戶端創(chuàng)建對(duì)象然后進(jìn)行調(diào)用。好處就是方便我們維護(hù)代碼以及把相應(yīng)的信息封裝起來,每一個(gè)實(shí)例都是各不相同的。
所有的界面按鈕處理事件都在客戶端,在創(chuàng)建界面對(duì)象是會(huì)把客戶端的處理事件函數(shù)作為創(chuàng)建對(duì)象的參數(shù),之后再按鈕上綁定這個(gè)函數(shù),當(dāng)點(diǎn)擊按鈕時(shí)便會(huì)回調(diào)函數(shù)
二、登錄界面實(shí)現(xiàn)
登錄界面模塊chat_login_panel.py
from tkinter import * # 導(dǎo)入模塊,用戶創(chuàng)建GUI界面 # 登陸界面類 class LoginPanel: # 構(gòu)造方法,參數(shù)為按鈕事件處理函數(shù),從客戶端main傳進(jìn)來,可以實(shí)現(xiàn)按鈕回調(diào) def __init__(self, handle_login, handle_register, close_login_window): # 初始化參數(shù)實(shí)例變量 self.handle_login = handle_login self.handle_register = handle_register self.close_login_window = close_login_window # 顯示登錄界面的實(shí)例方法 def show_login_panel(self): # 聲明全局變量方便,在靜態(tài)函數(shù)重調(diào)用 global login_frame global frames global imgLabel global numIdx self.login_frame = Tk() # 創(chuàng)建主窗口 # 設(shè)置背景顏色 self.login_frame.configure(background="white") login_frame = self.login_frame # 綁定全局變量 # 設(shè)置窗口關(guān)閉按鈕回調(diào),用于退出時(shí)關(guān)閉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 # 設(shè)置窗口在屏幕局中變量 gm_str = "%dx%d+%d+%d" % (width, height, (screen_width - width) / 2, (screen_height - 1.2 * height) / 2) self.login_frame.geometry(gm_str) # 設(shè)置窗口局中 self.login_frame.title("登錄") # 設(shè)置窗口標(biāo)題 # 設(shè)置窗口不能改變大小 self.login_frame.resizable(width=False, height=False) numIdx = 10 # gif的幀數(shù) # 循環(huán)遍歷動(dòng)圖的幀 frames = [PhotoImage(file='login.gif', format='gif -index %i' % (i)) for i in range(numIdx)] # 創(chuàng)建存放gif的標(biāo)簽 imgLabel = Label(self.login_frame, height=400, width=500) # 設(shè)置標(biāo)簽的位置 imgLabel.place(x=-252, y=-200, relx=0.5, rely=0.5, relwidth=1, relheigh=0.5) # 設(shè)置文本標(biāo)簽和位置 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() # 設(shè)置輸入框及位置 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) # 設(shè)置注冊(cè)按鈕及位置,按鈕事件為handle_register函數(shù) self.button_register = Button(login_frame, text="注冊(cè)賬號(hào)", 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) # 綁定回車鍵 # 設(shè)置登錄按鈕及位置,按鈕事件為handle_login函數(shù) 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) # 定時(shí)器函數(shù),用于刷新gif的幀 @staticmethod def update(idx): frame = frames[idx] idx += 1 # 下一張的序號(hào) imgLabel.configure(image=frame) login_frame.after(200, LoginPanel.update, idx % numIdx) # 200毫秒之后繼續(xù)執(zhí)行定時(shí)器函數(shù) # 調(diào)用定時(shí)器函數(shù),執(zhí)行循環(huán)mainloop顯示界面實(shí)例方法 def load(self): LoginPanel.update(0) self.login_frame.mainloop() # 關(guān)閉登錄界面實(shí)例方法 def close_login_panel(self): if self.login_frame == None: print("未顯示界面") else: # 關(guān)閉登錄界面 self.login_frame.destroy() # 獲取輸入的用戶名密碼實(shí)例方法 def get_input(self): return self.user_name.get(), self.password.get()
上面模塊把登錄界面封裝成類,這樣在客戶端就可以創(chuàng)建很多實(shí)例,每一個(gè)實(shí)例對(duì)應(yīng)一個(gè)登錄界面
注意:上面模塊是給客戶端調(diào)用的,直接運(yùn)行沒效果,下面給出客戶端調(diào)用登錄模塊顯示的效果
三、注冊(cè)界面實(shí)現(xiàn)
注冊(cè)界面模塊chat_login_panel.py
from tkinter import * # 導(dǎo)入模塊,用戶創(chuàng)建GUI界面 from PIL import Image # 導(dǎo)入處理圖像模塊 # 注冊(cè)界面類 class RegisterPanel(object): # 構(gòu)造方法,參數(shù)為按鈕事件處理函數(shù),從客戶端main傳進(jìn)來,可以實(shí)現(xiàn)按鈕回調(diào) def __init__(self, file_open_face, close_register_window, register_submit): # 初始化參數(shù)實(shí)例變量 self.file_open_face = file_open_face self.close_register_window = close_register_window self.register_submit = register_submit self.file_name = "" # 文件路徑 # 顯示注冊(cè)界面的實(shí)例方法 def show_register_panel(self): # 聲明全局變量方便,在靜態(tài)函數(shù)重調(diào)用 global register_frame global frames global imgLabel global numIdx # 創(chuàng)建主窗口 self.register_frame = Tk() register_frame = self.register_frame # 綁定全局變量 # 設(shè)置背景顏色 self.register_frame.configure(background="white") # 得到屏幕寬度,高度 screen_width = self.register_frame.winfo_screenwidth() screen_height = self.register_frame.winfo_screenheight() # 聲明寬度,高度變量 width = 503 height = 400 # 設(shè)置窗口在屏幕局中變量 gm_str = "%dx%d+%d+%d" % (width, height, (screen_width - width) / 2, (screen_height - 1.2 * height) / 2) # 設(shè)置窗口局中 self.register_frame.geometry(gm_str) # 設(shè)置窗口標(biāo)題 self.register_frame.title("注冊(cè)") # 設(shè)置窗口不能改變大小 self.register_frame.resizable(width=False, height=False) self.p1 = PhotoImage(file='添加頭像按鈕.png') # 把圖片轉(zhuǎn)化為PhotoImage類型 numIdx = 9 # gif的幀數(shù) # 循環(huán)遍歷動(dòng)圖的幀 frames = [PhotoImage(file='register.gif', format='gif -index %i' % (i)) for i in range(numIdx)] # 創(chuàng)建存放gif的標(biāo)簽 imgLabel = Label(self.register_frame, height=400, width=500) # 設(shè)置標(biāo)簽的位置 imgLabel.place(x=-252, y=-200, relx=0.5, rely=0.5, relwidth=1, relheigh=0.5) # 設(shè)置文本框,用戶存放頭像 self.face_show = Text(self.register_frame, bg="white", height=3.5, width=7, highlightcolor="white") # 設(shè)置文本框不可編輯 self.face_show.config(state=DISABLED) # 設(shè)置文本框的位置 self.face_show.place(x=370, y=230) # 聲明寬度高度,用來設(shè)置圖片大小 self.width = 50 self.height = 50 # 打開圖片,用在注冊(cè)頁面文本框中顯示默認(rèn)頭像 img = Image.open("默認(rèn)頭像.png") # 設(shè)置圖片的大小 out = img.resize((self.width, self.height), Image.ANTIALIAS) # 保存圖片,類型為png out.save(r"頭像.png", 'png') # 把頭像轉(zhuǎn)換為PhotoImage類型,用于在文本框顯示 self.p2 = PhotoImage(file='頭像.png') # 設(shè)置文本框可編輯 self.face_show.config(state=NORMAL) # 把頭像圖片插入文本框 self.face_show.image_create(END, image=self.p2) # 設(shè)置文本框不可編輯 self.face_show.config(state=DISABLED) # 設(shè)置文本框滑到最低 self.face_show.see(END) # 設(shè)置文本標(biāo)簽及位置 Label(self.register_frame, text="用戶名:", font=("宋體", 12), bg="white", fg="grey") \ .place(x=60, y=230) Label(self.register_frame, text="密 碼:", font=("宋體", 12), bg="white", fg="grey") \ .place(x=60, y=260) Label(self.register_frame, text="確認(rèn)密碼:", font=("宋體", 12), bg="white", fg="grey") \ .place(x=60, y=290) # 聲明用戶名,密碼,確認(rèn)密碼變量 self.user_name = StringVar() self.password = StringVar() self.confirm_password = StringVar() # 設(shè)置輸入文本框和位置,用于獲取用戶的輸入 Entry(self.register_frame, textvariable=self.user_name, fg="black", width=30) \ .place(x=140, y=230) Entry(self.register_frame, textvariable=self.password, show="*", fg="black", width=30) \ .place(x=140, y=260) Entry(self.register_frame, textvariable=self.confirm_password, show="*", fg="black", width=30) \ .place(x=140, y=290) # 設(shè)置退出注冊(cè)頁面按鈕及位置,按鈕事件為close_register_window函數(shù) self.botton_quit = Button(self.register_frame, text="返回", relief=FLAT, bg='white', fg="grey", font=('黑體', 15), command=self.close_register_window).place(x=0, y=370) self.register_frame.bind('<Return>', self.register_submit) # 綁定注冊(cè)按鈕回車事件 # 設(shè)置注冊(cè)按鈕及位置,按鈕事件為register.submit函數(shù) self.botton_register = Button(self.register_frame, text="立即注冊(cè)", bg="#00BFFF", fg="white", width=27, height=2, font=('黑體', 15), command=lambda: self.register_submit(self)).place(x=120, y=330) # 設(shè)置添加頭像按鈕及位置,事件處理為為file_open_face函數(shù) self.botton_file_open = Button(self.register_frame, image=self.p1, relief=FLAT, bd=0, command=self.file_open_face).place(x=430, y=230) # 定時(shí)器靜態(tài)函數(shù),用于刷新gif的幀 @staticmethod def update(idx): frame = frames[idx] idx += 1 # 下一張的序號(hào) imgLabel.configure(image=frame) register_frame.after(200, RegisterPanel.update, idx % numIdx) # 200毫秒之后繼續(xù)執(zhí)行定時(shí)器函數(shù) # 調(diào)用定時(shí)器函數(shù),執(zhí)行循環(huán)mainloop顯示界面實(shí)例方法 def load(self): RegisterPanel.update(0) self.register_frame.mainloop() # 添加頭像實(shí)例方法 def add_face(self, file_name): self.file_name = file_name # 打開圖片 img = Image.open(file_name) # 設(shè)置圖片大小 out = img.resize((self.width, self.height), Image.ANTIALIAS) # 保存圖片,類型為png out.save(r"頭像.png", 'png') # 把頭像轉(zhuǎn)化為PhotoImage self.p = PhotoImage(file='頭像.png') # 設(shè)置文本框可編輯 self.face_show.config(state=NORMAL) self.face_show.delete('0.0', END) # 把頭像插入文本框 self.face_show.image_create(END, image=self.p) # 設(shè)置文本不可編輯 self.face_show.config(state=DISABLED) # 設(shè)置文本框滑到最低 self.face_show.see(END) # 關(guān)閉注冊(cè)界面實(shí)例方法 def close_register_panel(self): if self.register_frame == None: print("未顯示界面") else: # 關(guān)閉注冊(cè)界面 self.register_frame.destroy() # 獲取輸入的用戶名、密碼、確認(rèn)密碼實(shí)例方法 def get_input(self): return self.user_name.get(), self.password.get(), self.confirm_password.get(), self.file_name
下面簡(jiǎn)單介紹下客戶端如何調(diào)用注冊(cè)界面:
當(dāng)運(yùn)行main客戶端模塊時(shí),首先會(huì)創(chuàng)建一個(gè)chat_logiin_panel的對(duì)象,然后調(diào)用對(duì)象的實(shí)例方法顯示登錄界面,如果用戶點(diǎn)擊了注冊(cè)按鈕,則會(huì)觸發(fā)事件handle_register函數(shù),這個(gè)函數(shù)是從main客戶端創(chuàng)建對(duì)象時(shí)作為參數(shù)傳進(jìn)來的,之后便會(huì)在客戶端中的handdle_register函數(shù)中創(chuàng)建chat_register_panel對(duì)象,再調(diào)用實(shí)例方法顯示注冊(cè)界面,其他的調(diào)用類似是,下面不再闡述
注意:上面模塊是給客戶端調(diào)用的,直接運(yùn)行沒效果,下面給出客戶端調(diào)用注冊(cè)模塊顯示的效果
四、聊天界面實(shí)現(xiàn)
聊天界面模塊chat_main_panel.py
from tkinter import * # 導(dǎo)入模塊,用戶創(chuàng)建GUI界面 import tkinter.font as tf import time import chat_mysql # 導(dǎo)入處理mysql的模塊 from PIL import Image # 導(dǎo)入處理圖像模塊 # 主界面類 class MainPanel: def __init__(self, user_name, send_message, send_mark, refurbish_user, private_talk, close_main_window): print("初始化主界面") self.user_name = user_name self.send_message = send_message self.private_talk = private_talk self.close_main_window = close_main_window # 用字典將標(biāo)記與表情圖片一一對(duì)應(yīng), 用于后面接收標(biāo)記判斷表情貼圖 self.dic = {} self.ee = 0 # 判斷表情面板開關(guān)的標(biāo)志 self.send_mark = send_mark self.refurbish_user = refurbish_user self.mark_flag = "" self.face = [] def show_main_panel(self): # 聲明全局變量,方便在靜態(tài)函數(shù)中調(diào)用用 global main_frame global frames global imgLabel global numIdx # 創(chuàng)建主窗口 main_frame = Tk() # 把全局變量綁定在實(shí)例變量上 self.main_frame = main_frame # 設(shè)置主窗口標(biāo)題 self.main_frame.title("python聊天室") # 設(shè)置主窗口顏色 self.main_frame.configure(background="white") # 設(shè)置關(guān)閉主窗口的回調(diào)函數(shù) self.main_frame.protocol("WM_DELETE_WINDOW", self.close_main_window) # 聲明寬度,高度變量用于設(shè)置主窗口局中 width = 1300 height = 700 # 獲取屏幕的高度,寬度 screen_width = self.main_frame.winfo_screenwidth() screen_height = self.main_frame.winfo_screenheight() # 設(shè)置主窗口局中的變量 gm_str = "%dx%d+%d+%d" % (width, height, (screen_width - width) / 2, (screen_height - 1.2 * height) / 2) # 設(shè)置主窗口局中 self.main_frame.geometry(gm_str) # 設(shè)置窗口不能改變大小 self.main_frame.resizable(width=False, height=False) # 表情圖片,把圖片轉(zhuǎn)換為PhotoImage, self.p1 = PhotoImage(file='微信表情1.png') self.p2 = PhotoImage(file='微信表情2.png') self.p3 = PhotoImage(file='微信表情3.png') self.p4 = PhotoImage(file='微信表情4.png') self.p5 = PhotoImage(file='微信表情5.png') self.p6 = PhotoImage(file='微信表情6.png') self.p7 = PhotoImage(file='微信表情7.png') self.p8 = PhotoImage(file='微信表情8.png') self.p9 = PhotoImage(file='微信表情9.png') self.p10 = PhotoImage(file='微信表情10.png') # 按鈕圖片,把圖片轉(zhuǎn)換為PhotoImage self.p11 = PhotoImage(file='表情按鈕.png') self.p12 = PhotoImage(file='聊天記錄按鈕.png') # 表情包字典,每一個(gè)表情包對(duì)應(yīng)一個(gè)標(biāo)記 self.dic = {'aa**': self.p1, 'bb**': self.p2, 'cc**': self.p3, 'dd**': self.p4, 'ee**': self.p5, 'ff**': self.p6, 'gg**': self.p7, 'hh**': self.p8, 'jj**': self.p9, 'kk**': self.p10} # 設(shè)置文本標(biāo)簽和位置 self.label1 = Label(self.main_frame, text=" 在線用戶 python聊天室歡迎您:" + self.user_name + " " " " " " + " ", font=("黑體", 20), bg="#00BFFF", fg="white") self.label1.grid(row=0, column=0, ipady=0, padx=0, columnspan=3, sticky=E+W) # 在線用戶列表框 friend_list_var = StringVar() # 聲明列表框變量 # 設(shè)置列表框及位置 self.friend_list = Listbox(self.main_frame, selectmode=NO, listvariable=friend_list_var, bg="#F8F8FF", fg="#00BFFF", font=("宋體", 14), highlightcolor="white", selectbackground="#00BFFF") self.friend_list.grid(row=1, column=0, rowspan=3, sticky=N + S, padx=0, pady=(0, 0)) self.friend_list.bind('<ButtonRelease-1>', self.private_talk) # 綁定列表框點(diǎn)擊事件 # 設(shè)置列表框的縮放比例 main_frame.rowconfigure(1, weight=1) # 設(shè)置主窗口第一行的縮放比例,也就是列表框 main_frame.columnconfigure(1, weight=1) # 設(shè)置列的縮放比例 sc_bar = Scrollbar(self.main_frame, activebackground='red') # 設(shè)置列表框滾動(dòng)條 sc_bar.grid(row=1, column=0, sticky=N + S + E, rowspan=3, pady=(0, 3)) # 設(shè)置滾動(dòng)條的位置 # 列表框和滾動(dòng)條的綁定 sc_bar['command'] = self.friend_list.yview self.friend_list['yscrollcommand'] = sc_bar.set # 設(shè)置消息框的滾動(dòng)條 msg_sc_bar = Scrollbar(self.main_frame) # 設(shè)置滾動(dòng)條 msg_sc_bar.grid(row=1, column=1, sticky=E + N + S, padx=(0, 1), pady=1) # 設(shè)置滾動(dòng)條的位置 # 顯示消息的文本框 self.message_text = Text(self.main_frame, bg="white", height=1, highlightcolor="white", highlightthickness=1) # 顯示消息的文本框不可編輯,當(dāng)需要修改內(nèi)容時(shí)再修改版為可以編輯模式 NORMAL self.message_text.config(state=DISABLED) # 設(shè)置消息框的位置 self.message_text.grid(row=1, column=1, sticky=W + E + N + S, padx=(0, 15), pady=(0, 27)) numIdx = 6 # gif的幀數(shù) # 循環(huán)遍歷動(dòng)圖的幀 frames = [PhotoImage(file='main.gif', format='gif -index %i' % (i)) for i in range(numIdx)] # 創(chuàng)建存儲(chǔ)gif的標(biāo)簽 imgLabel = Label(self.main_frame, height=400, width=490) # 設(shè)置標(biāo)簽的位置 imgLabel.grid(row=1, column=2, sticky=W + E + N + S, rowspan=100, padx=(0, 0), pady=(160, 175)) # 綁定消息框和消息框滾動(dòng)條 msg_sc_bar["command"] = self.message_text.yview self.message_text["yscrollcommand"] = msg_sc_bar.set # 設(shè)置發(fā)送消息框滾動(dòng)條 send_sc_bar = Scrollbar(self.main_frame) # 創(chuàng)建滾動(dòng)條 # 設(shè)置滾動(dòng)條的位置 send_sc_bar.grid(row=2, column=1, sticky=E + N + S, padx=(0, 1), pady=1) # 發(fā)送消息框 self.send_text = Text(self.main_frame, bg="white", height=11, highlightcolor="white", highlightbackground="#444444", highlightthickness=0) # 滾動(dòng)到底部 self.send_text.see(END) # 設(shè)置消息框的位置 self.send_text.grid(row=2, column=1, sticky=W + E + N + S, padx=(0, 15), pady=0) # 綁定發(fā)送消息框和發(fā)送消息框滾動(dòng)條 send_sc_bar["command"] = self.send_text.yview self.send_text["yscrollcommand"] = send_sc_bar.set self.main_frame.bind('<Return>', self.send_message) # 綁定發(fā)送按鈕回車事件 # 設(shè)置發(fā)送消息按鈕及位置,事件處理函數(shù)為send_message button1 = Button(self.main_frame, command=lambda: self.send_message(self), text="發(fā)送", bg="#00BFFF", fg="white", width=13, height=2, font=('黑體', 12),) button1.place(x=650, y=640) # 設(shè)置關(guān)閉窗口按鈕及位置,事件處理函數(shù)為close_main_window button2 = Button(self.main_frame, text="關(guān)閉", bg="white", fg="black", width=13, height=2, font=('黑體', 12), command=self.close_main_window) button2.place(x=530, y=640) # 設(shè)置表情包按鈕及位置,事件處理為實(shí)例方法express botton4 = Button(self.main_frame, command=self.express, image=self.p11, relief=FLAT, bd=0) botton4.place(x=214, y=525) # 設(shè)置聊天記錄按鈕及位置,事件處理為create_window實(shí)例方法 botton5 = Button(self.main_frame, command=self.create_window, image=self.p12, relief=FLAT, bd=0) botton5.place(x=250, y=525) # 設(shè)置刷新用戶列表按鈕及位置,事件處理為refurbish_user函數(shù) botton5 = Button(self.main_frame, command=self.refurbish_user, text="刷新在線用戶", bg="#00BFFF", fg="white", width=13, height=2, font=('黑體', 12),) botton5.place(x=40, y=650) # 定義器靜態(tài)函數(shù),用于刷新gif的幀 @staticmethod def update(idx): frame = frames[idx] idx += 1 # 下一張的序號(hào) imgLabel.configure(image=frame) main_frame.after(100, MainPanel.update, idx % numIdx) # 100毫秒之后繼續(xù)執(zhí)行定時(shí)器函數(shù) # 調(diào)用定時(shí)器函數(shù),執(zhí)行循環(huán)mainloop顯示界面實(shí)例方法 def load(self): MainPanel.update(0) self.main_frame.mainloop() # 聊天記錄按鈕處理事件實(shí)例方法 def create_window(self): top1 = Toplevel() # 創(chuàng)建子窗口 top1.configure(background="#FFFAFA") # 設(shè)置子窗口顏色 # 得到屏幕寬度,高度 screen_width = top1.winfo_screenwidth() screen_height = top1.winfo_screenheight() # 聲明寬度,高度變量 width = 600 height = 650 # 設(shè)置窗口在屏幕局中變量 gm_str = "%dx%d+%d+%d" % (width, height, (screen_width - width) / 2, (screen_height - 1.2 * height) / 2) top1.geometry(gm_str) # 設(shè)置窗口局中 top1.title("聊天記錄") # 設(shè)置窗口標(biāo)題 # 設(shè)置窗口不能改變大小 top1.resizable(width=False, height=False) # 設(shè)置文本標(biāo)簽 title_lable = Label(top1, text="聊天記錄", font=('粗斜體', 20, 'bold italic'), fg="white", bg="#00BFFF") # 設(shè)置文本在窗口的位置 title_lable.pack(ipady=10, fill=X) # 設(shè)置文本框,用戶存放聊天記錄信息 self.chatting_records = Text(top1, bg="white", height=50, highlightcolor="white", highlightthickness=1) # 設(shè)置位置 self.chatting_records.pack(ipady=10, fill=X) # 顯示消息的文本框不可編輯,當(dāng)需要修改內(nèi)容時(shí)再修改版為可以編輯模式 NORMAL self.chatting_records.config(state=DISABLED) # 設(shè)置清除聊天記錄按鈕及位置 botton = Button(top1, text="清空聊天記錄", command=self.clear_chatting_records, bg="#00BFFF", fg="white", width=12, height=2, font=('黑體', 11)) botton.place(x=490, y=600) # 調(diào)用實(shí)例方法顯示聊天記錄 self.show_chatting_records() # 顯示聊天記錄的實(shí)例方法 def show_chatting_records(self): # 設(shè)置文本框可編輯 self.chatting_records.config(state=NORMAL) # 打開用戶的存放聊天記錄的本地文件 f = open("C:/Users/Administrator/PycharmProjects/pythonProject/chatting_records/" + self.user_name + ".txt", 'r') while True: content = f.readline() # 每次讀取一行 ft = tf.Font(family='微軟雅黑', size=13) # 設(shè)置字體樣式和大小變量 # 設(shè)置顏色和字體樣式及大小 self.chatting_records.tag_config("tag_9", foreground="#00BFFF", font=ft) if content != "": # 如果不為空則在文本框最后一行插入文本 self.chatting_records.insert(END, content, 'tag_9') else: self.chatting_records.config(state=DISABLED) #否則則設(shè)置文本框不可編輯 return # 清除聊天記錄按鈕處理實(shí)例方法 def clear_chatting_records(self): # 設(shè)置文本框可編輯 self.chatting_records.config(state=NORMAL) self.chatting_records.delete('1.0', END) # 刪除文本框內(nèi)容 # 打開聊天記錄文件,以覆蓋的形式寫入內(nèi)容 a = open("C:/Users/Administrator/PycharmProjects/pythonProject/chatting_records/" + self.user_name + ".txt", 'w') a.write("") # 插入空字符串,則聊天記錄會(huì)被覆蓋 a.close() # 關(guān)閉 self.chatting_records.config(state=DISABLED) # 設(shè)置文本不可編輯 # 保存聊天記錄實(shí)例方法 def sava_chatting_records(self, content): # 打開聊天記錄文件 a = open("C:/Users/Administrator/PycharmProjects/pythonProject/chatting_records/" + self.user_name + ".txt", 'a') a.write(content) # 寫入信息 a.close() # 關(guān)閉 # 定義表情包按鈕處理事件實(shí)例方法 def express(self): # 如果ee標(biāo)記為0,則彈出表情包,否則銷毀表情包 if self.ee == 0: self.ee = 1 # 把標(biāo)記置為1,用于下次點(diǎn)擊按鈕時(shí)銷毀表情 # 設(shè)置表情圖按鈕及相應(yīng)的事件處理實(shí)例方法 self.b1 = Button(self.main_frame, command=self.bb1, image=self.p1, relief=FLAT, bd=0) self.b2 = Button(self.main_frame, command=self.bb2, image=self.p2, relief=FLAT, bd=0) self.b3 = Button(self.main_frame, command=self.bb3, image=self.p3, relief=FLAT, bd=0) self.b4 = Button(self.main_frame, command=self.bb4, image=self.p4, relief=FLAT, bd=0) self.b5 = Button(self.main_frame, command=self.bb5, image=self.p5, relief=FLAT, bd=0) self.b6 = Button(self.main_frame, command=self.bb6, image=self.p6, relief=FLAT, bd=0) self.b7 = Button(self.main_frame, command=self.bb7, image=self.p7, relief=FLAT, bd=0) self.b8 = Button(self.main_frame, command=self.bb8, image=self.p8, relief=FLAT, bd=0) self.b9 = Button(self.main_frame, command=self.bb9, image=self.p9, relief=FLAT, bd=0) self.b10 = Button(self.main_frame, command=self.bb10, image=self.p10, relief=FLAT, bd=0) # 設(shè)置表情包的位置 self.b1.place(x=207, y=480) self.b2.place(x=255, y=480) self.b3.place(x=303, y=480) self.b4.place(x=351, y=480) self.b5.place(x=399, y=480) self.b6.place(x=207, y=430) self.b7.place(x=255, y=430) self.b8.place(x=303, y=430) self.b9.place(x=351, y=430) self.b10.place(x=399, y=430) else: # 標(biāo)記ee為0則銷毀所有表情按鈕 self.ee = 0 self.b1.destroy() self.b2.destroy() self.b3.destroy() self.b4.destroy() self.b5.destroy() self.b6.destroy() self.b7.destroy() self.b8.destroy() self.b9.destroy() self.b10.destroy() # 所有表情按鈕處理實(shí)例方法 def bb1(self): self.mark('aa**') # 調(diào)用實(shí)例方法,把參數(shù)傳過去 def bb2(self): self.mark('bb**') def bb3(self): self.mark('cc**') def bb4(self): self.mark('dd**') def bb5(self): self.mark('ee**') def bb6(self): self.mark('ff**') def bb7(self): self.mark('gg**') def bb8(self): self.mark('hh**') def bb9(self): self.mark('jj**') def bb10(self): self.mark('kk**') # 處理發(fā)送表情的實(shí)例方法 def mark(self, exp): # 參數(shù)是發(fā)的表情圖標(biāo)記, 發(fā)送后將按鈕銷毀 self.send_mark(exp) # 函數(shù)回調(diào)把標(biāo)記作為參數(shù) # 發(fā)送完摧毀所有表情包 self.b1.destroy() self.b2.destroy() self.b3.destroy() self.b4.destroy() self.b5.destroy() self.b6.destroy() self.b7.destroy() self.b8.destroy() self.b9.destroy() self.b10.destroy() self.ee = 0 # 把標(biāo)記置為0 # 刷新在線列表實(shí)例方法 def refresh_friends(self, online_number, names): self.friend_list.delete(0, END) # 先刪除在線列表 for name in names: # 循環(huán)插入在線用戶 self.friend_list.insert(0, name) self.friend_list.insert(0, "【群聊】") # 在第二行插入群聊 self.friend_list.itemconfig(0, fg="#00BFFF") # 設(shè)置群聊字體顏色 self.friend_list.insert(0, '在線用戶數(shù): ' + str(online_number)) # 在第一行插入在線用戶數(shù) self.friend_list.itemconfig(0, fg="#FF00FF") # 設(shè)置在線用戶數(shù)顏色 # 接受到消息,在文本框中顯示,自己的消息用藍(lán)色,別人的消息用綠色 def show_send_message(self, user_name, content, chat_flag): self.message_text.config(state=NORMAL) # 設(shè)置消息框可編輯 # 設(shè)置發(fā)送的消息的用戶名和時(shí)間變量 title = user_name + " " + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "\n" if content == '* 系統(tǒng)提示: ' + user_name + ' 加入聊天室': # 加入聊天室標(biāo)記處理 ft = tf.Font(family='微軟雅黑', size=13) # 設(shè)置字體樣式和大小變量 # 設(shè)置字體顏色樣式及大小 self.message_text.tag_config("tag_1", foreground="#FF00FF", font=ft) self.message_text.insert(END, content + "\n", 'tag_1') # 在最后一行插入消息 self.message_text.config(state=DISABLED) # 設(shè)置不可編輯 elif content == '* 系統(tǒng)提示: ' + user_name + ' 已離開群聊': # 離開聊天室標(biāo)記處理 ft = tf.Font(family='微軟雅黑', size=13) self.message_text.tag_config("tag_2", foreground="#DC143C", font=ft) self.message_text.insert(END, content + "\n", 'tag_2') self.message_text.config(state=DISABLED) elif user_name == self.user_name: # 如果發(fā)送消息的用戶是自己 if chat_flag == "group_chat": # 如果標(biāo)記是群聊標(biāo)記,則自己的消息用藍(lán)色 print("group_chat====" + chat_flag) ft = tf.Font(family='微軟雅黑', size=13) self.message_text.tag_config("tag_4", foreground="#00BFFF", font=ft) self.message_text.insert(END, title, 'tag_4') self.sava_chatting_records(title) # 調(diào)用實(shí)例方法保存聊天記錄 elif chat_flag == "private_chat": # 如果是標(biāo)記是私聊,則消息用紅色 print("chat_flag====" + chat_flag) ft = tf.Font(family='微軟雅黑', size=13) self.message_text.tag_config("tag_5", foreground="#DC143C", font=ft) self.message_text.insert(END, title, 'tag_5') self.sava_chatting_records(title) else: # # 如果發(fā)送消息的用戶不是自己 if chat_flag == "group_chat": # 如果標(biāo)記是群聊,則消息用綠色 print("group_chat====" + chat_flag) ft = tf.Font(family='微軟雅黑', size=13) self.message_text.tag_config("tag_6", foreground="#008000", font=ft) self.message_text.insert(END, title, 'tag_6') self.sava_chatting_records(title) elif chat_flag == "private_chat": # 標(biāo)記是私聊,則消息用紅色 print("chat_flag====" + chat_flag) ft = tf.Font(family='微軟雅黑', size=13) self.message_text.tag_config("tag_7", foreground="#DC143C", font=ft) self.message_text.insert(END, title, 'tag_7') self.sava_chatting_records(title) if content in self.dic: # 判斷消息是否為表情標(biāo)記 chat_mysql.LogInformation.fing_face(user_name) # 去數(shù)據(jù)庫中讀取用戶的頭像 time.sleep(0.3) # 設(shè)置時(shí)間緩沖,給數(shù)據(jù)庫讀取用戶頭像以及保存到本地文件的時(shí)間緩沖 # 打開圖片 self.img1 = Image.open("用戶頭像.png") # 打開數(shù)據(jù)庫保存的本地文件 # 設(shè)置圖片大小 self.out1 = self.img1.resize((50, 50), Image.ANTIALIAS) # 保存圖片,類型為png self.out1.save(r"用戶頭像1.png", 'png') time.sleep(0.3) # 給修改圖片大小以及保存修改后的圖片留時(shí)間緩存 # 把頭像轉(zhuǎn)化為PhotoImage self.face.append(PhotoImage(file='用戶頭像1.png')) # 把頭像圖片加入到列表中 self.message_text.image_create(END, image=self.face[-1]) # 插入列表最后一個(gè)頭像 self.message_text.insert(END, " : ") self.message_text.image_create(END, image=self.dic[content]) # 插入表情 self.message_text.insert(END, "\n") self.message_text.config(state=DISABLED) # 滾動(dòng)到最底部 self.message_text.see(END) # 內(nèi)容是消息的處理 elif content != '* 系統(tǒng)提示: ' + user_name + ' 加入聊天室' and content != '* 系統(tǒng)提示: ' + user_name + ' 已離開群聊': chat_mysql.LogInformation.fing_face(user_name) time.sleep(0.3) # 打開圖片 self.img2 = Image.open("用戶頭像.png") # 設(shè)置圖片大小 self.out2 = self.img2.resize((50, 50), Image.ANTIALIAS) # 保存圖片,類型為png self.out2.save(r"用戶頭像2.png", 'png') time.sleep(0.3) self.face.append(PhotoImage(file='用戶頭像2.png')) self.message_text.image_create(END, image=self.face[-1]) self.message_text.insert(END, " : ") ft = tf.Font(family='微軟雅黑', size=15) self.message_text.tag_config("tag_8", foreground="#000000", font=ft) self.message_text.insert(END, content, 'tag_8') # 插入消息 self.message_text.config(state=DISABLED) # 滾動(dòng)到最底部 self.message_text.see(END) # 保存聊天記錄 self.sava_chatting_records(content) self.sava_chatting_records("------------------------------------------------------------------------------\n") # 群聊私聊改變標(biāo)簽的實(shí)例方法 def change_title(self, title): self.label1['text'] = title # 清空發(fā)送消息輸入框的實(shí)例方法 def clear_send_text(self): self.send_text.delete('0.0', END) # 獲取消息輸入框內(nèi)容的實(shí)例方法 def get_send_text(self): return self.send_text.get('0.0', END)
注意:上面模塊是給客戶端調(diào)用的,運(yùn)行沒效果,下面給出客戶端調(diào)用聊天界面模塊顯示的效果,下面效果演示了群聊私聊功能,以及加入聊天室和退出聊天室消息
至此所有界面都實(shí)現(xiàn)了,這些界面被封裝成類,劃分成單獨(dú)的模塊,單獨(dú)運(yùn)行是沒效果的,需要通過主函數(shù)也就是客戶端來調(diào)用,然后通過用戶的操作進(jìn)行相應(yīng)的調(diào)用
先告一段落,后面補(bǔ)上服務(wù)器和socket客戶端以及主程序,Mysql代碼模塊
到此這篇關(guān)于Python聊天室?guī)Ы缑鎸?shí)現(xiàn)的示例代碼(tkinter,Mysql,Treading,socket)的文章就介紹到這了,更多相關(guān)Python聊天室?guī)Ы缑鎯?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
django框架創(chuàng)建應(yīng)用操作示例
這篇文章主要介紹了django框架創(chuàng)建應(yīng)用操作,結(jié)合實(shí)例形式分析了Django框架的安裝、創(chuàng)建項(xiàng)目、創(chuàng)建數(shù)據(jù)庫及創(chuàng)建應(yīng)用相關(guān)操作技巧,需要的朋友可以參考下2019-09-09python3中celery異步框架簡(jiǎn)單使用+守護(hù)進(jìn)程方式啟動(dòng)
這篇文章主要介紹了python3中celery異步框架簡(jiǎn)單使用+守護(hù)進(jìn)程方式啟動(dòng),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Python flashtext文本搜索和替換操作庫功能使用探索
本文將深入介紹Python flashtext庫,包括其基本用法、功能特性、示例代碼以及實(shí)際應(yīng)用場(chǎng)景,以幫助大家更好地利用這個(gè)有用的工具2024-01-01Python 如何優(yōu)雅的將數(shù)字轉(zhuǎn)化為時(shí)間格式的方法
這篇文章主要介紹了Python 如何優(yōu)雅的將數(shù)字轉(zhuǎn)化為時(shí)間格式的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09如何使用Python實(shí)現(xiàn)CartPole游戲
在深度強(qiáng)化學(xué)習(xí)內(nèi)容的介紹中,提出了CartPole游戲進(jìn)行深度強(qiáng)化學(xué)習(xí),現(xiàn)在提供一種用Python簡(jiǎn)單實(shí)現(xiàn)Cart Pole游戲的方法,感興趣的朋友跟隨小編一起看看吧2024-07-07