Tkinter optionmenu functions - python

Using the Tkinter module, I am try to elicit an action based on the certain selection of an option menu and cancel that action if the option menu is not on the designated selection. The problem is that the program will compile except when both option menus = "treble clef" it somewhat stops working. I have tried using an if statement which works fine except I'm not sure how to get rid of the label it calls.
originalKey = Label(window, text = "Original Key Signature", bg = 'black', fg = 'white')
originalKey.pack()
oKey = StringVar(window)
oKey.set("Select") # initial value
optionold = OptionMenu(window, oKey, "treble clef", "bass clef", "alto clef")
optionold.config(bg = 'black', fg = 'white')
optionold.pack()
#new key selections option menu
def displayKey(str):
while nKey.get() == "treble clef" and oKey.get() == "treble clef":
testpic = Label(window, image = logoimage, bg = 'black')
testpic.pack()
break
newKey = Label(window, text = "New Key Signature", bg = 'black', fg = 'white')
newKey.pack()
nKey = StringVar(window)
nKey.set("select") # initial value
optionnew = OptionMenu(window, nKey, "treble clef", "bass clef", "alto clef",
command = displayKey)
optionnew.config(bg = 'black', fg = 'white')
optionnew.pack()

Related

Tkinter variable is not updating

Everything is working fine except when the program is loaded, I type in a number and try to convert using the button. The issue is that when the button is pressed, it always shows "converted temperature is: 0"
I believe that the variable "var" or the variable "number" is not updating. I am new to tkinter and struggling to figure out why the 0 is not being replaced with the correct temperature.
from tkinter import*
global number
global var
global textbox
number = 0
def convert():
if var.get() == 1:
number = float(textbox.get()) * 1.8 + 32
return number
elif var.get() == 2:
number = (float(textbox.get()) - 32) / 1.8
return number
main = Tk()
var = IntVar()
main.geometry("300x200")
main.configure(bg = 'black')
title = Label(main, text = "Temperature Converter", bg = 'black', fg = 'white' )
textbox = Entry(main, width = 8)
choice1 = Radiobutton(main, selectcolor = 'black', bg = 'black', fg = 'white', text = "Cel - Far", variable=var, value = 1)
choice2 = Radiobutton(main, selectcolor = 'black', bg = 'black', fg = 'white', text = 'Far - Cel', variable=var, value = 2)
button = Button(main, text = 'Convert', command = convert)
answer = Label(main, text = "Converted Temperature is: " + str(number), bg = 'black', fg = 'white' )
title.pack()
textbox.pack()
choice1.pack()
choice2.pack()
button.pack()
answer.pack()
main.resizable(False, False)
main.mainloop()
Change your convert function to:
def convert():
if var.get() == 1:
number = float(textbox.get()) * 1.8 + 32
elif var.get() == 2:
number = (float(textbox.get()) - 32) / 1.8
answer.config(text="Converted Temperature is: " + str(number))
The .config(...) method changes the label. In this case it changes its text attribute.

Tkinter: All radio buttons are already selected

