我正在学习python中的套接字,作为练习我用一个文本框,两个输入框和一个按钮制作了一个python gui app。它的工作方式类似于聊天应用程序,我可以同时运行多个模块,并且在每个模块中,当用户输入文本并单击“发送”时,它会在用户模块的文本框中显示输入的消息,并打开所有其他模块。我已经完成了大部分工作,但问题是它只在按下发送按钮时更新文本框但我想不断更新,所以一旦发送新消息,它就会在屏幕上显示。
到目前为止,这是我的代码:
#!/usr/bin/python
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.root = tk.Tk()
self.create_widgets()
def create_widgets(self):
... #code that creates widgets shortended for readability
#text box widget named self.txt
self.send_btn["command"] = self.send_msg //this handles sending messages to the server when the button is pressed
... #code that creates widgets shortended for readability
def send_msg(self):
s = socket.socket()
host = socket.gethostname()
port = 9999
address = (host, port)
msg=self.name_bar.get() + ": " +self.input_bar.get()
#name bar is another widget so I can enter an identity for each module
#input bar is the entry box where text is entered in
self.input_bar.delete(0, len(msg))
s.connect(address)
s.send(msg.encode())
#Wrote this code that updates textbox when button pushed
#self.txt.insert(tk.END, s.recv(1024))
#self.txt.insert(tk.END, "\n")
#Method I created to call constantly to update textbox
def rcv_msg(self):
s = socket.socket()
host = socket.gethostname()
port = 9999
address = (host, port)
s.connect(address)
if s.recv(1024).decode() != "":
#self.txt.insert(tk.END, s.recv(1024))
#self.txt.insert(tk.END, "\n")
我最近也在做Java,所以如果我的术语混淆了,我会道歉。 我已经制作了更新文本框的方法,我只是不知道如何调用它,我尝试了一个while循环,但它只是阻止应用程序运行。此外,服务器非常简单,只需将客户端上面的消息发送到客户端打开的所有模块。我不知道代码是否必要,我之前被告知要尽量保持问题简短,但如果需要,请告诉我。谢谢!
答案 0 :(得分:1)
你可以听一些新信息。一个不会干扰GUI的独立线程。 (伪代码!)
import socket
from threading import Thread, Lock
import time
class ListenThread(Thread):
def __init__(self, app, lock):
Thread.__init__(self)
self._app = app
self._lock = lock
self._terminating = False
def destroy(self):
self._terminating = True
def run(self):
s = socket.socket()
host = socket.gethostname()
port = 9999
address = (host, port)
while True:
if self._terminating:
break;
if s.recv(1024).decode() != "":
self._lock.acquire()
self._app.post_new_data(s.recv(1024))
self._lock.release()
time.sleep(0.1)
class App(object):
# ...
def __init__(self):
self._lock = Lock()
self._listener = ListenThread(self, self._lock)
self._listener.start()
def post_new_data(self, data):
# Post information to the GUI
def all_data(self):
self._lock.acquire()
# ...
self._lock.release()
def destroy(self):
self._listener.destroy()
# ... Tk mainloop ...
class ListenThread(Thread):
此项目将侦听来自其他连接的新数据,并通过self._app.post_new_data(...)
操作中的run(self)
调用将其发布到GUI。
def run(self):
s = socket.socket()
当我们第一次开始在一个线程上执行时(通过start()
),我们创建了socket并获得连接。这样,所有传入的传输都将通过此路由,以保持我们的GUI免费用于它喜欢做的事情(绘制界面,接受用户输入等)。
while
上的ListenThread.run
循环将继续查找新数据,直到我们杀死该帖子为止。一旦收到数据,它就会将该信息推送到我们的App
。在post_new_data
函数中,您可以将新数据添加到GUI,存储它,无论您想要什么。
def post_new_data(self, data):
self.txt.insert(tk.END, data)
self.txt.insert(tk.END, "\n")