Tkinter中使用tk.IntVar获取Checkbox状态返回地址而非值及Save按钮存储状态到字典失败的问题咨询
Let's tackle your two problems one by one, with clear explanations and actionable fixes:
1. Getting Variable Address Instead of Checkbox State
The root issue here is that your self.colors dictionary (and later self.comp_add_drop_status) stores tk.IntVar objects, not their actual integer state values. When you print or access these entries directly, you're seeing the object's memory address instead of the 0/unchecked or 1/checked status.
To get the real state, you need to call the .get() method on each IntVar instance. For example, instead of self.comp_add_drop_status["f1_Blue"], use self.comp_add_drop_status["f1_Blue"].get().
2. Saving Checked States to a New Dictionary
Your current save_colors2dict method was fetching the IntVar objects but not retrieving their values, and it lacked the logic to filter checked items. Here's how to fix this:
Modified save_colors2dict Method
def save_colors2dict(self): # Initialize empty dictionary for checked items selected_colors = {} # Iterate over each color and its associated IntVar for color_name, var in self.comp_add_drop_status.items(): # Get the actual checkbox state (0 or 1) current_state = var.get() if current_state == 1: # Add to new dictionary if the checkbox is checked selected_colors[color_name] = current_state # Print results to verify functionality print("All IntVar objects:", self.comp_add_drop_status.values()) print("Checked colors:", selected_colors) # Return the selected colors for further use return selected_colors
Key Fixes Explained
- We loop through all key-value pairs in the status dictionary
- For each entry, we call
.get()on theIntVarto get its current state - We only add entries where the state is 1 (checked) to the new dictionary
Full Modified Code
Here's your complete code with fixes applied, plus minor cleanups for consistency:
import tkinter as tk from tkinter import ttk class ToolTip(object): def __init__(self, widget): self.widget = widget self.tip_window = None def show_tip(self, tip_text): """Display text in a tooltip window""" if self.tip_window or not tip_text: return x, y, _cx, cy = self.widget.bbox("insert") # get size of widget x = x + self.widget.winfo_rootx() + 25 # calculate to display tooltip y = y + cy + self.widget.winfo_rooty() + 25 # below and to the right self.tip_window = tw = tk.Toplevel(self.widget) # create new tooltip window tw.wm_overrideredirect(True) # remove all Window Manager (wm) decorations tw.wm_geometry("+%d+%d" % (x, y)) # create window size label = tk.Label(tw, text=tip_text, justify=tk.LEFT, background="#ffffe0", relief=tk.SOLID, borderwidth=1, font=("tahoma", "8", "normal")) label.pack(ipadx=1) def hide_tip(self): tw = self.tip_window self.tip_window = None if tw: tw.destroy() def create_ToolTip(widget, text): toolTip = ToolTip(widget) # create instance of class def enter(event): toolTip.show_tip(text) def leave(event): toolTip.hide_tip() widget.bind('<Enter>', enter) # bind mouse events widget.bind('<Leave>', leave) class OOP(tk.Frame): def __init__(self, parent): # Initializer method tk.Frame.__init__(self, parent) self.canvas = tk.Canvas(self, borderwidth=0, background="#ffffff") self.frame = tk.Frame(self.canvas, background="#ffffff") self.vsb = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview) self.canvas.configure(yscrollcommand=self.vsb.set) self.hsb = tk.Scrollbar(self, orient="horizontal", command=self.canvas.xview) self.canvas.configure(xscrollcommand=self.hsb.set) self.vsb.pack(side="right", fill="y") self.hsb.pack(side="bottom", fill="x") self.canvas.pack(side="left", fill="both", expand=True) self.canvas_window = self.canvas.create_window((4,4), window=self.frame, anchor="nw", tags="self.frame") self.frame.bind("<Configure>", self.onFrameConfigure)#Bind an event whenever the size of the frame changes self.canvas.bind("<Configure>", self.onCanvasConfigure)#Enables scrolling self.colors = {"f1_Blue": 0, "f2_Red": 0, "f3_Green": 0, "f4_Black": 0, "f5_White": 0, "f6_Purple": 0} self.tabControl = ttk.Notebook(self.frame, width=2500, height=1100) # Create Tab Control self.tab_menu = ttk.Frame(self.tabControl) # Create a tab self.tab_menu.pack(fill=tk.BOTH, expand=1) self.tabControl.add(self.tab_menu, text="MENU") # Add a MENU tab self.tabControl.pack(expand=1, fill="both") # Pack to make visible self.label1 = tk.Label(self.tab_menu, text=' Status ', fg='white', bg='black') self.mighty = ttk.LabelFrame(self.tab_menu, labelwidget=self.label1) self.mighty.grid(column=0, row=0, padx=20, pady=10) self.comp_add_drop_status = self.check_box_addordrop(1, 0, self.mighty, self.colors) ttk.Label(self.mighty, text="Save the colors?", foreground="blue").grid(column=0, row=15, sticky=tk.W, columnspan=3) self.action = ttk.Button(self.mighty, text="Save", command=self.save_colors2dict) self.action.grid(column=5, row=15, sticky=tk.E, columnspan=3) # Add a title parent.title("TESTER") parent.resizable(1, 1) def onFrameConfigure(self, event): self.canvas.configure(scrollregion=self.canvas.bbox("all")) #Reset the scroll region to encompass the inner frame def onCanvasConfigure(self, event): canvas_width = event.width self.canvas.itemconfig(self.canvas_window, width=canvas_width) #Whenever the size of the canvas changes, alter the the window region respectively def check_box_addordrop(self, r, c, frame, items): cow = c row = r self.my_list_test = [] for item in items: items[item] = tk.IntVar(value=items[item]) checkbox = tk.Checkbutton(frame, text=item[3:15], variable=items[item]) checkbox.grid(column=cow, row=row, sticky=tk.W) row += 1 return items def save_colors2dict(self): selected_colors = {} for color_name, var in self.comp_add_drop_status.items(): if var.get() == 1: selected_colors[color_name] = 1 print("All checkbox variables:", self.comp_add_drop_status.values()) print("Selected colors:", selected_colors) return selected_colors if __name__ == '__main__': win = tk.Tk() example = OOP(win) example.pack(fill="both", expand=True) win.mainloop()
Additional Cleanups
- Removed redundant
from tkinter import *import to avoid namespace clutter - Changed
win.title()toparent.title()in the class initializer (uses the passed parent window instead of relying on a global variable)
内容的提问来源于stack exchange,提问作者Kahraman

