从单选按钮获取输入

1 投票
2 回答
2111 浏览
提问于 2025-04-17 18:29

我正在使用Tkinter和graphics.py(Tkinter的一个封装)来创建一个比较简单的积分器(找出图形下的面积),并且有一个图形用户界面(GUI)。目前,积分器的主要“控制面板”与实际的图形是分开的(图形是用graphics.py制作的)。我使用了Tkinter的Radiobutton()来选择积分类型(左矩形法、右矩形法、梯形法或辛普森法)。

我的问题是,我无法获取到单选按钮的输出。我是参考了TutorialsPoint: Tkinter Radiobutton的例子。

这是我的代码:

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()

但是,它没有打印出变量的值,而是打印了一个空字符串,所以执行上没有问题。root.mainloop()并没有陷入无限循环,因为我在我的GUI中有一个按钮(这里没有显示,因为不相关)可以退出程序。没有出现错误,所以我猜问题出在将选项设置给变量上。非常感谢任何帮助。

另外,顺便提一下,每次我运行程序时,‘右矩形法’、‘梯形法’和‘辛普森法’的单选按钮都是灰色的,像这样:

如果我点击其中一个单选按钮,这种灰色就会消失,但在那之前,它一直是灰色的。如果有办法解决这个问题,请告诉我。

谢谢!

2 个回答

1

我没有看到退出按钮的部分,但你的代码大致是这样的:

  1. 启动主循环
  2. 退出按钮的事件处理器会调用 root.quit()
  3. getInput 中,获取值并调用 self.frame.quit()

在主循环之后调用Tkinter的函数可能会导致一些问题,所以你应该先获取StringVar的值,然后再退出图形界面的循环。这是一个基于你代码的有效示例:

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()
1

问题在于,因为我使用了多个其他的小部件,所以我需要把 StringVar()master 参数设置为 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()

另外,正如 @A. Rodas 所说,为了去掉灰色的部分,我做了:

self.typeFrame = tk.Frame(self.frame)
self.typeChoice = tk.StringVar(self.typeFrame)
self.typeChoice.set(None)

撰写回答