0

I've read at least 25 similar questions on this site, and I simply cannot get this working.

As it stands i'm just trying to build a simple chat app with a client and server. The GUI will be running on a separate thread to the logic to ensure things stay fluid and don't lock up. I've trimmed most of the logic out of the code to isolate the problem

import socket, csv, datetime, tkinter as tk, threading
from tkinter import ttk

interface = tk.Tk()
test = tk.StringVar()
test.set("String Var Test")

class serverInterface():
    def __init__(self, interface):
        global test
        self.messageLog = tk.Text(interface, height=10, state="disabled", yscrollcommand="scrollBar.set")
        self.scrollBar = ttk.Scrollbar(interface, command=self.messageLog.yview).grid(row=0, column=2, sticky="nsew")
        self.messageLog.grid(row=0, column=0, columnspan=2)
        test.trace("w", serverInterface.guiUpdate(self))

    def guiUpdate(self):
        self.messageLog.insert(tk.END, test)


class server():
    def __init__(self):
        global test
        print("Server thread")
        while True:
            test.set("Updated from server object")


interface.title("Server")
serverInterface = threading.Thread(target=serverInterface(interface)) #Create serverInterface object
server = threading.Thread(target=server, daemon=True) # Create server object
server.start()
interface.mainloop()

This results in the console being spammed with Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\thoma\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__ return self.func(*args) TypeError: 'NoneType' object is not callable I've also tried to make use of Queue() as I've seen others suggest, but that just results in a different set of errors and I feel using StringVar() is probably the better way of doing this.

I appreciate that there's probably some lines in this code that don't need to be there, they're just leftovers from all the different attempts at bodging it :/

Any solutions would be appreciated.

1 Answers1

0

The error you're asking about is due to this line:

test.trace("w", serverInterface.guiUpdate(self))

That line is functionally identical to this:

result = serverInterface.guiUpdate(self)
test.trace("w", result)

Since guiUpdate(self) returns None, you're asking tkinter to call None. Hence the error TypeError: 'NoneType' object is not callable

The trace method must be given a callable (ie: a reference to a function). In this specific case you need to use self.guiUpdate.

The trace will automatically pass arguments to the function, so you need to properly define the function to accept those arguments. You also have a bug where you're trying to insert an object (test) in the text widget rather than the text contained in the object.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685