Working with Tkinter, I am trying to make a label disappear and another appear in its place when a specific option is selected with MenuOption(). Can I accomplish this without the need of a "refresh" button?
updated with a sample of my code:
mGui = Tk()
mGui.geometry('570x130+700+200')
mGui.resizable(width = FALSE, height = FALSE)
mGui.title('Title')
mylist = ['henry', 'tom', 'phil']
someValue = StringVar()
mLabel = Label(text = 'name: ').grid(row = 0, column = 0, sticky = E)
someMenu = OptionMenu(mGui, someValue, *mylist)
someMenu.grid(row = 0, column = 1, sticky = W)
someMenu.config(width = 14, anchor = W)
mGui.mainloop()
So, if someMenu.get() == 'tom' i want to hide mLabel...
so i've added the following:
def something():
print someValue.get()
mylist = ['henry', 'tom', 'phil']
someValue = StringVar()
someValue.trace('w', something)
and am getting TypeError: 'NoneType' object is not callable.. hmmmmm
You can put a trace on someValue, which can call a function whenever the value changes. In that function you can do anything you want, including removing widgets.
This website has an example: http://effbot.org/tkinterbook/variable.htm
if someMenu.get == "tom":
buttonName.pack()
else:
buttonName.pack_forget()
Related
I've recently been working on something where you have a list on names and only when a certain radiobutton has been clicked and a button is pressed does it happen.
from tkinter import *
main_window = Tk()
v = IntVar()
def preorder():
pass
preorder_button = Radiobutton(main_window, text = "PreOrder", indicatoron = 0,
width = 10,
padx = 20,
variable=v,
command=preorder,
value=1)
# Making a Spin wheel
wheel = Spinbox(main_window, from_=1, to=2, width = 3, bd=0, font = (24))
# Shopping cart list
shopping_cart = Text(main_window, width = 30, height = 10, borderwidth = 2, relief = 'groove')
# Making an 'Add To Cart' Button
var = 0
InvoiceList = []
A_List = ['Hello', 'Goodbye']
def AddToCart():
global var, InvoiceList
spinInt = int(wheel.get())
if v == 1:
InvoiceList.append(str(A_List[int(wheel.get()) - 1]))
print(InvoiceList)
shopping_cart.insert(END, InvoiceList[var] + '\n')
var = var + 1
AddCartButton = Button(main_window, text="Add To Cart", width=10, padx=20, command=AddToCart).grid(row=8, column=1, columnspan=2, sticky=SW)
preorder_button.grid(row = 3, column = 1)
wheel.grid(row = 3, column = 3, rowspan = 2)
shopping_cart.grid(row = 6, column = 1, columnspan = 4)
main_window.mainloop()
The problem is though that no matter what I do, i always get an error saying that theres nothing inside the Invoice String, so I'm guessing that it's a problem with how the codes adding a part from the first list to the second list but I have no idea whats wrong with it.
Heres the error i get:
[]
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\jackb\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "c:/Users/jackb/Documents/UNI/IFB104/Assignment 2/online_shopping_app.py", line 332, in AddToCart
shopping_cart.insert(END, InvoiceList[var] + '\n')
IndexError: list index out of range
What this code is supposed to do is while the radiobutton is checked and you press the button, it copies one part of the list according to what the spinbox is set to to another for future use and then displays the added item in the text box for the user to see
I figured it out after a bit. The problem was that the If statement is checking v when it should be checking v.get() instead since v by itself just gives back IntVar(). You can see this here when you do print(v) vs print(v.get()) since v by itself outputs PY_VAR0 but v.get() outputs 1
I'm using Tkinter to create a window with an entry field and a button. When the button is pressed and a certain condition is not met, I need my_label2 to show a specific text, in this case 'Not Valid'. Otherwise, I need the my_label2 to be blank. I have the variable label_text inside a function that is called by the button press, but I get an error saying that label_text is not defined. Can someone help me out with this?
root = tk.Tk()
def my_function():
valid = #this variable is either true or false
if valid :
label_text = ''
else :
label_text = 'Not Valid'
my_label = tk.Label(root, text = "Enter text: ")
my_label.grid(row = 0, column = 0)
my_entry = tk.Entry(root)
my_entry.grid(row = 0, column = 1)
my_button = tk.Button(root, text = "Submit", command = my_function)
my_button.grid(row = 1, column = 1)
my_label2 = tk.Label(root, textvariable = label_text)
my_label2.grid(row = 2, column = 1)
root.mainloop()
Tkinter Variables are different from normal variables. To create one:
label_text = tk.StringVar()
Then, rather than assigning to the variable, you nee to use the set method:
label_text.set('')
or
label_text.set('Not Valid')
See: http://effbot.org/tkinterbook/variable.htm
I am using tkinter to create a small GUI for some Python scripts. For this GUI I need a Combobox named combo with three options:
"none" (the user wants to hand in no data)
"constant" (the user wants to hand in only one value)
"adjustable" (the user wants to hand in more than one value)
Depending on the choice done in combo, a different number of entrys should
appear. The first option should show no entry (and delete all "leftover"
entrys), the second one should show only one entry and the third one should show
two entrys. For me it's no problem to create these entrys but I don't know how
to make them disappear. Once they were created they stay until the GUI is
closed.
I tried something like this:
import tkinter as tk
master = tk.Tk()
var1 = tk.StringVar()
var2 = tk.StringVar()
def submit():
if choice.get() == "none": # all entry boxes schould disappear
entry1.destroy()
entry2.destroy()
if choice.get() == "constant": # only 1 entry box schould be visible
entry1 = tk.Entry(master, textvariable = var1)
entry1.grid(column = 0, row = 1)
entry2.destroy()
if choice.get() == "adjustable": # all entry boxes should be visible
entry1 = tk.Entry(master, textvariable = var1)
entry1.grid(column = 0, row = 1)
entry2 = tk.Entry(master, textvariable = var1)
entry2.grid(column = 0, row = 2)
choice = tk.StringVar(value = "none")
combo = ttk.Combobox(master, textvariable = choice, state = "readonly")
combo["values"] = ("none", "constant", "adjustable")
combo.grid(column = 0, row = 0)
action = tk.Button(master, text = "confirm", command = submit)
action.grid(column=1, row=0)
master.mainloop()
But as I said before, once a entry was created it did not disappear anymore. I
also tried entry.grid_forget() insted of entry.destroy() but this also
didn't work.
I also tryed to declare entry1 and entry1 outside of submit() but then I
don't know how to recreate these entrys once they were destroyed.
Thanks to the help of jasonharper I found a solution while working at another script. The code should look something like this:
import tkinter as tk
from tkinter import ttk
master = tk.Tk()
var1 = tk.StringVar()
var2 = tk.StringVar()
def submit():
if choice.get() == "none": # all entry boxes schould disappear
entry1.grid_remove()
entry2.grid_remove()
if choice.get() == "constant": # only 1 entry box schould be visible
entry1.grid(column = 0, row = 1)
entry2.grid_remove()
if choice.get() == "adjustable": # all entry boxes should be visible
entry1.grid(column = 0, row = 1)
entry2.grid(column = 0, row = 2)
choice = tk.StringVar(value = "none")
combo = ttk.Combobox(master, textvariable = choice, state = "readonly")
combo["values"] = ("none", "constant", "adjustable")
combo.grid(column = 0, row = 0)
entry1 = tk.Entry(master, textvariable = var1)
entry2 = tk.Entry(master, textvariable = var2)
action = tk.Button(master, text = "confirm", command = submit)
action.grid(column=1, row=0)
master.mainloop()
Now all entrys are deleted or created when wanted. To delete the text at the entrys You only have to add entry.delete(0,"end").
I hope this will also help others.
I want to have the text input of this entry box save to a list and then be printed. I cannot have it save the input upon the button press and it just prints the placeholder variable.
names = []
from tkinter import*
class Trip:
def __init__(self, parent):
E_name = "q"
self.En_name = "g"
self.En_name = str(self.En_name)
self.go = Frame(parent, width = 500, height = 450, bg = "snow", pady = 30, padx = 10)
self.go.grid(row = 1, column = 0)
self.go.grid_propagate(0) # to reserve space required for frame
self.tet = Frame(parent, width = 500, height = 450, bg = "snow")
name = Label(self.go, text = "Name:", bg = "snow")
name.grid(row = 1, column = 0, sticky = E)
self.E_name = Entry(self.go, width = 40, textvariable = self.En_name)
self.E_name.grid(row = 1, column = 1, sticky = W, pady = 4)
menuButton = Button(self.go, text = "Continue", command = self.breakeverything)
menuButton.grid(row = 8, column = 1, pady = 4)
def breakeverything(self):
names.append(self.En_name)
print (names[0])
self.E_name.delete(0, "end")
#main routine
if __name__ == "__main__":
root = Tk()
root.title("Traveller Details")
play = Trip(root)
root.geometry("500x450+0+0")
root.mainloop()
A textvariable is supposed to be a tkinter.StringVar(), not a primitive string. Your application looks simple enough that it shouldn't even need it. Take out self.En_name, take out the textvariable, and just retrieve the current value of the Entry widget in breakeverything() (which should no longer be an appropriate name):
def breakeverything(self):
names.append(self.E_name.get())
print(names[-1]) # printing the last name in the list seems more useful
self.E_name.delete(0, "end")
I would also recommend moving names into Trip.__init__ and making it an instance variable like everything else, with self.names = []. It'll make it easier to keep track of scopes.
You're using textvariable incorrectly (you must use one of the special Tkinter variables such as StringVar), but you don't need to use it at all. Simply save a reference to the widget, then call the get method when you want the value:
self.E_name = Entry(self.go, width = 40)
...
print("you entered: " + self.E_name.get())
If you insist o using textvariable, use a StringVar and then call the get method on that instead:
self.En_name = StringVar()
self.E_name = Entry(..., textvariable=self.En_name)
...
print("you entered: " + self.En_name.get())
I started making a function that when a selection in a listbox is double clicked, the selection info(a dictionary) gets returned.
def OnDouble(self, event):
widget = event.widget
selection = widget.curselection()
value = widget.get(selection[0])
What I want is to be able to take that selection that gets returned and edit it's contents. By doing this, any changes in content should show up in the listbox and the list from which it comes from.
Example of value that gets returned with double click:
{'Num Tel/Cel': 'test1', 'Email': 'test1', 'Fecha de Entrega': '', 'Orden Creada:': ' Tuesday, June 23, 2015', 'Nombre': 'test1', 'Num Orden': '1'}
from Tkinter import *
oneThing = {"Name:": "Guido", "Tel.:":"666-6969", "Email:":"foobar#lol.com"}
another = {"Name:": "Philler", "Tel.:":"111-1111", "Email:":"philler#lol.com"}
z = [oneThing, another]
root = Tk()
l = Listbox(root)
l.pack(fill = "both")
l.pack_propagate(True)
[l.insert(END, item) for item in z]
def createPerson(index):
#This is whatever function that creates stuff
def edit():
for i in range(len(labels)):
z[index][labels[i]] = entries[i].get()
print z
top.destroy()
top = Toplevel()
labels = ["Name:", "Tel.:", "Email:"]
i = 0
for text in labels:
Label(top, text = text).grid(column = 0, row = i)
i += 1
e1 = Entry(top)
e1.grid(column = 1, row = 0)
e2 = Entry(top)
e2.grid(column = 1, row = 1)
e3 = Entry(top)
e3.grid(column = 1, row = 2)
Button(top, text = "Submit", command = edit).grid(column = 1, row = 3)
entries = [e1, e2, e3]
#Return reference to toplevel so that root can wait for it to run its course
return top
def edit():
global l, z, root
# Get dictionary from listbox
sel = l.curselection()
if len(sel) > 0:
indexToEdit = z.index(eval(l.get(sel[0])))
l.delete(sel)
root.wait_window(createPerson(indexToEdit))
print z[indexToEdit]
l.insert(sel, z[indexToEdit])
Button(root, text = "Edit", command = edit).pack()
root.mainloop()
Edit: Example now shows a way to edit elements on the fly based on user input; uses Toplevel() widget to accept input.
You can use the functions given in this documentation for editing the selections of a listbox.
Example -
widget.selection_set(<item to add>) # adds an item to the selection
or
widget.selection_clear(<item to remove>) # removes the item from the selection
Documentation for selection_set - here
Documentation for selection_clear - here