我正在使用podsixnet和tkinter创建聊天服务器/客户端,而我的问题是,当我按'send'将消息发送给聊天室中的其他用户时,文字小部件。
如果我使用注释的代码: print(data['who'] + ": " + data['message'])
,该消息将在控制台上正常打印,但我无法将其显示在GUI上。我真的不知道该如何解决这个问题。以下是我客户的代码,它是Python 3.6。
聊天客户端
import sys
from time import sleep
from sys import stdin, exit
from tkinter import *
from PodSixNet.Connection import connection, ConnectionListener
from _thread import *
root = Tk()
root.title("Chat")
line1 = 1.0
class Client(ConnectionListener):
def __init__(self, host, port):
self.Connect((host, port))
print("Chat client started")
print("Ctrl-C to exit")
# get a nickname from the user before starting
print("Enter your nickname: ")
connection.Send({"action": "nickname", "nickname": stdin.readline().rstrip("n")})
messages = Text(root)
messages.pack()
userInput = StringVar()
textField = Entry(root, text = userInput)
textField.pack(side = BOTTOM, fill = X)
self.message = messages
self.inputField = textField
sendButton = Button(root, text = "Send", command = lambda: self.InputLoop())
sendButton.pack(side = LEFT)
root.mainloop()
def Loop(self):
connection.Pump()
self.Pump()
def InputLoop(self):
connection.Send({"action": "message", "message": self.inputField.get()})
#######################################
### Network event/message callbacks ###
#######################################
def Network_players(self, data):
print("*** players: " + ", ".join([p for p in data['players']]))
def Network_message(self, data):
global line1
# print(data['who'] + ": " + data['message'])
msgGet = data['who'] + ": " + data['message']
self.message.insert(END, msgGet)
line1 += 1.0
# built in stuff
def Network_connected(self, data):
print("You are now connected to the server")
def Network_error(self, data):
print('error:', data['error'][1])
connection.Close()
def Network_disconnected(self, data):
print('Server disconnected')
exit()
if len(sys.argv) != 2:
print("Usage:", sys.argv[0], "host:port")
print("e.g.", sys.argv[0], "localhost:31425")
else:
host, port = sys.argv[1].split(":")
c = Client(host, int(port))
while 1:
c.Loop()
sleep(0.001)
编辑:这是服务器的代码,以防万一。
聊天服务器
import sys
from time import sleep, localtime
from weakref import WeakKeyDictionary
from PodSixNet.Server import Server
from PodSixNet.Channel import Channel
class ClientChannel(Channel):
"""
This is the server representation of a single connected client.
"""
def __init__(self, *args, **kwargs):
self.nickname = "anonymous"
Channel.__init__(self, *args, **kwargs)
def Close(self):
self._server.DelPlayer(self)
##################################
### Network specific callbacks ###
##################################
def Network_message(self, data):
self._server.SendToAll({"action": "message", "message": data['message'], "who": self.nickname})
def Network_nickname(self, data):
self.nickname = data['nickname']
self._server.SendPlayers()
class ChatServer(Server):
channelClass = ClientChannel
def __init__(self, *args, **kwargs):
Server.__init__(self, *args, **kwargs)
self.players = WeakKeyDictionary()
print('Server launched')
def Connected(self, channel, addr):
self.AddPlayer(channel)
def AddPlayer(self, player):
print("New Player" + str(player.addr))
self.players[player] = True
self.SendPlayers()
print("players", [p for p in self.players])
def DelPlayer(self, player):
print("Deleting Player" + str(player.addr))
del self.players[player]
self.SendPlayers()
def SendPlayers(self):
self.SendToAll({"action": "players", "players": [p.nickname for p in self.players]})
def SendToAll(self, data):
[p.Send(data) for p in self.players]
def Launch(self):
while True:
self.Pump()
sleep(0.0001)
# get command line argument of server, port
if len(sys.argv) != 2:
print("Usage:", sys.argv[0], "host:port")
print("e.g.", sys.argv[0], "localhost:31425")
else:
host, port = sys.argv[1].split(":")
s = ChatServer(localaddr=(host, int(port)))
s.Launch()
edit 以下似乎无法解决问题。
您可能需要告诉tkinter.Text
小部件通过调用pack
的所有可用空间,如下所示:
messages.pack(fill=BOTH, expand=1)
这是没有网络部分的客户端的剥离版本。我用它来测试上述解决方案,以发现它没有区别。
from tkinter import *
root = Tk()
messages = Text(root)
messages.pack() # (fill=BOTH, expand=1)
userInput = StringVar()
textField = Entry(root, text = userInput)
textField.pack(side = BOTTOM, fill = X)
def on_send():
msgGet = textField.get()
messages.insert(END, msgGet)
sendButton = Button(root, text = "Send", command = on_send)
sendButton.pack(side = LEFT)
root.mainloop()