it is my first time using tkinter. I have an entry box on the first window, and I created radio buttons on different windows. The problem is that they are already selected before I click any of them. How can I change all buttons to be deselected?
I am not sure if my codes are right or not.
from tkinter import *
from tkinter import messagebox
class SortingHat:
# Constructor
def __init__(self):
# Create main window
self.__main_window = Tk()
self.__main_window.geometry('300x200')
self.__main_window.title('Sorting Hat')
bg_image = PhotoImage(file = "HarryPotterlogo1.png")
bg_label = Label(self.__main_window, image = bg_image, bd=0)
bg_label.grid(row=1, column=0)
bg_label.image = bg_image
self.__first_label = Label(self.__main_window, text = \
'Enter Your Name.', fg = 'gold', bg = 'brown4')
self.__first_label.grid(row=2, column=0)
# Create Entry box
self.__entry = Entry(self.__main_window)
self.__entry.bind('<Return>', self.entry_action)
self.__entry.grid(row=3, column=0)
self.__button = Button(self.__main_window, text = 'Enter', \
fg = 'white', bg = 'black', command = self.action)
self.__button.grid(row=3, column=0, sticky = 'E')
self.__next_button = Button(text = 'Next', height = 1, width = 10, \
fg = 'black', bg = 'white', command = self.next1)
self.__next_button.grid(row=4, column=0, sticky ='W')
# Create OK button and Quit button
self.__quit_button = Button(text='Quit', height = 1, width = 10, \
command=self.__main_window.destroy)
self.__quit_button.grid(row=4, column=0, sticky = 'E')
def next1(self):
self.__new_window1 = Tk()
self.__new_window1.configure(bg = 'brown4')
self.__new_window1.title('Question 1')
self.__second_label = Label(self.__new_window1, text = \
'What is your favorite color? (10 points)', \
fg = 'gold', bg = 'brown4')
self.__second_label.grid(row=0, column=0, sticky = 'W')
# Question Radiobutton
self.__rb_var1 = IntVar()
# Create First question Radiobutton widgets
self.__rb1 = Radiobutton(self.__new_window1, text='a. Red and Gold', fg ='red', \
bg = 'brown4', variable=self.__rb_var1, value = 1)
self.__rb2 = Radiobutton(self.__new_window1, text='b. Green and Silver', fg = 'green', \
bg = 'brown4', variable=self.__rb_var1 , value = 2)
self.__rb3 = Radiobutton(self.__new_window1, text='c. Yellow and Black', fg = 'gold', \
bg = 'brown4', variable=self.__rb_var1, value = 3)
self.__rb4 = Radiobutton(self.__new_window1, text='d. Blue and Bronze', fg = 'blue', \
bg = 'brown4', variable=self.__rb_var1, value = 4)
self.__rb1.grid(row=1, column=0)
self.__rb2.grid(row=2, column=0)
self.__rb3.grid(row=3, column=0)
self.__rb4.grid(row=4, column=0)
I want all buttons to be deselected when the program starts.
The problem is that you shouldn't be opening a new Tk() window, instead you should be creating a new Toplevel() window, that will fix the issue.
So instead of self.__new_window1 = Tk() use self.__new_window1 = Toplevel()
Try this.
def next1(self):
self.__new_window1 = Toplevel()
self.__new_window1.configure(bg = 'brown4')
self.__new_window1.title('Question 1')
# Question Radiobutton
self.__rb_var1 = IntVar()
# Create First question Radiobutton widgets
self.__rb1 = Radiobutton(self.__new_window1, text='a. Red and Gold', fg ='red', bg = 'brown4', variable=self.__rb_var1, value = 1)
self.__rb2 = Radiobutton(self.__new_window1, text='b. Green and Silver', fg='green', bg='brown4', variable=self.__rb_var1, value=2)
self.__rb3 = Radiobutton(self.__new_window1, text='c. Yellow and Black', fg='gold', bg='brown4', variable=self.__rb_var1, value=3)
self.__rb4 = Radiobutton(self.__new_window1, text='d. Blue and Bronze', fg='blue', bg='brown4', variable=self.__rb_var1, value=4)
self.__rb1.grid(row=1, column=0)
self.__rb2.grid(row=2, column=0)
self.__rb3.grid(row=3, column=0)
self.__rb4.grid(row=4, column=0)
Try
self.__rb1.deselect()
self.__rb2.deselect()
self.__rb3.deselect()
self.__rb4.deselect()

