Error while trying to insert text to a Text widget from an outside function after mainloop()

362 Views Asked by At

This is the part of the code where im having trouble with:

#file1:

from tkinter import *
import file2
chat = Text()

def createGUI():
    main = Tk()
    main.title("main")
    main.geometry("1280x720")
    main.resizable()

    global chat
    chat = Text(main)
    chat.place(x=775, y=20, height=575, width=450)

    file2.StartThread()

    mainloop()

def InsertMSG(message):
    global chat
    chat.insert(1.0,  message)

if __name__ == '__main__':
    CreateGUI()

In the other file, this is the code:

#file 2:
import file1
import threading

def StartThread():
    listening = threading.Thread(target=listen)
    listening.start()

def listen():
    while True:
        message = input("Enter your message")
        file1.InsertMSG(message)

Quick note, in the actual code the message that's supposed to be printed in the Text widget is being received from a client and transpored throught a socket, but this part works perfectly so it's irelevant to the problem. I'm pretty certain that the Text isn't displayed due to the fact that I'm trying to insert the text after the mainloop() statement, but I have no idea how to fix it. (I've saw some solutions using tk.update_idletasks() and tk.update() but I couldn't seem to make it work. Thanks in advance!

1

There are 1 best solutions below

1
On

When you start file1 then it creates Text(main) but when file2 imports file1 then it doesn't get this chat but it creates new chat = Text() which is not displayed in window. So later it sends text to Text which you can't see.

You should send chat as parameter to function in file2

file2.StartThread(chat)

and it should send it as parameter to listener

def StartThread(chat):
    listening = threading.Thread(target=listen, args=(chat,))
    listening.start()

and it should send it as parameter to InsertMSG

def listen(chat):

    # ...code ...

    file1.InsertMSG(chat, message)

and it should get it

def InsertMSG(chat, message):
    chat.insert(1.0,  message)

This way it will use the same Text as it displays in window.


file1.py

import tkinter as tk  # PEP8: `import *` is not preferred
import file2

def CreateGUI():
    main = tk.Tk()
    main.title("main")
    main.geometry("1280x720")
    main.resizable()

    chat = tk.Text(main)
    chat.place(x=775, y=20, height=575, width=450)

    file2.StartThread(chat)

    main.mainloop()

def InsertMSG(chat, message):
    chat.insert(1.0,  message)

if __name__ == '__main__':
    CreateGUI()

file2.py

import file1
import threading

def StartThread(chat):
    listening = threading.Thread(target=listen, args=(chat,))
    listening.start()

def listen(chat):
    while True:
        message = input("Enter your message: ")
        file1.InsertMSG(chat, message)

PEP 8 -- Style Guide for Python Code


But I would rather use tkinter.Entry() to get text - and it wouldn't need thread.

import tkinter as tk  # PEP8: `import *` is not preferred

def create_gui():   # PEP8: `lower_case_names` for functions
    global chat
    global entry
    
    main = tk.Tk()
    main.title("main")
    #main.geometry("1280x720")
    main.resizable()

    chat = tk.Text(main, bg='white')
    chat.pack(fill='both', expand=True)

    label = tk.Label(main, text="Enter your message: ")
    label.pack()
    
    entry = tk.Entry(main, bg='white')
    entry.pack(fill='x')
    entry.bind('<Return>', insert_message)  # execute `insert_message()` when key `ENTER` pressed in `entry`

    main.mainloop()

def insert_message(event):   # PEP8: `lower_case_names` for functions
    text = entry.get()
    chat.insert('end', text + '\n')
    entry.delete('0', 'end')

if __name__ == '__main__':
    create_gui()

enter image description here