Tkinter OptionMenu error - python

I'm having some issues getting my OptionMenu to work the first issue is that it wont work on it's on i have to use some placeholder label to get it to work. so in the below example it works if i use TaxYear as the master but not if i use TaxYearLi.
The second issue is that for some reason w.set("2018/2019") is not working i get an error that I'm passing a string not a stringvar
Edit: OK I've fixed the StringVar issue and setting a default value need to deffine root as Tk.Tk() if someone also could explain why this needs to be done that would be helpful.
import Tkinter as Tk
root = Tk.Tk()
w = Tk.StringVar
w.set("2018/2019")
TaxYear = Tk.Label(text="Select tax year")
TaxYear.grid(row=1, column=0)
TaxYearLi = Tk.OptionMenu(TaxYearLi, w, "2018/2019")
TaxYearLi.grid(row=1,column=1)
Tk.mainloop()

If you need to declare a variable (root in your case) as TK() is because Tk() is a class in Tkinter code which basicly create the window by asking it to your OS.
so you need to create a variable (some call it root others master, others parents) who's gona be your root/master/parent window and evry widget need to be on this variable.
Now about your OptionMenu, as i mentioned you need to put all your widgets on the main window (root in your case)
import Tkinter as Tk
root = Tk.Tk()
w = Tk.StringVar #in Python3 i need to put StringVar() i don't know about 2.x
w.set("2018/2019")
TaxYear = Tk.Label(text="Select tax year")
TaxYear.grid(row=1, column=0)
TaxYearLi = Tk.OptionMenu(root, w, "2018/2019") #needs to be on the root window
TaxYearLi.grid(row=1,column=1)
root.mainloop()

Related

Why is my tkinter toplevel huge when I stated size constraints?

I'm aware this is probably a newb question, but I have yet to be able to find an answer. Here's a snippet of my code, that has a root window containing a button to open a Toplevel. The Toplevel pulls a random line from a text file to function as a sort of idea generator.
import random, fileinput
import tkinter as tk
from tkinter import *
root = tk.Tk()
root.title('Daydreamer')
#fname should be the file name of the image in working directory
fname = "bg.gif"
bg_image = tk.PhotoImage(file=fname)
#get width and height of image
w = bg_image.width()
h = bg_image.height()
#size window correctly
root.geometry("500x400")
cv = tk.Canvas(width=w, height=h)
cv.pack(side='top', fill='both', expand='yes')
cv.create_image(0,0,image=bg_image,anchor='nw')
#add a frame for text
mainframe=tk.Frame(root)
#new window for inspirations
def inspirations():
top = Toplevel(root)
top.geometry=("100x100")
top.title("Inspiration")
def idea():
textidea=None
for line in fileinput.input('textlist.txt'):
if random.randrange(fileinput.lineno())==0:
textidea=line
entrytext=tk.Text(top)
entrytext.insert(INSERT, textidea)
entrytext.insert(END, "Or press the Inspire Me button again for another idea!")
entrytext.pack()
idea()
top.mainloop()
#add buttons
btn1 = tk.Button(cv, text="Inspire Me", command=inspirations)
btn1.pack(side='left', padx=10, pady=5, anchor='sw')
root.mainloop()
Problem is, that Toplevel always comes out absolutely huge (larger than my root window), which looks incredibly silly for the small amount of content being displayed in it. Am I missing something really minute and stupid here? Help much appreciated.
The problem is that you aren't calling the geometry method, you're replacing it with a string.
Change this:
top.geometry=("100x100")
to this:
top.geometry("100x100")

Python Tkinter Closing Windows [duplicate]

This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 2 years ago.
In creating a Python Tkinter program, I wish to create a button that will close the program. I have tried the
#with master = Tk()
master.quit()
method. And it did absolutely nothing to my program - apart from stopping anything from working, although I received no Tracebacks.
The other method I have tried is:
#with master = Tk()
master.destroy()
This again did nothing to my program - it did give me a traceback error though which was:
_tkinter.TclError: can't invoke "button" command: application has been destroyed
My full code is:
from tkinter import *
master = Tk()
exitbutton = Button(master,text="Exit",(all the other personalization stuff here),command=(master.quit()))
#or I used master.destroy() in the command area.
exitbutton.grid(column=0,row=0)
None of the above methods have worked.
Many Thanks
(For the future)
You must pass the function's name rather than as a callable:
from tkinter import *
master = Tk()
exitbutton = Button(master,text="Exit",command=master.destroy)##dont include the parentheses
##or I used master.destroy() in the command area.
exitbutton.grid(column=0,row=0)
This should fix your problem.
Problem:
The only problem is that you are using parentheses() while passing the function(exit or destroy) to the Button as a command, Which causes it to be executed at the point where it is defined.
Solution:
The solution is to remove the parentheses() while passing the function(exit or destroy) to the Button as a command.
Fixed Code:
from tkinter import *
master = Tk()
exitbutton = Button(master, text="Exit", command=master.quit) # you can also use master.destroy
exitbutton.grid(column=0, row=0)
master.mainloop()
Tip:
As importing all(*) is not a good practice, you should import tkinter as tk
or as anything you want. The only change you will is to add tk. before each object belonging to tkinter.
Then your code will be as follows.
Best Practice:
import tkinter as tk
master = tk.Tk()
exitbutton = tk.Button(master, text="Exit", command=master.quit) # you can also use master.destroy
exitbutton.grid(column=0, row=0)
master.mainloop()
You want to pass a function object into the command keyword, so don't use parentheses. Also you should be using the destroy function for TKinter.
exitbutton = Button(master,text="Exit",(all the other personalization stuff here),command=master.destroy)