Tkinter buttons not performing command [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 4 years ago.
I am trying to create a counter for Jeopardy so that my Mom and I can keep score. Currently the program that I am creating is assigning the values to variables and then not performing the command when I press the button in the window. I am running Python 2.7.13.`
import Tkinter as tk
root = tk.Tk()
root.title("Jeopardy Scores")
def ChangeScore(User,Value):
if User == 1:
Score = int(JScore.get())
JScore.set(Score + Value)
#J = JScore.get()
#print J
#SayHi()
else:
Score = int(MScore.get())
MScore.set(Score + Value)
#M = MScore.get()
#print M
#SayHi()
#def SayHi(*args):
#print 'hi'
MainFrame = tk.Frame(root)
MainFrame.grid(column=0, row=0)
MainFrame.columnconfigure(0, weight=1)
MainFrame.rowconfigure(0, weight=1)
JScore = tk.StringVar()
MScore = tk.StringVar()
JScore.set(0)
MScore.set(0)
JL = tk.Label(MainFrame, text = "Joey's Score", padx = 10, pady = 2)
JL.config(bg = 'blue', fg = 'yellow', font = ('Arial',30, 'bold'))
JL.grid(column = 0, row = 0)
ML = tk.Label(MainFrame, text = "Mom's Score", padx = 10, pady = 2)
ML.config(bg = 'blue', fg = 'yellow', font = ('Arial',30, 'bold'))
ML.grid(column = 1, row = 0)
JSS = tk.Label(MainFrame, textvariable=JScore ,padx = 122)
JSS.config(bg = 'blue', fg = 'yellow', font = ('Arial',30, 'bold'))
JSS.grid(column = 0, row = 1)
MSS = tk.Label(MainFrame, textvariable = MScore,padx = 122)
MSS.config(bg = 'blue', fg = 'yellow', font = ('Arial',30, 'bold'))
MSS.grid(column = 1, row = 1)
for i in range(1,6):
Score = tk.IntVar()
Score.set(i*200)
Score1 = 200*i
JButton = tk.Button(MainFrame, textvariable = Score, command =
ChangeScore(1,Score1))
JButton.grid(column = 0, row = 1+i)
MButton = tk.Button(MainFrame, textvariable = Score, command =
ChangeScore(2,Score1))
MButton.grid(column = 1, row = 1+i)
JButton = tk.Button(MainFrame, text = '400', command = ChangeScore(1,400))
JButton.grid(column = 0, row = 7)
root.mainloop()
The code runs and produces this Window
Note that no buttons have been pressed when the picture was taken. It appears that all the buttons are 'being pressed' when the code runs and then nothing happens when i press the buttons afterwards.
I have no experience with Tkinter beyond the small information that has allowed me to do this and I have a bit more experience with Python. I am mainly doing this as an excerise for myself to improve my coding and to acutally use for Jeopardy!. Any help would be appreciate
Here the command parameter for Button should be a callable. You should not call the function yourself and pass the return value to it. Instead, you provide a function that is to be called later.
So change you code to things like
command=lambda: ChangeScore(1, 400)
to create a lambda to be called later will solve the problem.

Multiple Buttons to change the colours of multiple labels TKINTER, PYTHON?

So I have multiple buttons
and i need the buttons of each name:
i.e. Violet button to turn the LABEL above it into violet,
and purple button to turn the above LABEL purple.
AND the reset button resets them all to grey.
AND if someone could fix my code so that the spacing of the "RESET" button is between purple and Blue (but still a row down), that'd be greatly appreciated.
WHAT MY CODE DOES NOW:
It turns all of the boxes all the colours.
How do I make it so when I press the one button, the one label changes colour AND I wish to do this in one function if possible (i've already thought of making multiple functions and thought this would be nicer).
Import the Tkinter functions
from tkinter import *
# Create a window
the_window = Tk()
# Give the window a title
the_window.title('MULTI Button Colour')
#Variables
window_font = ('Arial', 8)
button_size = 10
label_size = 7
margin_size_width = 10
margin_size_height = 2
label_violet = Label(the_window, padx = margin_size_width, pady = margin_size_height, bg = 'grey', width = label_size)
label_violet.grid(row = 0, column = 0)
label_purple = Label(the_window, padx = margin_size_width, pady = margin_size_height, bg = 'grey', width = label_size)
label_purple.grid(row = 0, column = 1)
label_blue = Label(the_window, padx = margin_size_width, pady = margin_size_height, bg = 'grey', width = label_size)
label_blue.grid(row = 0, column = 2)
label_green = Label(the_window, padx = margin_size_width, pady = margin_size_height, bg = 'grey', width = label_size)
label_green.grid(row = 0, column = 3)
def change_colour():
if violet_button:
label_violet['bg'] = 'violet'
if purple_button:
label_purple['bg'] = 'purple'
if blue_button:
label_blue['bg'] = 'blue'
if green_button:
label_green['bg'] = 'green'
# if reset_button:
# label_violet['bg'] = 'grey'
# label_purple['bg'] = 'grey'
# label_blue['bg'] = 'grey'
# label_green['bg'] = 'grey'
violet_button = Button(the_window, text = 'Violet', width = button_size,
font = window_font, command = change_colour)
purple_button = Button(the_window, text = 'Purple', width = button_size,
font = window_font, command = change_colour)
blue_button = Button(the_window, text = 'Blue', width = button_size,
font = window_font, command = change_colour)
green_button = Button(the_window, text = 'Green', width = button_size,
font = window_font, command = change_colour)
reset_button = Button(the_window, text = 'RESET', width = button_size,
font = window_font, command = change_colour)
#----------------------------------------------------------------
violet_button.grid(row = 1, column = 0, padx = margin_size_width, pady = margin_size_height)
purple_button.grid(row = 1, column = 1, padx = margin_size_width, pady = margin_size_height)
blue_button.grid(row = 1, column = 2, padx = margin_size_width, pady = margin_size_height)
green_button.grid(row = 1, column = 3, padx = margin_size_width, pady = margin_size_height)
reset_button.grid(row = 2, column = 1, pady = margin_size_height)
# Start the event loop to react to user inputs
the_window.mainloop()
This should do what you want:
def get_function(cmd):
def change_colour():
if 'violet' == cmd:
label_violet['bg'] = 'violet'
if 'purple' == cmd:
label_purple['bg'] = 'purple'
if 'blue' == cmd:
label_blue['bg'] = 'blue'
if 'green' == cmd:
label_green['bg'] = 'green'
if 'reset' == cmd:
label_violet['bg'] = 'grey'
label_purple['bg'] = 'grey'
label_blue['bg'] = 'grey'
label_green['bg'] = 'grey'
return change_colour
violet_button = Button(the_window, text = 'Violet', width = button_size,
font = window_font, command = get_function('violet'))
purple_button = Button(the_window, text = 'Purple', width = button_size,
font = window_font, command = get_function('purple'))
blue_button = Button(the_window, text = 'Blue', width = button_size,
font = window_font, command = get_function('blue'))
green_button = Button(the_window, text = 'Green', width = button_size,
font = window_font, command = get_function('green'))
reset_button = Button(the_window, text = 'RESET', width = button_size,
font = window_font, command = get_function('reset'))
For the issue with the reset button, just specifie the columnspan argument of the grid function:
reset_button.grid(row = 2, column = 1, pady = margin_size_height, columnspan = 2)
You have a lot of code in there that you copy / paste. Computers are really good at repeating things with a few variables changed. You could argue that that's ALL a computer is good at. So by doing that yourself, you are doing the computer's job. Also, you are making more work for your future self if you want to change something later. It's much better to put things in a single location, so that you can make a single change later instead of changing for every label. I can see you thought about this a little already since you have so many constants. Taking that one step further is to make a "constant" widget that all your instances copy from. It's a little advanced, but here's how you would do that:
import tkinter as tk
# Constants (aka variables that don't change during the program run)
BUTTON_SIZE = 10
FONT=('Arial', 8)
class Corey(tk.Frame):
'''a new widget that combines a Label and a Button'''
instances = []
def __init__(self, master=None, color='grey', **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.color = color
self.lbl = tk.Label(self, bg=color) # set initial color
self.lbl.grid(sticky='nsew') # sticky makes the label as big as possible
btn = tk.Button(self, text=color.title(), width=BUTTON_SIZE, command=self.colorize, font=FONT)
btn.grid()
self.instances.append(self)
def colorize(self):
self.lbl.config(bg=self.color)
#classmethod
def reset(cls):
for widget in cls.instances:
widget.lbl.config(bg='grey')
# Create a window
the_window = tk.Tk()
# Give the window a title
the_window.title('MULTI Button Colour')
# make some Corey widgets
colors = 'violet', 'purple', 'blue', 'green'
for col, color in enumerate(colors):
widget = Corey(the_window, color)
widget.grid(row=0, column=col, padx=10, pady=2)
reset_button = tk.Button(the_window, text = 'RESET', width=BUTTON_SIZE, command=Corey.reset, font=FONT)
reset_button.grid(row=1, column=0, columnspan=len(colors), pady=4)
the_window.mainloop()
The immediate advantage is that in order to add or subtract colors from my version, you only have to change one line. Also, if you want to change the appearance, say add a relief or change the button to a checkbox, again you only have to change a single line. Subclasses like this are a huge part of GUI design, I recommend you jump into this as soon as you can.

How do I take text input commands in the following piece of code?

I am building a Python GUI where I can enter commands such as play music, pictures etc. which will be executed. I have not yet started working on OS codes.
How do I take user commands using the text box?
or, simply:
How do I make this text box a command box?
from tkinter import *
import quotes #Imported external module having quotations
my_quote = "Random quote."
root = None
textSpace = None
texter = None
def textBox(parent): #creates a text box
global textSpace
textSpace = Entry(parent)
textSpace.place(x = 205, y = 190, width = "200")
def text_input():
global texter
texter = textSpace.get()
print("Text entered:", texter)
def quotes(): #Random quote at bottom of window
global root
quote_text = Label(root, text = my_quote, font = ("papyrus", 7,
"italic"),
bg = "light sky blue")
quote_text.pack(side = "bottom")
def main_win(): #This is the main window
global root
global textSpace
input = textBox #I am not sure if this is correct
user_command = input
root = Tk() #We have to initiate the window right
root.title("Greetings")
root.configure(bg = "light sky blue")
root.geometry("600x350")
head_text = Label(root, text = "PEWDS", font=("Comic Sans MS", 36,
"bold"), bg = "light sky blue", fg = "purple")
head_text.pack(side = "top")
sub_text = Label(root, text = "Enter your command below.", font=("MS
sans serif", 20, "italic"), bg = "light sky blue", fg = "alice blue")
sub_text.pack()
quotes()
go_button = Button(text = "GO", command = text_input)
go_button.place(x=285, y=230)
go_button.configure(bg = "cadetblue")
textBox(root)
root.mainloop
main_win()

Categories