diff --git a/python/test/Client/Chat_main.py b/python/test/Client/Chat_main.py index fb68d3d..d61ad1d 100644 --- a/python/test/Client/Chat_main.py +++ b/python/test/Client/Chat_main.py @@ -1,11 +1,14 @@ import wx +import wx.aui import wx.lib.scrolledpanel as scrolled -import threading +import time +import multiprocessing class ChatFrame(wx.Frame): def __init__(self): - super().__init__(None, size=(1000, 700)) + super().__init__(None, size=(800, 600), title="客户端") + ChatMain_Panel = wx.Panel(self, style=wx.BORDER_SUNKEN) ChatMain_box = wx.BoxSizer(wx.HORIZONTAL) @@ -14,7 +17,7 @@ class ChatFrame(wx.Frame): Function_Panel = wx.Panel(ChatMain_Panel, style=wx.BORDER_RAISED) Function_box = wx.BoxSizer(wx.VERTICAL) Function_Panel.SetSizer(Function_box) - Function_Panel.SetBackgroundColour(wx.Colour(242, 242, 242)) + Function_Panel.SetBackgroundColour(wx.Colour(240, 240, 240)) image_chat = r'./Client/image/chat.png' Chat_bitmap = wx.Bitmap(image_chat, wx.BITMAP_TYPE_PNG) @@ -23,7 +26,7 @@ class ChatFrame(wx.Frame): Function_box.Add(Chat_bitmap_static, 1, wx.EXPAND, 0) Chat_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_chat_button) - Function_box.AddSpacer(30) # 调整这个数字以改变间距大小 + Function_box.AddSpacer(20) # 调整这个数字以改变间距大小 image_connect = r'./Client/image/connect.png' connect_bitmap = wx.Bitmap(image_connect, wx.BITMAP_TYPE_PNG) @@ -32,7 +35,7 @@ class ChatFrame(wx.Frame): Function_box.Add(connect_bitmap_static, 1, wx.EXPAND, 0) connect_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_connect_button) - Function_box.AddSpacer(28) # 调整这个数字以改变间距大小 + Function_box.AddSpacer(20) # 调整这个数字以改变间距大小 image_find = r'./Client/image/find.png' find_bitmap = wx.Bitmap(image_find, wx.BITMAP_TYPE_PNG) @@ -41,7 +44,7 @@ class ChatFrame(wx.Frame): Function_box.Add(find_bitmap_static, 1, wx.EXPAND, 0) find_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_find_button) - Function_box.AddSpacer(340) # 调整这个数字以改变间距大小 + Function_box.AddSpacer(280) # 调整这个数字以改变间距大小 image_site = r'./Client/image/site.png' site_bitmap = wx.Bitmap(image_site, wx.BITMAP_TYPE_PNG) @@ -56,29 +59,65 @@ class ChatFrame(wx.Frame): operate_box = wx.BoxSizer(wx.VERTICAL) - chat_page = self.ChatPage(ChatMain_Panel) # 将 ChatMain_Panel 作为 ChatPage 的 parent - operate_box.Add(chat_page, 1, wx.EXPAND, 0) + self.chat_page = self.ChatPage(ChatMain_Panel) # 将 ChatMain_Panel 作为 ChatPage 的 parent + operate_box.Add(self.chat_page, 1, wx.EXPAND, 5) + self.chat_page.Hide() - ChatMain_box.Add(operate_box, 0, wx.EXPAND, 0) + self.connect_page = self.ConnectPage(ChatMain_Panel) + operate_box.Add(self.connect_page, 1, wx.EXPAND, 5) + self.connect_page.Hide() + + self.site_page = self.SitePage(ChatMain_Panel) + operate_box.Add(self.site_page, 1, wx.EXPAND, 5) + self.site_page.Hide() + + self.find_page = self.FindPage(ChatMain_Panel) + operate_box.Add(self.find_page, 1, wx.EXPAND, 5) + self.find_page.Hide() + + ChatMain_box.Add(operate_box, 1, wx.EXPAND, 5) + + self.chat_page.Show() ChatMain_Panel.SetSizer(ChatMain_box) def click_chat_button(self, event): - print("点击了聊天") + self.chat_page.Hide() + self.connect_page.Hide() + self.site_page.Hide() + self.find_page.Hide() + self.chat_page.Show() + self.Layout() def click_connect_button(self, event): - print("点击了联系人") + self.chat_page.Hide() + self.connect_page.Hide() + self.site_page.Hide() + self.find_page.Hide() + self.connect_page.Show() + self.Layout() def click_site_button(self, event): - print("点击了设置") + self.chat_page.Hide() + self.connect_page.Hide() + self.site_page.Hide() + self.find_page.Hide() + self.site_page.Show() + self.Layout() def click_find_button(self, event): - print("点击了查找") + self.chat_page.Hide() + self.connect_page.Hide() + self.site_page.Hide() + self.find_page.Hide() + self.find_page.Show() + self.Layout() class ChatPage(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, style=wx.BORDER_SUNKEN) ChatPage_main_box = wx.BoxSizer(wx.HORIZONTAL) + self.chat_window_id = [] ChatPage_Contact_person_box = wx.BoxSizer(wx.VERTICAL) self.ChatPage_Contact_person_panel = scrolled.ScrolledPanel(self, -1, style=wx.SUNKEN_BORDER) @@ -86,18 +125,89 @@ class ChatFrame(wx.Frame): self.ChatPage_Contact_person_panel.SetSizer(wx.BoxSizer(wx.VERTICAL)) ChatPage_Contact_person_box.Add(self.ChatPage_Contact_person_panel, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) - ChatPage_main_box.Add(ChatPage_Contact_person_box, 0, wx.EXPAND, 0) - - - + ChatPage_main_box.Add(ChatPage_Contact_person_box, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) + self.chat_tab = wx.aui.AuiNotebook(self, style=wx.aui.AUI_NB_CLOSE_ON_ALL_TABS) + ChatPage_main_box.Add(self.chat_tab, proportion=3, flag=wx.EXPAND | wx.ALL, border=5) self.SetSizer(ChatPage_main_box) + def ChatPage_add_Contact_person(self, Id, Remark, info): + ChatPage_add_Contact_person_box = wx.BoxSizer(wx.VERTICAL) - def ChatPage_add_Contact_person(self,NetName,info): + ChatPage_add_Contact_person_top_box = wx.BoxSizer(wx.HORIZONTAL) + if len(Remark) > 6: + Remark = Remark[:6] + "..." + else: + Remark += ''.join([" " for i in range(max(0, 9 - len(Remark)))]) + ChatPage_add_Contact_person_NetName = wx.StaticText(self.ChatPage_Contact_person_panel, -1, Remark) + ChatPage_add_Contact_person_top_box.Add(ChatPage_add_Contact_person_NetName, 0, wx.ALIGN_LEFT, 0) + ChatPage_add_Contact_person_top_box.AddSpacer(20) - #self.ChatPage_Contact_person_panel.GetSizer().Add(, 0, wx.ALL, 5) - self.ChatPage_Contact_person_panel.Layout() # 重新布局滚动面板 + ChatPage_add_Contact_person_date = wx.StaticText(self.ChatPage_Contact_person_panel, -1, + time.strftime("%Y/%m/%d", time.localtime())) + ChatPage_add_Contact_person_top_box.Add(ChatPage_add_Contact_person_date, 0, wx.ALIGN_CENTER_VERTICAL, 0) + ChatPage_add_Contact_person_box.Add(ChatPage_add_Contact_person_top_box, 0, wx.EXPAND, 0) + if len(info) > 10: + info = info[:10] + "..." + ChatPage_add_Contact_person_info = wx.StaticText(self.ChatPage_Contact_person_panel, -1, info) + ChatPage_add_Contact_person_box.Add(ChatPage_add_Contact_person_info, 0, wx.ALIGN_LEFT, 0) + + self.ChatPage_Contact_person_panel.GetSizer().Add(ChatPage_add_Contact_person_box, 0, wx.ALL, 5) + self.ChatPage_Contact_person_panel.Layout() + self.ChatPage_Contact_person_panel.SetupScrolling() + + ChatPage_add_Contact_person_NetName.Bind(wx.EVT_LEFT_DOWN, + lambda event: self.ChatPage_add_Contact_tab(Id, Remark)) + + def ChatPage_add_Contact_tab(self, Id, Remark): + if Id in self.chat_window_id: + return + self.chat_window_id.append(Id) + + chat_panel = wx.Panel(self.chat_tab) + chat_box = wx.BoxSizer(wx.VERTICAL) + + chat_receive_box = wx.BoxSizer(wx.HORIZONTAL) + chat_receive_text = wx.TextCtrl(chat_panel, style=wx.TE_MULTILINE | wx.TE_READONLY) + chat_receive_box.Add(chat_receive_text, 1, wx.EXPAND, 0) + chat_box.Add(chat_receive_box, 2, wx.EXPAND, 0) + + toolbar = wx.ToolBar(chat_panel) + toolbar.SetToolBitmapSize((16, 16)) # Set the size of the toolbar icons + toolbar.AddTool(wx.ID_ANY, "Tool", wx.Bitmap(wx.Bitmap(r'./Client/image/picture.png'))) + toolbar.AddTool(wx.ID_ANY, "Tool", wx.Bitmap(wx.Bitmap(r'./Client/image/file.png'))) + toolbar.AddTool(wx.ID_ANY, "Tool", wx.Bitmap(wx.Bitmap(r'./Client/image/speech.png'))) + toolbar.AddTool(wx.ID_ANY, "Tool", wx.Bitmap(wx.Bitmap(r'./Client/image/video.png'))) + toolbar.Realize() + toolbar.SetSize((-1, 30)) # Set the size of the toolbar + chat_box.Add(toolbar, 0, wx.EXPAND) + + chat_send_box = wx.BoxSizer(wx.HORIZONTAL) + chat_send_text = wx.TextCtrl(chat_panel, style=wx.TE_MULTILINE) + chat_send_box.Add(chat_send_text, 1, wx.EXPAND, 0) + chat_box.Add(chat_send_box, 1, wx.EXPAND, 0) + + send_button = wx.Button(chat_panel, label='发送') # Create a send button + chat_send_box.Add(send_button, 0, wx.EXPAND | wx.LEFT, 5) # Add the button to the send box + + chat_panel.SetSizer(chat_box) + + self.chat_tab.AddPage(chat_panel, Remark, select=True) + + class ConnectPage(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent) + print("联系人") + + class SitePage(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent) + print("设置") + + class FindPage(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent) + print("查找") diff --git a/python/test/Client/Login.py b/python/test/Client/Login.py index b627039..a154259 100644 --- a/python/test/Client/Login.py +++ b/python/test/Client/Login.py @@ -1,3 +1,5 @@ +import json +import multiprocessing import wx import threading import time @@ -6,6 +8,11 @@ import time class LoginFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, id=1001, title='登录', pos=wx.DefaultPosition, size=(380, 300)) + self.queue_in = multiprocessing.Queue() + self.queue_out = multiprocessing.Queue() + + self.queue_thread = threading.Thread(target=self.queue_recv) + self.queue_thread.start() # 创建菜单栏 menu_bar = wx.MenuBar() @@ -42,8 +49,8 @@ class LoginFrame(wx.Frame): # 创建注册面板 self.sizer = wx.BoxSizer(wx.VERTICAL) - self.login_panel = self.LoginPanel(self) - self.register_panel = self.RegisterPanel(self) + self.login_panel = LoginPanel(self) + self.register_panel = RegisterPanel(self) self.sizer.Add(self.login_panel, 1, wx.EXPAND) self.sizer.Add(self.register_panel, 1, wx.EXPAND) @@ -52,6 +59,10 @@ class LoginFrame(wx.Frame): self.login_panel.Show() + # 主页按钮绑定 + self.Bind(wx.EVT_BUTTON, self.send_login_button, self.login_panel.LoginPanel_login_label) + self.Bind(wx.EVT_BUTTON, self.send_register_button, self.register_panel.RegisterPanel_login_label) + self.SetSizer(self.sizer) def update_status_bar(self, event): @@ -84,111 +95,170 @@ class LoginFrame(wx.Frame): self.register_panel.Hide() self.Layout() - class LoginPanel(wx.Panel): - def __init__(self, parent): - super().__init__(parent) - # 主盒子 - LoginPanel_main_box = wx.BoxSizer(wx.VERTICAL) + def login_page_receive(self, receive_content): + if receive_content["genre"] == '登录': + match receive_content["data"]: + case 0: + # 关闭当前框架 + self.Close() + case -1: + wx.MessageBox('重复登录', '登录', wx.OK | wx.ICON_INFORMATION) + case 1: + wx.MessageBox('密码错误', '登录', wx.OK | wx.ICON_INFORMATION) + case 2: + wx.MessageBox('未找到该账号', '登录', wx.OK | wx.ICON_INFORMATION) + elif receive_content["genre"] == '注册': + wx.MessageBox( + f'注册成功\n网名 : {receive_content["data"]['NetName']} \n账号 : {receive_content["data"]['Id']} \n密码 : {receive_content["data"]['Password']}', + '注册', wx.OK | wx.ICON_INFORMATION) - # 顶部盒子,目前只放了软件名 - LoginPanel_top_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子 - LoginPanel_show_title = wx.StaticText(self, label='登录') - LoginPanel_show_title.SetFont(wx.Font(30, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) - LoginPanel_top_box.Add(LoginPanel_show_title, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 10) - LoginPanel_main_box.Add(LoginPanel_top_box, 0, wx.EXPAND) + def queue_send(self, function, content): + data = json.dumps({"function": function, "content": content}) + self.queue_out.put(data) - # 中部盒子,放账号和密码 - LoginPanel_content_box = wx.BoxSizer(wx.VERTICAL) - # 账号 - LoginPanel_account_box = wx.BoxSizer(wx.HORIZONTAL) - LoginPanel_account_label = wx.StaticText(self, label=' 账号:') - LoginPanel_account_label.SetFont( - wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) - LoginPanel_account_box.Add(LoginPanel_account_label, 0, wx.ALIGN_CENTER_VERTICAL) - self.LoginPanel_account_text = wx.TextCtrl(self, size=(300, 30)) - self.LoginPanel_account_text.SetHint('请输入账号') - LoginPanel_account_box.Add(self.LoginPanel_account_text, 1, wx.ALIGN_CENTER_VERTICAL) - LoginPanel_content_box.Add(LoginPanel_account_box) - # 添加空白控件来增加间距 - LoginPanel_content_box.Add(wx.StaticText(self, label=''), 0, wx.ALL, 5) - # 密码 - LoginPanel_password_box = wx.BoxSizer(wx.HORIZONTAL) - LoginPanel_password_label = wx.StaticText(self, label=' 密码:') - LoginPanel_password_label.SetFont( - wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) - LoginPanel_password_box.Add(LoginPanel_password_label, 0, wx.ALIGN_CENTER_VERTICAL) - self.LoginPanel_password_text = wx.TextCtrl(self, size=(300, 30)) - self.LoginPanel_password_text.SetHint('请输入密码') - LoginPanel_password_box.Add(self.LoginPanel_password_text, 1, wx.ALIGN_CENTER_VERTICAL) - LoginPanel_content_box.Add(LoginPanel_password_box) - LoginPanel_main_box.Add(LoginPanel_content_box, 0, wx.EXPAND) + def queue_recv(self): + while True: + try: + data_json = self.queue_in.get() + data = json.loads(data_json) + self.queue_pick(data) + except Exception as e: + print("Error in queue_recv:", e) - # 底部盒子 - LoginPanel_bottom_box = wx.BoxSizer(wx.VERTICAL) - # 登录按钮 - LoginPanel_login_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子布局 - self.LoginPanel_login_label = wx.Button(self, size=(200, 50), label='登录') - LoginPanel_login_box.AddStretchSpacer() # 添加一个可伸缩的空间,将登录按钮推到垂直中间 - LoginPanel_login_box.Add(self.LoginPanel_login_label, 0, wx.ALIGN_CENTER_HORIZONTAL) # 将登录按钮添加到垂直盒子中 - LoginPanel_login_box.AddStretchSpacer() # 再次添加一个可伸缩的空间,将登录按钮推到垂直中间 - LoginPanel_bottom_box.Add(LoginPanel_login_box, 1, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) # 将垂直盒子添加到底部盒子中,设置垂直和水平居中对齐 - LoginPanel_main_box.Add(LoginPanel_bottom_box, 1, wx.EXPAND) # 将底部盒子添加到主盒子中,使其填满剩余空间 + def queue_pick(self, data): + match data["function"]: + case "server_status": + self.server_status = data["content"] + case "login_page_receive": + self.login_page_receive(data["content"]) - self.SetSizer(LoginPanel_main_box) + def send_login_button(self, event): + if self.server_status: + account = self.login_panel.LoginPanel_account_text.GetValue().strip() + password = self.login_panel.LoginPanel_password_text.GetValue().strip() + content = {'account': account, 'password': password} + target = "服务器" + genre = "登录" + data = {"genre": genre, "target": target, "content": content} + self.queue_send("send_server", data) - class RegisterPanel(wx.Panel): - def __init__(self, parent): - super().__init__(parent) + def send_register_button(self, event): + if self.server_status: + account = self.register_panel.RegisterPanel_account_text.GetValue().strip() + password = self.register_panel.RegisterPanel_password_text.GetValue().strip() + content = {'account': account, 'password': password} + target = "服务器" + genre = "注册" + data = {"genre": genre, "target": target, "content": content} + self.queue_send("send_server", data) - # 主盒子 - RegisterPanel_main_box = wx.BoxSizer(wx.VERTICAL) - # 顶部盒子,目前只放了软件名 - RegisterPanel_top_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子 - RegisterPanel_show_title = wx.StaticText(self, label='注册') - RegisterPanel_show_title.SetFont( - wx.Font(30, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) - RegisterPanel_top_box.Add(RegisterPanel_show_title, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 10) - RegisterPanel_main_box.Add(RegisterPanel_top_box, 0, wx.EXPAND) +class LoginPanel(wx.Panel): + def __init__(self, parent): + super().__init__(parent) + # 主盒子 + LoginPanel_main_box = wx.BoxSizer(wx.VERTICAL) - # 中部盒子,放账号和密码 - RegisterPanel_content_box = wx.BoxSizer(wx.VERTICAL) - # 账号 - RegisterPanel_account_box = wx.BoxSizer(wx.HORIZONTAL) - RegisterPanel_account_label = wx.StaticText(self, label=' 用户名:') - RegisterPanel_account_label.SetFont( - wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) - RegisterPanel_account_box.Add(RegisterPanel_account_label, 0, wx.ALIGN_CENTER_VERTICAL) - self.RegisterPanel_account_text = wx.TextCtrl(self, size=(300, 30)) - self.RegisterPanel_account_text.SetHint('请输入用户名') - RegisterPanel_account_box.Add(self.RegisterPanel_account_text, 1, wx.ALIGN_CENTER_VERTICAL) - RegisterPanel_content_box.Add(RegisterPanel_account_box) - # 添加空白控件来增加间距 - RegisterPanel_content_box.Add(wx.StaticText(self, label=''), 0, wx.ALL, 5) - # 密码 - RegisterPanel_password_box = wx.BoxSizer(wx.HORIZONTAL) - RegisterPanel_password_label = wx.StaticText(self, label=' 密码: ') - RegisterPanel_password_label.SetFont( - wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) - RegisterPanel_password_box.Add(RegisterPanel_password_label, 0, wx.ALIGN_CENTER_VERTICAL) - self.RegisterPanel_password_text = wx.TextCtrl(self, size=(300, 30)) - self.RegisterPanel_password_text.SetHint('请输入密码') - RegisterPanel_password_box.Add(self.RegisterPanel_password_text, 1, wx.ALIGN_CENTER_VERTICAL) - RegisterPanel_content_box.Add(RegisterPanel_password_box) - RegisterPanel_main_box.Add(RegisterPanel_content_box, 0, wx.EXPAND) + # 顶部盒子,目前只放了软件名 + LoginPanel_top_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子 + LoginPanel_show_title = wx.StaticText(self, label='登录') + LoginPanel_show_title.SetFont(wx.Font(30, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) + LoginPanel_top_box.Add(LoginPanel_show_title, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 10) + LoginPanel_main_box.Add(LoginPanel_top_box, 0, wx.EXPAND) - # 底部盒子 - RegisterPanel_bottom_box = wx.BoxSizer(wx.VERTICAL) - # 登录按钮 - RegisterPanel_register_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子布局 - self.RegisterPanel_login_label = wx.Button(self, size=(200, 50), label='确认') - RegisterPanel_register_box.AddStretchSpacer() # 添加一个可伸缩的空间,将登录按钮推到垂直中间 - RegisterPanel_register_box.Add(self.RegisterPanel_login_label, 0, - wx.ALIGN_CENTER_HORIZONTAL) # 将登录按钮添加到垂直盒子中 - RegisterPanel_register_box.AddStretchSpacer() # 再次添加一个可伸缩的空间,将登录按钮推到垂直中间 - RegisterPanel_bottom_box.Add(RegisterPanel_register_box, 1, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) # 将垂直盒子添加到底部盒子中,设置垂直和水平居中对齐 - RegisterPanel_main_box.Add(RegisterPanel_bottom_box, 1, wx.EXPAND) # 将底部盒子添加到主盒子中,使其填满剩余空间 + # 中部盒子,放账号和密码 + LoginPanel_content_box = wx.BoxSizer(wx.VERTICAL) + # 账号 + LoginPanel_account_box = wx.BoxSizer(wx.HORIZONTAL) + LoginPanel_account_label = wx.StaticText(self, label=' 账号:') + LoginPanel_account_label.SetFont( + wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) + LoginPanel_account_box.Add(LoginPanel_account_label, 0, wx.ALIGN_CENTER_VERTICAL) + self.LoginPanel_account_text = wx.TextCtrl(self, size=(300, 30)) + self.LoginPanel_account_text.SetHint('请输入账号') + LoginPanel_account_box.Add(self.LoginPanel_account_text, 1, wx.ALIGN_CENTER_VERTICAL) + LoginPanel_content_box.Add(LoginPanel_account_box) + # 添加空白控件来增加间距 + LoginPanel_content_box.Add(wx.StaticText(self, label=''), 0, wx.ALL, 5) + # 密码 + LoginPanel_password_box = wx.BoxSizer(wx.HORIZONTAL) + LoginPanel_password_label = wx.StaticText(self, label=' 密码:') + LoginPanel_password_label.SetFont( + wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) + LoginPanel_password_box.Add(LoginPanel_password_label, 0, wx.ALIGN_CENTER_VERTICAL) + self.LoginPanel_password_text = wx.TextCtrl(self, size=(300, 30)) + self.LoginPanel_password_text.SetHint('请输入密码') + LoginPanel_password_box.Add(self.LoginPanel_password_text, 1, wx.ALIGN_CENTER_VERTICAL) + LoginPanel_content_box.Add(LoginPanel_password_box) + LoginPanel_main_box.Add(LoginPanel_content_box, 0, wx.EXPAND) - self.SetSizer(RegisterPanel_main_box) + # 底部盒子 + LoginPanel_bottom_box = wx.BoxSizer(wx.VERTICAL) + # 登录按钮 + LoginPanel_login_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子布局 + self.LoginPanel_login_label = wx.Button(self, size=(200, 50), label='登录') + LoginPanel_login_box.AddStretchSpacer() # 添加一个可伸缩的空间,将登录按钮推到垂直中间 + LoginPanel_login_box.Add(self.LoginPanel_login_label, 0, wx.ALIGN_CENTER_HORIZONTAL) # 将登录按钮添加到垂直盒子中 + LoginPanel_login_box.AddStretchSpacer() # 再次添加一个可伸缩的空间,将登录按钮推到垂直中间 + LoginPanel_bottom_box.Add(LoginPanel_login_box, 1, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) # 将垂直盒子添加到底部盒子中,设置垂直和水平居中对齐 + LoginPanel_main_box.Add(LoginPanel_bottom_box, 1, wx.EXPAND) # 将底部盒子添加到主盒子中,使其填满剩余空间 + + self.SetSizer(LoginPanel_main_box) + + +class RegisterPanel(wx.Panel): + def __init__(self, parent): + super().__init__(parent) + + # 主盒子 + RegisterPanel_main_box = wx.BoxSizer(wx.VERTICAL) + + # 顶部盒子,目前只放了软件名 + RegisterPanel_top_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子 + RegisterPanel_show_title = wx.StaticText(self, label='注册') + RegisterPanel_show_title.SetFont( + wx.Font(30, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) + RegisterPanel_top_box.Add(RegisterPanel_show_title, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 10) + RegisterPanel_main_box.Add(RegisterPanel_top_box, 0, wx.EXPAND) + + # 中部盒子,放账号和密码 + RegisterPanel_content_box = wx.BoxSizer(wx.VERTICAL) + # 账号 + RegisterPanel_account_box = wx.BoxSizer(wx.HORIZONTAL) + RegisterPanel_account_label = wx.StaticText(self, label=' 用户名:') + RegisterPanel_account_label.SetFont( + wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) + RegisterPanel_account_box.Add(RegisterPanel_account_label, 0, wx.ALIGN_CENTER_VERTICAL) + self.RegisterPanel_account_text = wx.TextCtrl(self, size=(300, 30)) + self.RegisterPanel_account_text.SetHint('请输入用户名') + RegisterPanel_account_box.Add(self.RegisterPanel_account_text, 1, wx.ALIGN_CENTER_VERTICAL) + RegisterPanel_content_box.Add(RegisterPanel_account_box) + # 添加空白控件来增加间距 + RegisterPanel_content_box.Add(wx.StaticText(self, label=''), 0, wx.ALL, 5) + # 密码 + RegisterPanel_password_box = wx.BoxSizer(wx.HORIZONTAL) + RegisterPanel_password_label = wx.StaticText(self, label=' 密码: ') + RegisterPanel_password_label.SetFont( + wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) + RegisterPanel_password_box.Add(RegisterPanel_password_label, 0, wx.ALIGN_CENTER_VERTICAL) + self.RegisterPanel_password_text = wx.TextCtrl(self, size=(300, 30)) + self.RegisterPanel_password_text.SetHint('请输入密码') + RegisterPanel_password_box.Add(self.RegisterPanel_password_text, 1, wx.ALIGN_CENTER_VERTICAL) + RegisterPanel_content_box.Add(RegisterPanel_password_box) + RegisterPanel_main_box.Add(RegisterPanel_content_box, 0, wx.EXPAND) + + # 底部盒子 + RegisterPanel_bottom_box = wx.BoxSizer(wx.VERTICAL) + # 登录按钮 + RegisterPanel_register_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子布局 + self.RegisterPanel_login_label = wx.Button(self, size=(200, 50), label='确认') + RegisterPanel_register_box.AddStretchSpacer() # 添加一个可伸缩的空间,将登录按钮推到垂直中间 + RegisterPanel_register_box.Add(self.RegisterPanel_login_label, 0, + wx.ALIGN_CENTER_HORIZONTAL) # 将登录按钮添加到垂直盒子中 + RegisterPanel_register_box.AddStretchSpacer() # 再次添加一个可伸缩的空间,将登录按钮推到垂直中间 + RegisterPanel_bottom_box.Add(RegisterPanel_register_box, 1, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) # 将垂直盒子添加到底部盒子中,设置垂直和水平居中对齐 + RegisterPanel_main_box.Add(RegisterPanel_bottom_box, 1, wx.EXPAND) # 将底部盒子添加到主盒子中,使其填满剩余空间 + + self.SetSizer(RegisterPanel_main_box) diff --git a/python/test/Client/Session_server.py b/python/test/Client/Session_server.py index 87f5841..6ae7683 100644 --- a/python/test/Client/Session_server.py +++ b/python/test/Client/Session_server.py @@ -1,3 +1,4 @@ +import multiprocessing import time import socket import json @@ -10,12 +11,41 @@ class Session_server: self.socker_port = 8000 self.server_socket = None self.server_status = False # 服务器状态 + self.queue_in = multiprocessing.Queue() + self.queue_out = multiprocessing.Queue() + + self.queue_thread = threading.Thread(target=self.queue_recv) + self.queue_thread.start() self.link_server_Thread = threading.Thread(target=self.link_server) self.link_server_Thread.start() self.receive_server_Thread = threading.Thread(target=self.receive_server) + def queue_send(self, function, content): + data = json.dumps({"function": function, "content": content}) + self.queue_out.put(data) + print(data) + + def queue_recv(self): + while True: + try: + data_json = self.queue_in.get() + data = json.loads(data_json) + self.queue_pick(data) + except Exception as e: + print("Error in queue_recv:", e) + + def queue_pick(self, data): + match data["function"]: + case "server_status": + self.server_status = data["content"] + case "send_server": + genre = data["content"]["genre"] + target = data["content"]["target"] + content = data["content"]["content"] + self.send_server(genre, target, content) + def link_server(self): while True: if not self.server_status: @@ -31,9 +61,8 @@ class Session_server: except Exception as a: self.server_status = False print("连接错误:" + str(a)) - - def login_page_receive(self, receive_content): - pass + finally: + self.queue_send("server_status", self.server_status) def receive_server(self): while self.server_status: @@ -41,11 +70,12 @@ class Session_server: receive_content_json = self.server_socket.recv(1024).decode('utf-8') receive_content = json.loads(receive_content_json) if receive_content["genre"] in ['注册', '登录']: - self.login_page_receive(receive_content) + self.queue_send("login_page_receive", receive_content) print(receive_content) except Exception as a: print("接收错误:" + str(a)) self.server_status = False + self.queue_send("server_status", self.server_status) def send_server(self, genre, target, content): if self.server_status: @@ -57,4 +87,4 @@ class Session_server: except Exception as a: print("发送错误:" + str(a)) self.server_status = False - + self.queue_send("server_status", self.server_status) diff --git a/python/test/Client/__init__.py b/python/test/Client/__init__.py index 8261eb0..5325e74 100644 --- a/python/test/Client/__init__.py +++ b/python/test/Client/__init__.py @@ -1,48 +1,14 @@ from .Login import * from .Session_server import * +from .Chat_main import * -class Client_main(LoginFrame, Session_server): +class start_all: def __init__(self): - Session_server.__init__(self) # 与服务器会话 - LoginFrame.__init__(self) - - # 主页按钮绑定 - self.Bind(wx.EVT_BUTTON, self.send_login_button, self.login_panel.LoginPanel_login_label) - self.Bind(wx.EVT_BUTTON, self.send_register_button, self.register_panel.RegisterPanel_login_label) - - def send_login_button(self, event): - if self.server_status: - account = self.login_panel.LoginPanel_account_text.GetValue().strip() - password = self.login_panel.LoginPanel_password_text.GetValue().strip() - content = {'account': account, 'password': password} - target = "服务器" - genre = "登录" - self.send_server(genre=genre, target=target, content=content) - - def send_register_button(self, event): - if self.server_status: - account = self.register_panel.RegisterPanel_account_text.GetValue().strip() - password = self.register_panel.RegisterPanel_password_text.GetValue().strip() - content = {'account': account, 'password': password} - target = "服务器" - genre = "注册" - self.send_server(genre=genre, target=target, content=content) - - def login_page_receive(self, receive_content): - if receive_content["genre"] == '登录': - match receive_content["data"]: - case 0: - wx.MessageBox('登录成功', '登录', wx.OK | wx.ICON_INFORMATION) - case -1: - wx.MessageBox('重复登录', '登录', wx.OK | wx.ICON_INFORMATION) - case 1: - wx.MessageBox('密码错误', '登录', wx.OK | wx.ICON_INFORMATION) - case 2: - wx.MessageBox('未找到该账号', '登录', wx.OK | wx.ICON_INFORMATION) - elif receive_content["genre"] == '注册': - wx.MessageBox( - f'注册成功\n网名 : {receive_content["data"]['NetName']} \n账号 : {receive_content["data"]['Id']} \n密码 : {receive_content["data"]['Password']}', - '注册', wx.OK | wx.ICON_INFORMATION) + Session_server() + app = wx.App(False) + frame = LoginFrame() + frame.Show(True) + app.MainLoop() diff --git a/python/test/Client/image/chat.png b/python/test/Client/image/chat.png index 9f5d40d..9b6bcb8 100644 Binary files a/python/test/Client/image/chat.png and b/python/test/Client/image/chat.png differ diff --git a/python/test/Client/image/connect.png b/python/test/Client/image/connect.png index d37d62e..1d2dd4d 100644 Binary files a/python/test/Client/image/connect.png and b/python/test/Client/image/connect.png differ diff --git a/python/test/Client/image/file.png b/python/test/Client/image/file.png new file mode 100644 index 0000000..382d791 Binary files /dev/null and b/python/test/Client/image/file.png differ diff --git a/python/test/Client/image/find.png b/python/test/Client/image/find.png index 953ae60..dbbf010 100644 Binary files a/python/test/Client/image/find.png and b/python/test/Client/image/find.png differ diff --git a/python/test/Client/image/picture.png b/python/test/Client/image/picture.png new file mode 100644 index 0000000..42aa5cb Binary files /dev/null and b/python/test/Client/image/picture.png differ diff --git a/python/test/Client/image/speech.png b/python/test/Client/image/speech.png new file mode 100644 index 0000000..4bbe387 Binary files /dev/null and b/python/test/Client/image/speech.png differ diff --git a/python/test/Client/image/video.png b/python/test/Client/image/video.png new file mode 100644 index 0000000..076fc19 Binary files /dev/null and b/python/test/Client/image/video.png differ diff --git a/python/test/StartClient.py b/python/test/StartClient.py index a5804bf..619bc72 100644 --- a/python/test/StartClient.py +++ b/python/test/StartClient.py @@ -1,8 +1,5 @@ import wx -from Client import Client_main +from Client import start_all if __name__ == '__main__': - app = wx.App() - frame = Client_main() - frame.Show() - app.MainLoop() + start_all() diff --git a/python/test/test.py b/python/test/test.py index 1b89490..9b60e15 100644 --- a/python/test/test.py +++ b/python/test/test.py @@ -1,34 +1,151 @@ -# 服务端 -import socket -import cv2 -import pickle -import struct +import wx +import wx.aui +import wx.lib.scrolledpanel as scrolled +import time -HOST = '127.0.0.1' # 服务器IP地址 -PORT = 65432 # 监听端口 -# 创建Socket -server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -server_socket.bind((HOST, PORT)) -server_socket.listen(5) +class ChatFrame(wx.Frame): + def __init__(self): + super().__init__(None, size=(1000, 700)) -# 接受客户端连接 -connection, address = server_socket.accept() -print('Connected by', address) + ChatMain_Panel = wx.Panel(self, style=wx.BORDER_SUNKEN) + ChatMain_box = wx.BoxSizer(wx.HORIZONTAL) + ChatMain_Panel.SetSizer(ChatMain_box) -# 使用OpenCV捕获视频 -cap = cv2.VideoCapture(0) + Function_Panel = wx.Panel(ChatMain_Panel, style=wx.BORDER_RAISED) + Function_box = wx.BoxSizer(wx.VERTICAL) + Function_Panel.SetSizer(Function_box) + Function_Panel.SetBackgroundColour(wx.Colour(242, 242, 242)) -while True: - ret, frame = cap.read() - # 将视频帧序列化 - data = pickle.dumps(frame) - # 将序列化的数据封装成一个结构体 - message = struct.pack("Q", len(data)) + data - # 发送数据到客户端 - connection.sendall(message) + image_chat = r'./Client/image/chat.png' + Chat_bitmap = wx.Bitmap(image_chat, wx.BITMAP_TYPE_PNG) + Chat_bitmap_static = wx.StaticBitmap(Function_Panel, bitmap=Chat_bitmap, style=wx.BORDER_RAISED) + Chat_bitmap_static.SetToolTip("聊天") + Function_box.Add(Chat_bitmap_static, 1, wx.EXPAND, 0) + Chat_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_chat_button) -# 释放资源 -connection.close() -server_socket.close() -cap.release() + Function_box.AddSpacer(30) # 调整这个数字以改变间距大小 + + image_connect = r'./Client/image/connect.png' + connect_bitmap = wx.Bitmap(image_connect, wx.BITMAP_TYPE_PNG) + connect_bitmap_static = wx.StaticBitmap(Function_Panel, bitmap=connect_bitmap, style=wx.BORDER_RAISED) + connect_bitmap_static.SetToolTip("通讯录") + Function_box.Add(connect_bitmap_static, 1, wx.EXPAND, 0) + connect_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_connect_button) + + Function_box.AddSpacer(28) # 调整这个数字以改变间距大小 + + image_find = r'./Client/image/find.png' + find_bitmap = wx.Bitmap(image_find, wx.BITMAP_TYPE_PNG) + find_bitmap_static = wx.StaticBitmap(Function_Panel, bitmap=find_bitmap, style=wx.BORDER_RAISED) + find_bitmap_static.SetToolTip("查找") + Function_box.Add(find_bitmap_static, 1, wx.EXPAND, 0) + find_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_find_button) + + Function_box.AddSpacer(340) # 调整这个数字以改变间距大小 + + image_site = r'./Client/image/site.png' + site_bitmap = wx.Bitmap(image_site, wx.BITMAP_TYPE_PNG) + site_bitmap_static = wx.StaticBitmap(Function_Panel, bitmap=site_bitmap, style=wx.BORDER_RAISED) + site_bitmap_static.SetToolTip("设置") + Function_box.Add(site_bitmap_static, 1, wx.EXPAND, 0) + site_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_site_button) + + Function_box.Fit(Function_Panel) # 调整面板大小以适应图像 + + ChatMain_box.Add(Function_Panel, 0, wx.EXPAND | wx.ALL, 5) + + operate_box = wx.BoxSizer(wx.VERTICAL) + + chat_page = self.ChatPage(ChatMain_Panel) # 将 ChatMain_Panel 作为 ChatPage 的 parent + operate_box.Add(chat_page, 1, wx.EXPAND, 5) + + ChatMain_box.Add(operate_box, 1, wx.EXPAND, 5) + + ChatMain_Panel.SetSizer(ChatMain_box) + + def click_chat_button(self, event): + print("点击了聊天") + + def click_connect_button(self, event): + print("点击了联系人") + + def click_site_button(self, event): + print("点击了设置") + + def click_find_button(self, event): + print("点击了查找") + + class ChatPage(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent, style=wx.BORDER_SUNKEN) + ChatPage_main_box = wx.BoxSizer(wx.HORIZONTAL) + self.ChatPage_add_Contact_text_box_dick = {} + + ChatPage_Contact_person_box = wx.BoxSizer(wx.VERTICAL) + self.ChatPage_Contact_person_panel = scrolled.ScrolledPanel(self, -1, style=wx.SUNKEN_BORDER) + self.ChatPage_Contact_person_panel.SetupScrolling() # 启用滚动功能 + self.ChatPage_Contact_person_panel.SetSizer(wx.BoxSizer(wx.VERTICAL)) + ChatPage_Contact_person_box.Add(self.ChatPage_Contact_person_panel, proportion=1, flag=wx.EXPAND | wx.ALL, + border=5) + ChatPage_main_box.Add(ChatPage_Contact_person_box, 1, wx.EXPAND, 5) + + self.ChatPage_add_Contact_person(11, "lsy", "asdasddsa") + + self.chat_tab = wx.aui.AuiNotebook(self,style=wx.aui.AUI_NB_CLOSE_ON_ALL_TABS) + ChatPage_main_box.Add(self.chat_tab, 1, wx.EXPAND, 0) + + self.SetSizer(ChatPage_main_box) + + def ChatPage_add_Contact_person(self, Id, Remark, info): + ChatPage_add_Contact_person_box = wx.BoxSizer(wx.VERTICAL) + + ChatPage_add_Contact_person_top_box = wx.BoxSizer(wx.HORIZONTAL) + if len(Remark) > 6: + Remark = Remark[:6] + "..." + else: + Remark += ''.join([" " for i in range(max(0, 9 - len(Remark)))]) + ChatPage_add_Contact_person_NetName = wx.StaticText(self.ChatPage_Contact_person_panel, -1, Remark) + ChatPage_add_Contact_person_top_box.Add(ChatPage_add_Contact_person_NetName, 0, wx.ALIGN_LEFT, 0) + + ChatPage_add_Contact_person_top_box.AddSpacer(20) + + ChatPage_add_Contact_person_date = wx.StaticText(self.ChatPage_Contact_person_panel, -1, + time.strftime("%Y/%m/%d", time.localtime())) + ChatPage_add_Contact_person_top_box.Add(ChatPage_add_Contact_person_date, 0, wx.ALIGN_CENTER_VERTICAL, 0) + ChatPage_add_Contact_person_box.Add(ChatPage_add_Contact_person_top_box, 0, wx.EXPAND, 0) + + if len(info) > 10: + info = info[:10] + "..." + ChatPage_add_Contact_person_info = wx.StaticText(self.ChatPage_Contact_person_panel, -1, info) + ChatPage_add_Contact_person_box.Add(ChatPage_add_Contact_person_info, 0, wx.ALIGN_LEFT, 0) + + self.ChatPage_Contact_person_panel.GetSizer().Add(ChatPage_add_Contact_person_box, 0, wx.ALL, 5) + self.ChatPage_Contact_person_panel.Layout() + self.ChatPage_Contact_person_panel.SetupScrolling() + + ChatPage_add_Contact_person_NetName.Bind(wx.EVT_LEFT_DOWN, lambda event: self.ChatPage_add_Contact_tab(Id, Remark)) + + + def ChatPage_add_Contact_tab(self, Id, Remark): + for i in range(self.chat_tab.GetPageCount()): + if self.chat_tab.GetPageText(i) == Remark: + return + + chat_panel = wx.Panel(self.chat_tab) + chat_box = wx.BoxSizer(wx.VERTICAL) + + chat_receive_box = wx.BoxSizer(wx.HORIZONTAL) + chat_receive_text = wx.TextCtrl(chat_panel, style=wx.TE_MULTILINE) + chat_receive_box.Add(chat_receive_text, 0, wx.EXPAND, 0) + + chat_box.Add(chat_receive_box, 1, wx.EXPAND, 0) + + self.chat_tab.AddPage(chat_panel, wx.Panel(), Remark, select=True) # 将第三个参数改为 wx.Panel(),表示每个页面使用一个新的 Panel 承载控件 + + chat_panel.SetSizer(chat_box) + +app = wx.App() +frame = ChatFrame() +frame.Show() +app.MainLoop() diff --git a/python/test/test2.py b/python/test/test2.py index 0838e74..70d5508 100644 --- a/python/test/test2.py +++ b/python/test/test2.py @@ -17,7 +17,7 @@ payload_size = struct.calcsize("Q") while True: # 从服务器接收数据 while len(data) < payload_size: - packet = client_socket.recv(4*1024) + packet = client_socket.recv(4*10240) if not packet: break data += packet packed_msg_size = data[:payload_size] diff --git a/python/test/test_plan.py b/python/test/test_plan.py index 9470ff0..5a312cd 100644 --- a/python/test/test_plan.py +++ b/python/test/test_plan.py @@ -3,7 +3,7 @@ from Client.Chat_main import ChatFrame if __name__ == '__main__': app = wx.App() - frame = ChatFrame() + frame = ChatFrame("lsy") frame.Show() app.MainLoop()