Saliva
Saliva

Reputation: 63

Chat Client: tkinter text widget not updating after pressing send

I am creating a chat server/client using PodSixNet and tkinter and my problem is when I press 'send' to send a message to the other users in the chat room it does not display in the the Text widget.

If I use the commented out code:print(data['who'] + ": " + data['message']) the message will print just fine on the console but I just cannot get it to appear on the GUI. I don't really know how to go about solving this issue. Below is the code of my client, it is python 3.6.

Chat Client

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)

EDIT: Here is the code of the server, in case it is needed.

Chat Server

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()

Upvotes: 0

Views: 170

Answers (1)

Mathias Rav
Mathias Rav

Reputation: 2973

EDIT The following doesn't seem to fix the problem.

You probably need to tell the tkinter.Text widget to use all the available space by calling pack as follows:

messages.pack(fill=BOTH, expand=1)

Here's a stripped-down version of the client without the network part. I used it to test the above solution to find that it doesn't make a difference.

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()

Upvotes: 1

Related Questions