[英]Two-Way communication between classes python (edited + code added)
So, I have classes that need to communicate with each other. 因此,我有一些需要彼此通信的类。 For example, I build client of chat program. 例如,我建立了聊天程序的客户端。 One class handle the sockets, and another class that handle the GUI. 一类处理套接字,另一类处理GUI。 So the GUI class has to get the received data from the sockets class, and in addition has to send the messages through the socket class. 因此,GUI类必须从套接字类获取接收到的数据,此外还必须通过套接字类发送消息。
The problem is that if you make one class contain the other you cant communicate two-way. 问题是,如果使一个类包含另一个类,则无法双向通信。 You need to pass an instance of the parent into the child But I don't think that passing the instance is the right way. 您需要将父实例传递给孩子,但我认为传递实例不是正确的方法。
Whats the best what to do that? 最好的做法是什么?
Here some code for example, hope its clear (please read the comments in the code to understand better): 这里以一些代码为例,希望它清晰(请阅读代码中的注释以更好地理解):
class MainWindow:
def __init__(self, master, username, sock):
# Tkinter Code Here
def insert_msg(self, data): # d_type 1 - msg
self.chat_textbox.insert(END, "\n%s %s" % (datetime.now().strftime('%H:%M:%S'), data))
self.chat_textbox.see(END)
def send_msg(self, data, d_type=SEND_ENUM.TYPE_MSG, arg=0):
data = str(data)
if len(data) >= 1 and d_type == SEND_ENUM.TYPE_MSG:
try:
self.chat_textbox.insert(END, "\n%s [Me] %s" % (datetime.now().strftime('%H:%M:%S'), data))
# For example, here has to use send_msg method from SockHandler class
# self.sock_handler.send_msg(data)
except sock_handling.ConnectionError as error:
self.chat_textbox.insert(END, "\nError: The message was not delivered", "RED")
else:
pass
finally:
self.msg_box_entry.delete(0, 'end')
self.chat_textbox.see(END)
elif d_type != SEND_ENUM.TYPE_MSG:
try:
# also here self.sock_handler.send_msg(data, d_type)
except sock_handling.ConnectionError as error:
pass
else:
pass
class SockHandler:
def __init__(self, client_socket):
# nothing relevant for the Q
def send_msg(self, data, d_type=SEND_ENUM.TYPE_MSG, arg=0):
packed_data = self.pack_data(d_type, arg, data)
if len(data) >= 1 and d_type == SEND_ENUM.TYPE_MSG:
try:
self.client_socket.send(packed_data)
except socket.error:
raise ConnectionError("Connection Error")
finally:
pass
elif d_type != SEND_ENUM.TYPE_MSG:
try:
self.client_socket.send(packed_data)
except socket.error:
raise ConnectionError("Connection Error")
def receive_data(self):
try:
while True:
recv_data = self.client_socket.recv(self.BUFFER)
(d_type,), data = struct.unpack("!I", recv_data[:4]), recv_data[4:]
if d_type == RECV_ENUM.TYPE_MSG:
# For example, here has to use insert_msg method from MainWindow class
elif d_type == RECV_ENUM.TYPE_USER_LIST:
pass
elif d_type == RECV_ENUM.TYPE_POKE:
pass
except socket.error:
self.client_socket.close()
raise ConnectionError("Connection Error")
Why not instantiate the SockHandler
as an attribute to the MainWindow
? 为什么不将SockHandler
实例SockHandler
MainWindow
的属性?
Like this: 像这样:
class MainWindow:
def __init__(self, master, username, sock):
# Tkinter Code Here
self.socket_handler = SockHandler(sock)
Now you can send messages from MainWindow
using self.socket_handler.send_msg
现在您可以使用self.socket_handler.send_msg
从MainWindow
发送消息
For receiving, have your socket store received data where that the MainWindow
can retrieve it. 为了进行接收,请让套接字存储接收到的数据,以便MainWindow
可以在其中检索数据。
Like this: 像这样:
class SockHandler:
def __init__(self, client_socket):
# nothing relevant for the Q
self.received_messages = Queue.Queue()
Now you need to expose a way for MainWindow
to access the received messages. 现在,您需要为MainWindow
提供一种访问已接收消息的方法。 If you want, you can have it directly fetch the messages by querying the queue but I would prefer something like this: 如果需要,您可以通过查询队列直接获取消息,但我希望这样:
# Within the SockHandler Class
def get_next_message():
try:
return self.received_messages.get(True, 5)
except:
return None
It doesn't matter if SockHandler
or MainWindow
handles the Timeout exception in this method. SockHandler
或MainWindow
在此方法中处理Timeout异常无关紧要。 That is up to you. 那取决于你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.