I want to change the text displaying in frame after my mainloop()
has been called. I have created loginfo
function to append text in my string but nothing happens. The GUI gets started and displays the text originally contained in it("hi"), I don't see the text I add through loginfo
function ("hello") and after exiting the GUI I get the below error.
Traceback (most recent call last):
File "1.py", line 5, in <module>
monitor.loginfo()
File "/home/shreyas/Desktop/test/main.py", line 45, in loginfo
self.text.configure(state='normal')
File "/usr/lib/python3.8/tkinter/__init__.py", line 1637, in configure
return self._configure('configure', cnf, kw)
File "/usr/lib/python3.8/tkinter/__init__.py", line 1627, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: invalid command name ".!frame.!text"
My task is to create a function that i will call any time with the text i want to insert. The function will be called after the mainloop is running as i recieve the text to display.
These are the 2 files I created:
main.py
import tkinter
from tkinter import *
class Monitor:
def __init__(self):
self.root = Tk()
self.root.title('Monitor')
self.root.geometry("800x400")
self.root.grid_columnconfigure((0,1), weight=1)
self.root.grid_rowconfigure(0, weight=1)
"""-----------------------------------------------"""
self.console = Frame(self.root,borderwidth=1)
self.console.grid(row = 0, column = 0, sticky = W+E+N+S)
self.console.grid_columnconfigure(0, weight=1)
self.console.grid_rowconfigure(2, weight=1)
self.lbl_c = Label(self.console, text="console",bg='white')
self.lbl_c.grid(row = 1, column = 0, sticky = W+E+N+S)
self.text = tkinter.Text(self.console)
self.text.grid(row = 2, column = 0,rowspan = 3, columnspan = 1, sticky = N+S+E+W)
self.text.insert(tkinter.END,"hi")
self.text.configure(state='disabled')
"""------------------------------------------------"""
self.fm = Frame(self.root,borderwidth=1)
self.fm.grid(row = 0, column = 1, sticky = W+E+N+S)
self.fm.grid_columnconfigure(0, weight=1)
self.fm.grid_rowconfigure(2, weight=1)
self.lbl_fm = Label(self.fm, text="frequency_monitor",bg='white')
self.lbl_fm.grid(row = 1, column = 0, sticky = W+E+N+S)
self.text1 = tkinter.Text(self.fm)
self.text1.grid(row = 2, column = 0,rowspan = 1, columnspan = 1, sticky = N+S+E+W)
self.text1.insert(tkinter.END,"<---------- Frequency Monitor ---------->\n\n"+"Camera100\n"+"Frequency: 9.6 CPU Time: 3.0ms\n"+("----------------------------------------")+"Screen100\n"+"Frequency: 29.8 CPU Time: 6.0ms\n"+("----------------------------------------"))
self.text1.configure(state='disabled')
def loginfo(self):
self.text.configure(state='normal')
self.text.insert(tkinter.END,"hello")
self.text.update()
self.text.configure(state='disabled')
1.py
import main as m
monitor = m.Monitor()
monitor.root.mainloop()
monitor.loginfo()
I use python 3.1 to run my code. Can someone please tell me what's causing the error and how could I achieve the expected result.
update: when i use mainloop() like so
import main as m
monitor = m.Monitor()
monitor.root.mainloop()
monitor.root.update()
monitor.root.update_idletasks()
monitor.loginfo()
i get the same error but when i use while
import main as m
monitor = m.Monitor()
#monitor.root.mainloop()
#monitor.loginfo()
while True:
monitor.root.update()
monitor.root.update_idletasks()
monitor.loginfo()
it updates text and keeps updating it since i called loginfo in while But it doesnot update if i call it outside the while loop.
The code after mainloop()
gets called only after your applications is closed. So after the application is closed, the method is called, but the widgets used in the method is destroyed. So change your code to:
monitor = Monitor()
monitor.loginfo()
monitor.root.mainloop()
This way, the function is called before you exit the GUI. Think of mainloop()
as a while
loop that keeps updating till the window is closed. Technically saying mainloop()
is same as:
while True: # Only exits, because update cannot be used on a destroyed application
root.update()
root.update_idletasks()
Edit:
Since you wanted a delay, you have to add a button or something that calls this method while the GUI is active, an example is to use after
to show the function after some time, like:
monitor = Monitor()
monitor.root.after(1000,monitor.loginfo) # Cause a delay of 1 second or 1000 millisecond
monitor.root.mainloop()