You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter中跨类获取Radiobutton值报错:name 'choice' is not defined

解决Tkinter不同页面类间共享Radiobutton值的问题

这个错误的根源很明确,咱们一步步拆解:

问题出在哪?

  1. 变量作用域隔离:你在PageOne的__init__里定义的choice是局部变量,PageTwo的作用域完全访问不到它,自然会报“choice未定义”。
  2. 局部变量被回收:你定义的var也是__init__里的局部变量,当__init__执行完毕,Python的垃圾回收机制会把它清理掉,导致你的单选按钮其实根本没法正确保存选中状态。
  3. 时机错误:你在PageOne初始化时就调用var.get()获取choice,这时候用户还没来得及选择任何单选按钮,拿到的只会是默认值0,完全没意义。

修复方案

咱们需要把变量变成实例属性,再通过页面控制器(controller)来实现不同页面间的数据共享,具体修改如下:

修改后的完整代码示例

import tkinter as tk
from tkinter import ttk

# 页面控制器类,用来管理所有页面的实例和切换
class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        # 注册所有页面,并把控制器传递给每个页面
        for F in (PageOne, PageTwo):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("PageOne")

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        # 把var设为实例属性,避免被垃圾回收,同时让其他页面可访问
        self.var = tk.IntVar()
        # 可选:设置默认选中第一个选项
        self.var.set(1)
        
        tk.Radiobutton(self, text="Herfindahl Index", variable=self.var, value=1).place(relx=0.3, rely=0.3, anchor="w")
        tk.Radiobutton(self, text="Crop Diversification Index", variable=self.var, value=2).place(relx=0.3, rely=0.4, anchor="w")
        
        # 添加跳转按钮到PageTwo,方便测试
        ttk.Button(self, text="Go to PageTwo", command=lambda: self.controller.show_frame("PageTwo")).place(relx=0.5, rely=0.6, anchor="center")

class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        
        # 通过控制器获取PageOne的实例,进而拿到单选按钮的选中值
        page_one = self.controller.frames["PageOne"]
        choice = page_one.var.get()
        
        if choice == 1:
            button6 = ttk.Button(self, text=f"Selected: {choice} (Herfindahl Index)", command=herfindahl_index)
            button6.place(relx=0.5, rely=0.5, anchor="center")
        else:
            button6 = ttk.Button(self, text=f"Selected: {choice} (Crop Diversification Index)", command=lambda: print("Crop Diversification Index triggered"))
            button6.place(relx=0.5, rely=0.5, anchor="center")
        
        # 添加返回按钮
        ttk.Button(self, text="Back to PageOne", command=lambda: self.controller.show_frame("PageOne")).place(relx=0.5, rely=0.7, anchor="center")

# 假设你的Herfindahl Index处理函数如下
def herfindahl_index():
    print("Executing Herfindahl Index calculation logic")

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

关键改动说明

  1. 把var设为PageOne的实例属性:用self.var代替局部变量var,这样它会和PageOne的实例绑定,不会被垃圾回收,单选按钮的状态能正确保存。
  2. 通过controller共享页面实例:控制器(SampleApp)保存了所有页面的实例,PageTwo可以通过self.controller.frames["PageOne"]获取到PageOne的实例,进而访问self.var拿到选中值。
  3. 延迟获取选中值:不在PageOne初始化时拿值,而是在PageTwo初始化(或切换到PageTwo时)再获取,这样拿到的是用户实际选择的值。
  4. 补充页面切换逻辑:添加跳转按钮方便测试,确保页面间的交互顺畅。

如果你的控制器框架和示例不同,核心逻辑是一致的:把需要共享的变量设为页面实例的属性,通过共同的父控制器来实现不同页面间的实例访问。

内容的提问来源于stack exchange,提问作者PRAJYOT KUMAR GARABADU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:04:20