0

I have a python script which has an object of a class which basically opens a Tkinter window. The problem is that when I create the object, the rest of the program stops running because when I create the Tkinter object, it basically starts an infinite while loop. The thing is that I want to change, i.e. the text in a label, but from my other class. My two files look roughly like this:

from tkinter import *
class Panel():
def __init__(self):
    self.root = Tk()
    width = 300
    screen_width = int(self.root.winfo_screenwidth())
    screen_height = int(self.root.winfo_screenheight())
    self.root.geometry(str(width)+"x50+"+str(screen_width-width)+"+0")
    self.root.overrideredirect(True)

    #Create Label
    self.label = Label(self.root, text="Text")
    self.label.pack()
    self.root.mainloop()

def closePanel(self):
    self.root.quit()
    
def editText(self,new_text):
    self.label.configure(text=new_text)
     

And my other class:

from Panel import *
outputPanel = Panel()
outputPanel.editText("New Text")
Luca Tatas
  • 160
  • 1
  • 14
  • 1
    Once you are in the `mainloop` all the functional parts will need to be executed from `Tk` itself. e.g. you should be having `Button`s to execute the `editText` method instead as a command parameter. I recommend you to give [this introduction](http://effbot.org/tkinterbook/tkinter-index.htm#introduction) a go to understand how to use `tkinter`. – r.ook Jul 24 '20 at 21:51

2 Answers2

0

When you create a tkinter application, your whole application should run as a tkinter application. Therefore you need to create the main window at the highest level. Everything else must run within the mainloop of the tkinter program.

In your case, the Panel module instantiates a class which instantiates a tkinter window. You must move that instantiation to the the Panel module itself. Here is my version of you modified code, just to give a basic idea:

from tkinter import *
class Panel():
    def __init__(self, root):     # root is passed when instantiating Panel()
        self.root=root            # make root an instance variable
        width = 300
        screen_width = int(self.root.winfo_screenwidth())
        screen_height = int(self.root.winfo_screenheight())
        self.root.geometry(str(width)+"x50+"+str(screen_width-width)+"+0")
        self.root.overrideredirect(True)
    
        #Create Label
        self.label = Label(self.root, text="Text")
        self.label.pack()
    
    def closePanel(self):
        self.root.quit()
        
    def editText(self,new_text):
        self.label.configure(text=new_text)

root = Tk()                         # create a window at highest level 
outputPanel = Panel(root)           # Panel may be imported and accessed here
outputPanel.editText("New Text")
outputPanel.editText("New Text")
root.mainloop()

There is an excellent post about how to structure a tkinter application here: Best way to structure a tkinter application?

Ronald
  • 2,930
  • 2
  • 7
  • 18
  • thanks, i have already changed my program so now the tkinter class is the main class. but my problem is that i want to constantly update the text of the label. But i dont want to do this with a button but rather with some sort of voice recognition. so i want to recognize what the user said, feed that in a string and call the function. this does work, but sadly i dont know how to probably run the voice recognition multiple times – Luca Tatas Jul 24 '20 at 22:12
  • so i want to show the tkinter window and after some time i want to change the text of the label. but to show the label in the first time i have to call "mainloop()", but when i call this function i am obviously not able to do anything after that – Luca Tatas Jul 24 '20 at 22:15
  • You can run the tkinter mainloop only once, but *within* that loop - that is before you call it-, you can run whatever you want. Therefore it should be always the last command of your application. – Ronald Jul 24 '20 at 22:23
  • yeah, thats the problem. what do i do if i want a voice recognizer constantly listening for lets say "quit" but i also want the tkinter window to show up. then id need to call "mainloop()"to show the window but then id not be able to have another while loop which would realize the voice recognition because i cant have anything after "mainloop()". so i want the window to show but then i also want to execute other commands. is there any possibilty that i could get this to work? probably not huh? – Luca Tatas Jul 24 '20 at 22:55
  • I'm not familiar with your voice recognizer, but I'd, say, you can run it entirely within the mainloop of tkinter. – Ronald Jul 25 '20 at 12:55
0

Put outputPanel.root.mainloop() after outputPanel.editText("New Text") and remove self.root.mainloop().

ENIAC
  • 813
  • 1
  • 8
  • 19