Home > Back-end >  How to display values on TKINTER GUI after receiving a message from a client(using sockets) (Python)
How to display values on TKINTER GUI after receiving a message from a client(using sockets) (Python)

Time:11-26

I am working with sockets and Tkinter in python, the idea is simple, I have a client and I am sending a message, and that message has to be displayed on the server's side GUI(without pulsing any button), I coded both sides, but on the server when I am trying to display the message I am having some problems, until now I could already display the sent message, however, each time I send a message from the client a new GUI on the server is being created by my code, and I do understand why this is happening, but I don't know how to solve it, the server side GUI should display only 1 GUI and the message sent by the client should be updated on this latter GUI, without displaying several GUIs, does somebody know how to solve it? I would appreciate it... I am attaching my code for client and server: CLIENT:

from tkinter import *
import socket
HOST = '127.0.0.1'
PORT = 6005

cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
root = Tk()
root.title("client")
root.geometry("300x200")
e = Entry(root, width=50, bg="white", fg="black")
e.pack()

cli.connect((HOST, PORT))
def button_click():
    x =e.get()
    message = str(x)
    cli.send(message.encode('utf-8'))
    count.config(text=message)


OTP = Button(root, text="Send Transfer", padx=20, pady=10, command=button_click)
OTP.pack()
count = Label(root)
count.pack()
root.mainloop()

SERVER:

import socket
import threading
import tkinter
import tkinter.scrolledtext
from tkinter import simpledialog

host='127.0.0.1'
port=6005
server= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen()
balance=0


def handler(client):
    while True:
        try:
            message = client.recv(1024)
            if not message: break
            message=message.decode('utf-8')
            thread = threading.Thread(target=gui, args=(message,))
            thread.start()
        except:
            break
    server.close()
        

def gui(message):
    global balance
    balance=balance int(message)
    print(balance)
    root = tkinter.Tk()
    root.title("Server")
    root.geometry("300x200")
    myLabel=tkinter.Label(root)
    myLabel.config(text=f"You current balance is: {balance}")
    myLabel.pack()
    root.mainloop()    


def receive():
    
    while True:
        try:
            client, address = server.accept()
            print(f"connected with {str(address)}")
            thread = threading.Thread(target=handler, args=(client,))
            thread.start()
        except:
            break

receive()

CodePudding user response:

You should create the server GUI only once in main thread (not in child thread) and run the socket server in child thread instead.

Below is the modified code on server side:

import socket
import threading
import tkinter
from tkinter.scrolledtext import ScrolledText

# client handler
def handler(client):
    while True:
        try:
            message = client.recv(1024)
            if not message: break
            message = message.decode('utf-8')
            update_balance(int(message)) # or float(message)?
        except Exception as ex:
            print("Client handler exception:", ex)
            break
    client.close()

# socket server function
def server():
    host = '127.0.0.1'
    port = 6005
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((host, port))
    server.listen()

    while True:
        try:
            client, address = server.accept()
            print(f"connected with {address}")
            thread = threading.Thread(target=handler, args=(client,), daemon=True)
            thread.start()
        except Exception as ex:
            print("Server exception:", ex)
            break

    server.close()

# function to show the update balance in the text box
def update_balance(amount=0):
    global balance
    balance  = amount
    # avoid updating tkinter widget in a thread
    root.after(1, lambda: logbox.insert("end", f"Your current balance is {balance}\n"))

balance = 0

root = tkinter.Tk()
root.title("Server")
#root.geometry("300x200")

logbox = ScrolledText(root, width=60, height=20)
logbox.pack()
update_balance() # show the initial balance

# create thread for socket server
threading.Thread(target=server, daemon=True).start()

root.mainloop()    
  • Related