Rushy Panchal
Rushy Panchal

Reputation: 17532

Getting Input from Radiobutton

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

Answers (2)

Rushy Panchal
Rushy Panchal

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

A. Rodas
A. Rodas

Reputation: 20679

I haven't seen the part of the exit button, but your code does something like this:

  1. Starts the mainloop
  2. The event handler of the exit button calls root.quit()
  3. In 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

Related Questions