Reputation: 17532
I am using a mix of Tkinter and graphics.py (a wrapper on Tkinter) to create a fairly basic integrator (find the area under a graph) with a GUI. As of now, the main "control panel" for the integrator is separate from the actual graph (which is made by using graphics.py). I am using Tkinter's Radiobutton()
for the choice selection of the integration type (Left Rectangular, Right Rectangular, Trapezoidal, or Simpson's Approximation).
My problem is that I am unable to get the output from the radiobuttons. I was using the example from TutorialsPoint: Tkinter Radiobutton.
Here is my code:
class FunctionInput:
def __init__(self, master, window, items):
self.window = window
self.items = items
self.runProgram = True
self.typeChoice = tk.StringVar()
self.frame = tk.Frame(master)
self.typeFrame = tk.Frame(self.frame)
self.quitButton = tk.Button(self.frame, text = 'Quit', command = self.frame.quit)
self.optLabel = tk.Label(self.frame, text = 'Type of Approximation: ')
self.optL = tk.Radiobutton(self.typeFrame, text = 'Left Rectangular', variable = self.typeChoice, value = 'l')
self.optR = tk.Radiobutton(self.typeFrame, text = 'Right Rectangular', variable = self.typeChoice, value = 'r')
self.optT = tk.Radiobutton(self.typeFrame, text = 'Trapezoidal', variable = self.typeChoice, value = 't')
self.optS = tk.Radiobutton(self.typeFrame, text = 'Simpsons Rule', variable = self.typeChoice, value = 's')
self.optL.grid(row = 1, column = 1, padx = 5, pady = 5)
self.optR.grid(row = 1, column = 2, padx = 5, pady = 5)
self.optT.grid(row = 2, column = 1, padx = 5, pady = 5)
self.optS.grid(row = 2, column = 2, padx = 5, pady = 5)
self.optLabel.grid(row = 4)
self.typeFrame.grid(row = 5)
self.quitButton.grid(row = 6)
# there were numerous other widgets and frames, but I only included the relevant ones
self.frame.grid()
def getInput(self):
type_integration = self.typeChoice.get()
self.frame.quit()
return type_integration
def main():
# some other code, win and axisLabels are defined prior to this
root = tk.Tk(className = ' Function Grapher')
app = FunctionInput(root, win, axisLabels)
root.rowconfigure(0, weight = 1)
root.columnconfigure(0, weight = 1)
root.mainloop() # there is a button to exit the mainloop in my GUI
typeIntegration = app.getInput()
print typeIntegration # trying to debug it
if __name__ == '__main__': main()
However, it doesn't not print the variable. It prints an empty string, so execution is not a problem. root.mainloop()
does not get stuck in an infinite loop, because I have a button in my GUI (not shown here because it is irrelevant) that exits it. An error is not raised, so I'm guessing that the issue is with setting the option to the variable. Any help is greatly appreciated.
Also, on a side note, whenever I run the program, the 'Right Rectangular', 'Trapezoidal', and 'Simpson's Rule' radiobuttons are grayed out, like such:
This grayness goes away if I click on one of the radiobuttons, but until then, it stays. If there is some way to fix this, please let me know.
Thanks!
Upvotes: 1
Views: 2137
Reputation: 17532
The problem was that since I was using multiple other widgets, I had to set StringVar()
s master
parameter as self.typeFrame
:
class FunctionInput:
def __init__(self, master, window, items):
self.window = window
self.items = items
self.runProgram = True
self.frame = tk.Frame(master)
self.typeFrame = tk.Frame(self.frame)
self.typeChoice = tk.StringVar(self.typeFrame)
self.quitButton = tk.Button(self.frame, text = 'Quit', command = self.frame.quit)
self.optLabel = tk.Label(self.frame, text = 'Type of Approximation: ')
self.optL = tk.Radiobutton(self.typeFrame, text = 'Left Rectangular', variable = self.typeChoice, value = 'l')
self.optR = tk.Radiobutton(self.typeFrame, text = 'Right Rectangular', variable = self.typeChoice, value = 'r')
self.optT = tk.Radiobutton(self.typeFrame, text = 'Trapezoidal', variable = self.typeChoice, value = 't')
self.optS = tk.Radiobutton(self.typeFrame, text = 'Simpsons Rule', variable = self.typeChoice, value = 's')
self.optL.grid(row = 1, column = 1, padx = 5, pady = 5)
self.optR.grid(row = 1, column = 2, padx = 5, pady = 5)
self.optT.grid(row = 2, column = 1, padx = 5, pady = 5)
self.optS.grid(row = 2, column = 2, padx = 5, pady = 5)
self.optLabel.grid(row = 4)
self.typeFrame.grid(row = 5)
self.quitButton.grid(row = 6)
# there were numerous other widgets and frames, but I only included the relevant ones
self.frame.grid()
def getInput(self):
type_integration = self.typeChoice.get()
self.frame.quit()
return type_integration
def main():
# some other code, win and axisLabels are defined prior to this
root = tk.Tk(className = ' Function Grapher')
app = FunctionInput(root, win, axisLabels)
root.rowconfigure(0, weight = 1)
root.columnconfigure(0, weight = 1)
root.mainloop() # there is a button to exit the mainloop in my GUI
print app.getInput()
if __name__ == '__main__': main()
Also, as @A. Rodas said, to get rid of the grayness, I did:
self.typeFrame = tk.Frame(self.frame)
self.typeChoice = tk.StringVar(self.typeFrame)
self.typeChoice.set(None)
Upvotes: 1
Reputation: 20679
I haven't seen the part of the exit button, but your code does something like this:
root.quit()
getInput
, retrieves the value and calls self.frame.quit()
Calling Tkinter functions after the mainloop may lead to problems like this, so you should get the value of the StringVar first and then exit the GUI loop. This is a working example based on your code:
import Tkinter as tk
class App():
def __init__(self, master):
self.master = master
self.type_integration = None
self.typeChoice = tk.StringVar()
self.typeChoice.set(None) # This fixes the grayness of the radio buttons!
self.typeFrame = tk.Frame(master)
OPTIONS = [('Left Rectangular', 'l'),
('Right Rectangular', 'r'),
('Trapezoidal', 't'),
('Simpsons Rule', 's')]
for text, value in OPTIONS:
tk.Radiobutton(self.typeFrame, text=text, variable=self.typeChoice, value=value).pack()
tk.Button(self.typeFrame, text="Exit", command=self.exit).pack()
self.typeFrame.pack()
def exit(self):
self.type_integration = self.typeChoice.get()
self.master.destroy() # self.master.quit() freezes the GUI
def getinput(self):
return self.type_integration
master = tk.Tk()
app = App(master)
tk.mainloop()
print app.getinput()
Upvotes: 1