I am trying to update a label, but the code I have written creates a new label each time. I am relatively new to tkinter so I couldn't understand how to apply other answers to my code.
from tkinter import *
import random
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master=master
self.init_window()
def init_window(self):
self.pack(fill=BOTH, expand=1)
testButton=Button(self, text="Press", command=calc)
testButton.pack()
l1=Label(text="")
def testbutton(ans): #creates a new instance of l1 each time, I want to update existing l1
var=StringVar()
l1=Label(textvariable=var) #l1.configure() gives error l1 not defined
var.set(ans)
l1.pack()
def calc():
list1=["a","b","c"]
index=random.randint(0,2)
answer=list1[index]
Window.testbutton(answer)
root=Tk()
root.geometry("400x300")
app=Window(root)
root.mainloop()
Each time the button is pressed, a new label is created, instead of updating the text on the existing label.
This is a simplified version of my actual project, but highlights the issue with labels.
I've tried to use l1.configure(...) inside the testbutton function but then it runs an error that l1 isn't defined.
To avoid creating a new Label each time, you need to make one and save it as an attribute of the Window instance. To make it accessible to the calc() function, you'll also need to pass the Window instance to it as an argument (to avoid using global variables). A common why to do that with tkinter is by using a lamba function as the Button's command= argument and making self the default value for its argument as shown below.
from tkinter import *
import random
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.pack(fill=BOTH, expand=1)
testButton = Button(self, text="Press",
command=lambda win=self: calc(win))
testButton.pack()
self.l1 = Label(text="")
self.l1.pack()
def testbutton(self, ans):
self.l1.configure(text=ans)
def calc(window): # note window argument added
list1 = ["a","b","c"]
index = random.randint(0,2)
answer = list1[index]
window.testbutton(answer)
root = Tk()
root.geometry("400x300")
app = Window(root)
root.mainloop()
You can just use class methods and attributes.
Use a StringVar to change label text:
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.pack(fill=BOTH, expand=1)
testButton = Button(self, text="Press", command=self.calc)
testButton.pack()
self.ltext = StringVar()
l1 = Label(textvariable=self.ltext)
l1.pack()
def testbutton(self, ans):
self.ltext.set(ans)
def calc(self):
list1 = ["a", "b", "c"]
index = random.randint(0, 2)
answer = list1[index]
self.testbutton(answer)
root = Tk()
root.geometry("400x300")
app = Window(root)
root.mainloop()
Related
I have a script, and woult like to have some imputs, outputs (as in the terminal) and a start running script.
How can I do this?
this is what I have for now:
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
exitButton = Button(self, text="Run", command=self.clickExitButton)
exitButton.place(x=0, y=0)
def clickrunButton(self):
run() #this doesnt work
root = Tk()
app = Window(root)
# set window title
root.wm_title("Tkinter window")
# show window
root.mainloop()
You have to place your app in the root, for example with pack(). You also have to change the name of the function, because it doesn't match the one you give to the button command.
from tkinter import *
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack() # Window is packed in its master.
exitButton = Button(self, text="Run", command=self.clickrunButton)
exitButton.pack()
def clickrunButton(self):
self.run() # Now this work
def run(self):
print('Something')
root = Tk()
app = Window(root)
# set window title
root.wm_title("Tkinter window")
# show window
root.mainloop()
I create an instance of TopLevel class inside another class, but can't "withdraw()" the child window
with a call from parent.
import tkinter as tk
class Table(tk.Toplevel):
def __init__(self, master):
tk.Toplevel.__init__(self,master)
self.var_new_t=tk.Toplevel(self.master)
self.t2=Table_2(self.var_new_t)
#Goal is to create a child window and immediately hide it.
self.t2.hide_me()
#self.t2.withdraw() ##Tried a few differnt ways
class Table_2(tk.Toplevel):
def __init__(self, master):
tk.Toplevel.__init__(self,master)
self.master = master
label = tk.Label(self.master, bg='green', text='Second Table')
label.grid()
def hide_me(self):
self.master.withdraw()
root = tk.Tk()
n= Table(root)
tk.Button(root, text="Quit", command=root.destroy).pack()
root.mainloop()
I tried a few other variations to no avail.
Your code is creating two windows. Consider this code:
Table is a toplevel window because it inherits from Toplevel. So, this line creates the Table window:
tk.Toplevel.__init__(self,master)
Then, you create another window when you do this:
self.var_new_t=tk.Toplevel(self.master)
If you inherit from Toplevel you typically shouldn't create a second Toplevel inside unless you explicitly intend to create two windows.
Your code needs to look something like this:
class Table(tk.Toplevel):
def __init__(self, master):
tk.Toplevel.__init__(self,master)
self.t2=Table_2(self)
self.t2.hide_me()
class Table_2(tk.Toplevel):
def __init__(self, master):
tk.Toplevel.__init__(self,master)
self.master = master
label = tk.Label(self, bg='green', text='Second Table')
label.grid()
def hide_me(self):
self.withdraw()
Hey guys I have to classes that both create a Frame. The first one contains a button that is supposed to close its frame. The second frame simply contains a Label. My code should first create the frame with the button and when the button is pressed the second window should show up. What happens is that when pressing the button a "merged" window is created that contains the button and the label.
import tkinter as tk
class Window1(tk.Frame):
def __init__(self):
tk.Frame.__init__(self)
self.grid()
self.btn = tk.Button(self,text = "button",command = self.run)
self.btn.grid(row = 0,column = 0)
def run(self):
tk.Frame.quit(self)
class Window2(tk.Frame):
def __init__(self):
tk.Frame.__init__(self)
self.grid()
self.label = tk.Label(self,text = "label ")
self.label.grid(row = 0,column = 0)
w = Window1()
w.mainloop()
v = Window2()
v.mainloop()
The first picture is before you press the button, the next one after you pressed the button. The problem seems that tk.Frame.quit(self) doesn't work correctly. I tried similar ways to close the window such as:
tk.Frame.destroy(self)
but that doesn't help either.
edit: I solved it by inheriting the class from tk.TK instead of tk.Frame
Frame doesn't create window - it only group elements. Tk() creates window.
To close window you have to destroy() object create by Tk(). But you don't creat it manually root = tk.Tk() so tkinter create it automatically, but you have no access to this root to close it.
If widget doesn't have parent then it uses root and your Frame does it too.
import tkinter as tk
class Window1(tk.Frame):
def __init__(self, master):
# send `root` to `Frame` as its parent
tk.Frame.__init__(self, master)
# `Frame` will keep `master as `self.master`
# so we don't have to do `self.master = master` manually
self.grid()
self.btn = tk.Button(self, text="Hello Button", command=self.run)
self.btn.grid(row=0, column=0)
def run(self):
# use `master` (`root`) to destroy it
self.master.destroy()
class Window2(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.grid()
self.label = tk.Label(self, text="Hello Label")
self.label.grid(row=0, column=0)
root = tk.Tk() # create main window as `root`
Window1(root) # send `root` to `Window1` and later to `Frame`
root.mainloop()
root = tk.Tk()
Window2(root)
root.mainloop()
What i wanted to do is, while typing some words in Entry widget, at the same time changing the characters that are displayed in label widget. Here are the codes:
import tkinter as tk
class App(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.entry = tk.Entry(master=self)
self.entry.pack(side="left")
self.var = tk.StringVar()
self.var.set(self.entry.get)
self.label = tk.Label(master=self)
self.label.pack(side="left")
self.configure_widgets()
self.pack()
def configure_widgets(self):
self.label.configure(textvariable=self.var)
if __name__ == "__main__":
root = tk.Tk()
example = App(master=root)
example.mainloop()
Which parts i should change of the codes? Thank you in advance.
Both Entry and Label accept a variable as a parameter. The entry will set the variable value and the Label will get it.
import tkinter as tk
class App(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.var = tk.StringVar()
self.entry = tk.Entry(master=self, textvariable=self.var)
self.entry.pack(side="left")
self.label = tk.Label(master=self, textvariable=self.var)
self.label.pack(side="left")
self.configure_widgets()
self.pack()
def configure_widgets(self):
self.label.configure(textvariable=self.var)
if __name__ == "__main__":
root = tk.Tk()
example = App(master=root)
example.mainloop()
Similar questions have been asked, but none of them address the particular way my script is constructed:
from Tkinter import *
from ttk import *
class Gui(Frame):
def __init__(self, parent):
Frame.__init__(self, parent) #Gui inherits from built in Frame Class
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Shoes Ware")
self.pack(fill=BOTH, expand=1)
run_val = Entry(self)
run_val["width"] = 5
run_val.place(x=80, y=40)
quit_B = Button(self, text="Submit", command=self.submit)
quit_B.place(x=130, y=170)
def submit(self):
value = run_val.get()
print value
self.quit()
def main():
root = Tk()
root.geometry("300x200+50+50")
app = Gui(root)
root.mainloop()
if __name__ == '__main__':
main()
I get "NameError: global name 'run_val' is not defined" when I hit the submit button. What am I doing wrong here. Right now the print statement is just to check my work. Later on, I'll be using that value in a program.
You are not storing the reference to the Entry widget in initUI.
def initUI(self):
# ...
self.run_val = Entry(self)
self.run_val["width"] = 5
self.run_val.place(x=80, y=40)
Then you can retrieve the value of self.run_val.get() without any problem.