I'm trying to make a Tkinter program that displays what you enter but instead I get a bunch of numbers in the IDLE shell.
My program:
from Tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.text_write = Entry(frame)
self.text_write.pack()
self.Show = Button(frame, text='Show', command=self.Show)
self.Show.pack(side=RIGHT)
def Show(self):
Label(self.text_write.get())
root = Tk()
app = App(root)
root.mainloop()
but instead of text being shown. Numbers appear in my IDLE shell such as:
.4334975024
.4334975600
.4334975672
.4334975816
.4334975960
.4334976104
.4334976248
.4334976392
.4334976536
would somebody please explain the problem and how I could fix it.
def Show(self):
Label(self.text_write.get())
If you replace "Label" with "print" it works (as in, prints the value to stdout)
What the code does as-is is create a new label with a string as a parent (when it wants a window as a parent), and then doesn't attach that label to anything.
You probably want to create the Label object and attach it to the window in init, and then update the label's value in Show()?
Try this:
from Tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.text_write = Entry(frame)
self.text_write.pack()
# rename the show button because you gave a member function the same name
self.show_button = Button(frame, text='Show', command=self.Show)
self.show_button.pack(side=RIGHT)
# create label to display entered text
self.display = Label(frame, text='')
self.display.pack(side=BOTTOM)
def Show(self):
# print text to the standard output
print self.text_write.get()
# show text on label
self.display['text'] = self.text_write.get()
root = Tk()
app = App(root)
root.mainloop()
Related
Hi I am pretty new to tkinter and have being trying to create a button that opens a window then a have a button in the new window the gives a message when pressed. I ran into the problem that the only whay I could get it to recognise the function I wrote was to write it inside the function that opens the second window. I don't know if I have being searching for the wrong things but I can't find how to do this properly. Can someone help me out Here is my code
from tkinter import *
master = Tk()
master.title("frame control")
def win():
window2 = Toplevel()
def open():
stamp = Label(window2, text="Staped").pack()
lab2 = Button(window2,text = "yo ",command = open).pack()
lab1 = Button(master,text = " open a new window" , command = win).pack()
mainloop()
This is your code but with best practises:
import tkinter as tk
def create_stamp():
stamp = tk.Label(window2, text="Stamp")
stamp.pack()
def create_second_win():
global window2
window2 = tk.Toplevel(root)
lab2 = tk.Button(window2, text="Click me", command=create_stamp)
lab2.pack()
root = tk.Tk()
root.title("Frame control")
button = tk.Button(root, text="Open a new window", command=create_second_win)
button.pack()
root.mainloop()
I made window2 a global variable so that I can access it from create_stamp. Generally it is discouraged to use from ... import *. As #Matiiss said, sometimes you can have problems with global variables if you don't keep track of the variable names that you used.
If you want to avoid using global variables and want to use classes, look at this:
import tkinter as tk
class App:
def __init__(self):
self.stamps = []
self.root = tk.Tk()
self.root.title("Frame control")
self.button = tk.Button(self.root, text="Open a new window", command=self.create_second_win)
self.button.pack()
def create_stamp(self):
stamp = tk.Label(self.window2, text="Stamp")
stamp.pack()
self.stamps.append(stamp)
def create_second_win(self):
self.window2 = tk.Toplevel(self.root)
self.lab2 = tk.Button(self.window2, text="Click me", command=self.create_stamp)
self.lab2.pack()
def mainloop(self):
self.root.mainloop()
if __name__ == "__main__":
app = App()
app.mainloop()
As #Matiiss mentioned it would be more organised if you move the second window to its own class. For bigger projects it is a must but in this case you don't have to.
I want to change the text in a label from outside of the class that is creating a Frame.
Here is the current code which I have cut down alot.
import tkinter as tk
import sys
class MyWindow(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.label = tk.Label(self, text="Hello, world")
self.label.pack()
root = tk.Tk()
run = MyWindow(root)
run.label.config(text = 'dddddddddd')
root.geometry('480x320')
MyWindow(root).pack()
root.mainloop()
If I change
self.label = tk.Label(self, text="Hello, world")
to
self.label = tk.Label(root, text="Hello, world")
I end up getting a new label (I'm guessing a new instance of the label I created stacked on top of the last one).
You never pack the MyWindow instance you created and called run, instead you pack a new instance in which you haven't changed the Label text.
Change
MyWindow(root).pack()
to
run.pack()
Is there any way in Python/tkinter to access child elements referring by their variable names, but from an other function?
For example in VBA, it is possible to directly refer to an element of an other window by its name.
For example if I have two windows, UserForm1 and UserForm2 I can change the text value of Label1 of UserForm2 by clicking a button on UserForm1.
Private Sub CommandButton1_Click()
UserForm2.Label1.Caption = "Changed"
End Sub
In tkinter I have found the winfo_children() to access child elements. Is there any way to access them by their names?
See my sample code below:
import tkinter
from tkinter import *
#----------------------------------------------------------------------
def new(parent_window):
""""""
parent_window.withdraw()
global main_window
global new_window
new_window = tkinter.Tk()
new_window.title("My App - New")
label1 = tkinter.Label(new_window, text="NEW")
label1.grid(row=0,column=0,columnspan=3,pady=10,padx=10, sticky="nsw")
b1 = tkinter.Button(new_window, text="Change It", command=lambda: showdashboard(new_window))
b1.grid(row=4,column=1,padx=20,pady=10,sticky="nwse")
b2 = tkinter.Button(new_window, text="Quit", command=lambda: quit())
b2.grid(row=5,column=1,padx=20,pady=10,sticky="nwse")
#----------------------------------------------------------------------
def dashboard(parent_window):
""""""
parent_window.withdraw()
global main_window
global dashboard_window
dashboard_window = tkinter.Tk()
dashboard_window.title("My App - Dashboard")
label1 = tkinter.Label(dashboard_window, text="Dashboard")
label1.grid(row=0,column=0,columnspan=3,pady=10,padx=10, sticky="nsw")
b1 = tkinter.Button(dashboard_window, text="New", command=lambda: new(dashboard_window))
b1.grid(row=4,column=1,padx=20,pady=10,sticky="nwse")
#----------------------------------------------------------------------
def showdashboard(parent_window):
""""""
parent_window.withdraw()
dashboard_window.update()
dashboard_window.deiconify()
#This way it works <<<<<<<<<<<<<<------!!!!!!!
byID=dashboard_window.winfo_children()
byID[0].config(text="change the value")
#But I am looking for somethin like this <<<<<<<<<<<<<<------????
dashboard_window.label1.config(text="changed the value")
#----------------------------------------------------------------------
main_window=tkinter.Tk()
main_window.title("MyApp")
label = tkinter.Label(main_window, text="My App")
label.grid(row=0,column=0,pady=10,padx=10,sticky="nwse")
b1 = tkinter.Button(main_window, text="Dashboard", command=lambda:dashboard(main_window))
b1.grid(row=1,column=0,padx=20,pady=10,sticky="nwse")
main_window.mainloop()
winfo_children() returns an instance of the class associated with the type of widget along with the name that tkinter assigned to the actual tk object.
This means that yes, we can refer to the name of widget, although I'm not sure what advantage this would really give you other than not needing to assign the label to a variable.
from tkinter import *
root = Tk()
Label(root, text="Label1").pack()
label2 = Label(root, name="name", text="Label2")
label2.pack()
print(root.winfo_children())
print(root.nametowidget('.!label'))
print(str(label2))
Button(root, text="Delete label2", command=lambda: root.nametowidget(".name").destroy()).pack()
The above will result in two Label widgets and a Button widget appearing in the window. The first Label is not stored in a variable and yet we can quite happily call it inside the print statement. The second is stored in a variable but you can see that in the command of the Button we don't refer to the variable but the name attribute of the Label.
Bryan Oakley has a fantastic answer here explaining this.
I'm not sure what you mean by names in:
"Is there any way in Python/tkinter to access child elements referring by their names?"
You can access widgets simply by their object references:
# Procedural
import tkinter as tk
def change():
object_reference['text'] = "Changed!"
root = tk.Tk()
object_reference = tk.Label(root, text="This is a label for root-window")
object_reference.pack()
another_window = tk.Toplevel(root)
btn_in_other_window = tk.Button(another_window, text="Change")
btn_in_other_window['command'] = change
btn_in_other_window.pack()
root.mainloop()
or if they were to be defined with more of an object-oriented approach, you can make use of the .(dot) notation:
#oop
import tkinter as tk
class App1(tk.Toplevel):
def __init__(self, master):
super().__init__()
self.label = tk.Label(self, text="This is App1's label")
self.label.pack()
class App2(tk.Toplevel):
def __init__(self, master):
super().__init__(master)
self.button = tk.Button(self, text="This is a App2's button")
self.button.pack()
def change(label):
label['text'] = "Changed!"
if __name__ == '__main__':
root = tk.Tk()
root.withdraw()
app1 = App1(root)
app2 = App2(root)
app2.button['command'] = lambda label=app1.label: change(label)
root.mainloop()
As an alternative, it is possible to get a list of the children widgets of the element window with:
root.update()
lista = list(root.children.values())
Then it is possible to refer to the list elements and do whatever with the widget itself. For example to get the width of the first widget do print(lista[0].winfo_width()).
Warning: I am not sure that the list contains the elements in the same order that the widgets appear in the script, although for me it worked in this order. Hopping someone will write in the comments.
This is my first python personal project. I am wanting to use Tkinter to create a window (GUARDIAN LOCATOR) that asks the user to input a value (enter sailor guardian) into the entry box. The rest of the program is dependent on what the user types in the entry box as I will be having if/else statements reacting to the sailor guardian entered.
The issue I am having is storing what is entered in the entry box as a variable to use in my main file for the if/else statements. I can get the value to print to the prompt window, but I haven't been able to store it successfully to a global variable.
My Tkinter window is in it's own class.
I have tried many different ways of doing this based on similar issues from stackoverflow, but I am getting an error every time. This is my base code that still produces the error.
Class file with the Tkinter window
class GuardianLocator:
def __init__(self, master):
frame = Frame(master)
frame.grid()
master.title("GUARDIAN LOCATOR")
self.locator_label = Label(frame, text="Which Sailor Guardian are you looking for?", width=40, height=2)
self.locator_label.grid()
self.entry = Entry(frame)
self.entry.grid()
self.button1 = Button(frame, text="Search", command=self.guardian_name, pady=2)
self.button1.grid()
def guardian_name(self):
print(self.entry.get())
and in my main working file
root = Tk()
locator = guardian_locator.GuardianLocator(root)
root.mainloop()
This is my test loop to see if it's working.
if locator.guardian_input() is "Sailor Moon":
print("hi")
else:
print("no")
Not sure exactly how your code is organized and where is your "test loop" located, but I assume it is after root.mainloop(). Thus the script can be as follows:
from tkinter import *
class GuardianLocator:
def __init__(self, master):
self._name = ""
frame = Frame(master)
frame.grid()
master.title("GUARDIAN LOCATOR")
self.locator_label = Label(frame, text="Which Sailor Guardian are you looking for?", width=40, height=2)
self.locator_label.grid()
self.entry = Entry(frame)
self.entry.grid()
self.button1 = Button(frame, text="Search", command=self.guardian_name, pady=2)
self.button1.grid()
def guardian_name(self):
self._name = self.entry.get()
print(self.entry.get())
root = Tk()
locator = GuardianLocator(root)
root.mainloop()
# this will be executed after the root window is closed.
print("Name is", locator._name)
Please note self._name = "" in the constructor. This instance variable can be used to store the name provided in your GuardianLocator window.
I'm working on my very first Python GUI and I'm trying to modify this tkinter example, but I simply cannot figure out how to write a callback function for the OK button that will pass on the entered value to the main program.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from Tkinter import Tk, BOTH, StringVar, IntVar
from ttk import Frame, Button, Style, Label, Entry
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Get Value")
self.style = Style()
self.style.theme_use("default")
self.pack(fill=BOTH, expand=1)
valueLabel = Label(self, text="Value: ")
valueLabel.place(x=10, y=10)
value=StringVar(None)
value.set("this is the default value")
valueEntry=Entry(self, textvariable=value)
valueEntry.place(x=70, y=10)
quitButton = Button(self, text="Quit", command=self.quit)
quitButton.place(x=10, y=50)
okButton = Button(self, text="OK", command=self.quit)
okButton.place(x=120, y=50)
def main():
root = Tk()
root.geometry("220x100+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
I've read a gazillion of tutorials, but none of them explains this clearly. Theoretically, I should be able to get the selected value with value.get(), but I keep getting error messages no matter where I put it. Also, AFAIK, I should be able to define a default value with value.set(), but this doesn't seem to have an effect, since the text box is empty when I run the program.
What is the easiest way to pass on values to the main python program after root.mainloop() terminates? (The actual dialog box contains several entry boxes for entering string and integer values.)
I.e. I want to be able to use something like:
root = Tk()
root.geometry("220x100+300+300")
app = Example(root)
root.mainloop()
print value
print value2
print value3
How do I define default values for entry boxes?
Change every occurrence of the value variable with self.value. This should fix it and the default value will be displayed.
UPDATE
from Tkinter import Tk, BOTH, StringVar, IntVar
from ttk import Frame, Button, Style, Label, Entry
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def showMe(self):
print(self.value.get())
def initUI(self):
self.parent.title("Get Value")
self.style = Style()
self.style.theme_use("default")
self.pack(fill=BOTH, expand=1)
valueLabel = Label(self, text="Value: ")
valueLabel.place(x=10, y=10)
self.value=StringVar(None)
self.value.set("this is the default value")
valueEntry=Entry(self, textvariable=self.value)
valueEntry.place(x=70, y=10)
quitButton = Button(self, text="Quit", command=self.quit)
quitButton.place(x=10, y=50)
okButton = Button(self, text="OK", command=self.showMe)
okButton.place(x=120, y=50)
def main():
root = Tk()
root.geometry("220x100+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
Both your quitButton and okButton call the self.quit functions. So no mater what value you enter when you press the OK button you are calling the quit function which has its own problems as well outside the scope of your question.
Try to define value as self.value and make the okButton call a function that does: print self.value.get().