Tkinter - can't type into entry widget after restoring the window with wm_state('normal') function

I can't find any solution, so I hope you will help me.
I'm using in my project entry widgets and wm_state('iconic') and wm_state('normal) function. Unfortunatelly after restoring tkinter main window by using wm_state('normal) function I'm unable to use entry widget. Manually minimizing and restoring the window solves the problem. Do you have any idea, how can I avoid it? Below is the testing code I prepared for better understanding. Thank you for the help. I thought root.withdraw() is the solution, but unfortunately, program disappears then from the taskbar, what is not good in my case.
import tkinter as tk
from tkinter import ttk
import time
root = tk.Tk()
root.geometry('200x200')
def test_function():
root.wm_state('iconic')
time.sleep(0.5)
root.wm_state('normal')
button = tk.Button(root, text='MINIMIZE BUTTON', command=test_function)
button.grid(row=0, column=0)
entrywidget = tk.Entry(root, width='10')
entrywidget.grid(row=1, column=0)
entrywidget.focus()
root.mainloop()
Using:
root.withdraw()
root.deiconify()
Instead of:
root.wm_state('iconic')
root.wm_state('normal')
Solves the entry widget problem, but program is no longer visible on the taskbar after root.withdraw() until root.deiconify() method call.

How can I combine this tkinter label and string into one window?

In a program I am working on there is a tkinter label/button which starts the card game (the program I am using) and a other window that has a string stating 'Welcome to the card game'.
Here is the tkinter section of the code:
import tkinter
window = tkinter.Tk()
print()
from tkinter import *
def quit():
global root
root.quit()
root = Tk()
while True:
label = tkinter.Label(window, text = "Welcome to the card game! (During name registration only use characters)").pack()
Button(root, text="Start Game", command=quit).pack()
root.mainloop()
However when I run the program they each appear in their own window screens when it would be more convenient for the user to have the options in one single window.
Is there anyway to merge them?
EDIT - (Having the button and text using root has fixed the problem.)
There is a lot going on here that should not be in such a small set of code.
Lets break it down.
First your imports. You are importing from tkinter multiple times. You only need to import once and you can use everything with the proper prefix. The preferred method is import tkinter as tk this way you don't overwrite any other imports or built in methods.
Next we need to get rid of one of your instances of Tk() as tkinter should only ever have one. For other windows use Toplevel().
In your quit function you do not need to define global as you are not assigning values here so the function will look in the global namespace for root.
Next Lets delete the empty print statement.
Next make sure both your label and button have the same container assigned to them. This is the reason why you are seeing them in different windows.
Next rename your function as quit is a built in method and should not be overwritten.
Lastly we remove the while statement as the mainloop() is already looping the Tk instance. You do not need to manage this yourself.
Here is what your code should look like (a 2nd window serves no purpose here):
import tkinter as tk
def root_quit():
root.quit()
root = tk.Tk()
tk.Label(root, text="Welcome to the card game! (During name registration only use characters)").pack()
tk.Button(root, text="Start Game", command=root_quit).pack()
root.mainloop()
Here is an example using Toplevel just so you can get an idea of how it is used.
import tkinter as tk
def root_quit():
root.quit()
def game_window():
top = tk.Toplevel(root)
tk.Button(top, text='exit', command=root_quit).pack()
root = tk.Tk()
tk.Label(root, text="Welcome to the card game! (During name registration only use characters)").pack()
tk.Button(root, text="Start Game", command=game_window).pack()
root.mainloop()

How do I get an attribute from a Combobox and put it into a variable?

I'm making a project in Tkinter Python and I want users to select an attribute from a Combobox widget and press a button and that attribute will be stored in a variable. I've searched all over the web, but I can't make heads or tails of the code and have no idea how to store this attribute. Can someone tell me how to do this
I've tried the .get thing... (module? widget?) but that is not working and as I said, the internet ain't no help.
This is my basic code with the window and the Combobox:
from tkinter import *
from tkinter import ttk
master = Tk()
ver = ttk.Combobox(master, state="readonly", values=["test1", "test2"]).pack()
Button(master, text="Run").pack()
master.mainloop()
I want to be able to store the selected item in the Combobox and put it in a variable.
pack returns None if you want to assign to a variable, you must do it on a separate line.
If you want action, Button requires a command key word arg to which you assign a callback.
After you have fixed the mistakes, you can use the get method on the Combobox:
import tkinter as tk
from tkinter import ttk
def print_selected():
print(combo.get())
master = tk.Tk()
combo = ttk.Combobox(master, state="readonly", values=["test1", "test2"])
combo.pack()
tk.Button(master, text="Run", command=print_selected).pack()
master.mainloop()

Categories