IntVar是Tkinter中用於管理整數變量的特殊類,它是Variable類的子類,專門用於處理整數值。

基本概念

IntVar是一個Tkinter變量類,用於在GUI組件之間共享和跟蹤整數值的變化。

導入和基本使用

import tkinter as tk
from tkinter import ttk

# 創建主窗口
root = tk.Tk()
root.title("IntVar示例")
root.geometry("400x300")

創建IntVar變量

# 創建IntVar變量
int_var = tk.IntVar()

# 設置初始值
int_var.set(42)

# 獲取值
current_value = int_var.get()
print(f"當前值: {current_value}")

IntVar與不同組件的結合使用

示例1:IntVar全面展示

import tkinter as tk
from tkinter import ttk

class IntVarComprehensive:
    def __init__(self, root):
        self.root = root
        self.setup_ui()
        
    def setup_ui(self):
        """設置用户界面"""
        self.root.title("IntVar全面展示")
        self.root.geometry("600x500")
        
        # 創建主Frame
        main_frame = tk.Frame(self.root, bg="#f0f0f0", padx=20, pady=20)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 1. 基本IntVar操作
        self.create_basic_intvar_section(main_frame)
        
        # 2. IntVar與Scale組件
        self.create_scale_section(main_frame)
        
        # 3. IntVar與Spinbox組件
        self.create_spinbox_section(main_frame)
        
        # 4. IntVar與Radiobutton組件
        self.create_radiobutton_section(main_frame)
        
        # 5. IntVar與Checkbutton組件
        self.create_checkbutton_section(main_frame)
        
        # 6. 多個IntVar聯動
        self.create_linked_intvar_section(main_frame)
        
    def create_basic_intvar_section(self, parent):
        """創建基本IntVar操作部分"""
        section_frame = tk.LabelFrame(parent, text="1. 基本IntVar操作", 
                                     padx=10, pady=10, bg="white")
        section_frame.pack(fill=tk.X, pady=10)
        
        # 創建IntVar
        self.basic_intvar = tk.IntVar(value=100)
        
        # 顯示當前值
        value_label = tk.Label(section_frame, textvariable=self.basic_intvar, 
                              font=("Arial", 14, "bold"), bg="white", fg="blue")
        value_label.pack(pady=5)
        
        # 控制按鈕
        control_frame = tk.Frame(section_frame, bg="white")
        control_frame.pack(pady=10)
        
        operations = [
            ("+10", 10), ("-10", -10), ("×2", "multiply"), 
            ("÷2", "divide"), ("清零", "clear"), ("隨機", "random")
        ]
        
        for text, op in operations:
            tk.Button(control_frame, text=text, 
                     command=lambda o=op: self.basic_operation(o)).pack(side=tk.LEFT, padx=5)
        
        # 手動設置值
        set_frame = tk.Frame(section_frame, bg="white")
        set_frame.pack(pady=5)
        
        tk.Label(set_frame, text="設置值:", bg="white").pack(side=tk.LEFT)
        self.set_entry = tk.Entry(set_frame, width=10)
        self.set_entry.pack(side=tk.LEFT, padx=5)
        tk.Button(set_frame, text="設置", 
                 command=self.set_manual_value).pack(side=tk.LEFT, padx=5)
        
    def create_scale_section(self, parent):
        """創建Scale組件部分"""
        section_frame = tk.LabelFrame(parent, text="2. IntVar與Scale組件", 
                                     padx=10, pady=10, bg="white")
        section_frame.pack(fill=tk.X, pady=10)
        
        # 創建IntVar
        self.scale_intvar = tk.IntVar(value=50)
        
        # 創建Scale
        scale = tk.Scale(
            section_frame,
            from_=0, to=100,
            orient=tk.HORIZONTAL,
            variable=self.scale_intvar,
            length=300,
            showvalue=True,
            bg="white"
        )
        scale.pack(pady=5)
        
        # 顯示值
        scale_value_frame = tk.Frame(section_frame, bg="white")
        scale_value_frame.pack(pady=5)
        
        tk.Label(scale_value_frame, text="Scale值:", bg="white").pack(side=tk.LEFT)
        scale_value_label = tk.Label(scale_value_frame, textvariable=self.scale_intvar,
                                    font=("Arial", 12), bg="white", fg="green")
        scale_value_label.pack(side=tk.LEFT, padx=5)
        
        # 綁定變化事件
        self.scale_intvar.trace_add("write", self.on_scale_change)
        
    def create_spinbox_section(self, parent):
        """創建Spinbox組件部分"""
        section_frame = tk.LabelFrame(parent, text="3. IntVar與Spinbox組件", 
                                     padx=10, pady=10, bg="white")
        section_frame.pack(fill=tk.X, pady=10)
        
        # 創建IntVar
        self.spinbox_intvar = tk.IntVar(value=5)
        
        # 創建Spinbox
        spinbox = tk.Spinbox(
            section_frame,
            from_=0, to=100,
            increment=1,
            textvariable=self.spinbox_intvar,
            width=10,
            bg="white"
        )
        spinbox.pack(pady=5)
        
        # 顯示值
        spinbox_value_frame = tk.Frame(section_frame, bg="white")
        spinbox_value_frame.pack(pady=5)
        
        tk.Label(spinbox_value_frame, text="Spinbox值:", bg="white").pack(side=tk.LEFT)
        spinbox_value_label = tk.Label(spinbox_value_frame, textvariable=self.spinbox_intvar,
                                      font=("Arial", 12), bg="white", fg="purple")
        spinbox_value_label.pack(side=tk.LEFT, padx=5)
        
    def create_radiobutton_section(self, parent):
        """創建Radiobutton組件部分"""
        section_frame = tk.LabelFrame(parent, text="4. IntVar與Radiobutton組件", 
                                     padx=10, pady=10, bg="white")
        section_frame.pack(fill=tk.X, pady=10)
        
        # 創建IntVar
        self.radio_intvar = tk.IntVar(value=1)
        
        # 創建Radiobuttons
        radio_frame = tk.Frame(section_frame, bg="white")
        radio_frame.pack(pady=5)
        
        options = [
            (1, "選項 1"),
            (2, "選項 2"), 
            (3, "選項 3"),
            (4, "選項 4")
        ]
        
        for value, text in options:
            tk.Radiobutton(radio_frame, text=text, variable=self.radio_intvar,
                          value=value, bg="white", command=self.on_radio_change).pack(anchor="w")
        
        # 顯示選中值
        radio_value_frame = tk.Frame(section_frame, bg="white")
        radio_value_frame.pack(pady=5)
        
        tk.Label(radio_value_frame, text="選中選項:", bg="white").pack(side=tk.LEFT)
        self.radio_value_label = tk.Label(radio_value_frame, text="1", 
                                         font=("Arial", 12), bg="white", fg="orange")
        self.radio_value_label.pack(side=tk.LEFT, padx=5)
        
    def create_checkbutton_section(self, parent):
        """創建Checkbutton組件部分"""
        section_frame = tk.LabelFrame(parent, text="5. IntVar與Checkbutton組件", 
                                     padx=10, pady=10, bg="white")
        section_frame.pack(fill=tk.X, pady=10)
        
        # 創建多個IntVar用於Checkbuttons
        self.check_vars = []
        check_frame = tk.Frame(section_frame, bg="white")
        check_frame.pack(pady=5)
        
        options = ["選項 A", "選項 B", "選項 C", "選項 D"]
        
        for i, text in enumerate(options):
            var = tk.IntVar()
            self.check_vars.append(var)
            tk.Checkbutton(check_frame, text=text, variable=var,
                          bg="white", command=lambda idx=i: self.on_check_change(idx)).pack(anchor="w")
        
        # 顯示選中狀態
        self.check_value_label = tk.Label(section_frame, text="選中: 無", 
                                         bg="white", font=("Arial", 10))
        self.check_value_label.pack(pady=5)
        
    def create_linked_intvar_section(self, parent):
        """創建多個IntVar聯動部分"""
        section_frame = tk.LabelFrame(parent, text="6. 多個IntVar聯動", 
                                     padx=10, pady=10, bg="white")
        section_frame.pack(fill=tk.X, pady=10)
        
        # 創建主IntVar
        self.master_intvar = tk.IntVar(value=10)
        
        # 主控制
        master_frame = tk.Frame(section_frame, bg="white")
        master_frame.pack(pady=5)
        
        tk.Label(master_frame, text="主控制:", bg="white").pack(side=tk.LEFT)
        master_scale = tk.Scale(master_frame, from_=0, to=100, 
                               variable=self.master_intvar, orient=tk.HORIZONTAL,
                               length=200, showvalue=True, bg="white")
        master_scale.pack(side=tk.LEFT, padx=10)
        
        # 創建關聯的IntVar
        self.linked_var1 = tk.IntVar()
        self.linked_var2 = tk.IntVar()
        self.linked_var3 = tk.IntVar()
        
        # 顯示關聯值
        linked_frame = tk.Frame(section_frame, bg="white")
        linked_frame.pack(pady=10)
        
        links = [
            ("50%", self.linked_var1),
            ("150%", self.linked_var2), 
            ("平方", self.linked_var3)
        ]
        
        for text, var in links:
            frame = tk.Frame(linked_frame, bg="white")
            frame.pack(side=tk.LEFT, padx=20)
            
            tk.Label(frame, text=text, bg="white").pack()
            value_label = tk.Label(frame, textvariable=var, font=("Arial", 12),
                                  bg="white", fg="red")
            value_label.pack()
        
        # 綁定主IntVar變化事件
        self.master_intvar.trace_add("write", self.update_linked_vars)
        self.update_linked_vars()  # 初始化
        
    def basic_operation(self, operation):
        """基本數學運算"""
        current = self.basic_intvar.get()
        
        if operation == "multiply":
            new_value = current * 2
        elif operation == "divide":
            new_value = current // 2
        elif operation == "clear":
            new_value = 0
        elif operation == "random":
            import random
            new_value = random.randint(0, 1000)
        else:
            new_value = current + operation
            
        self.basic_intvar.set(new_value)
        
    def set_manual_value(self):
        """手動設置值"""
        try:
            value = int(self.set_entry.get())
            self.basic_intvar.set(value)
        except ValueError:
            pass
            
    def on_scale_change(self, *args):
        """Scale值變化事件"""
        # 這裏可以添加額外的處理邏輯
        pass
        
    def on_radio_change(self):
        """Radiobutton變化事件"""
        selected = self.radio_intvar.get()
        self.radio_value_label.config(text=str(selected))
        
    def on_check_change(self, index):
        """Checkbutton變化事件"""
        selected = []
        for i, var in enumerate(self.check_vars):
            if var.get() == 1:
                selected.append(chr(65 + i))  # A, B, C, D
        
        if selected:
            self.check_value_label.config(text=f"選中: {', '.join(selected)}")
        else:
            self.check_value_label.config(text="選中: 無")
            
    def update_linked_vars(self, *args):
        """更新關聯的IntVar"""
        master_value = self.master_intvar.get()
        self.linked_var1.set(master_value // 2)      # 50%
        self.linked_var2.set(int(master_value * 1.5)) # 150%
        self.linked_var3.set(master_value ** 2)      # 平方

if __name__ == "__main__":
    root = tk.Tk()
    app = IntVarComprehensive(root)
    root.mainloop()

實際應用示例

示例2:計數器應用

import tkinter as tk
from tkinter import ttk
import time

class CounterApplication:
    def __init__(self, root):
        self.root = root
        self.running = False
        self.start_time = 0
        self.setup_ui()
        
    def setup_ui(self):
        """設置用户界面"""
        self.root.title("計數器應用 - IntVar示例")
        self.root.geometry("500x400")
        self.root.resizable(False, False)
        
        # 創建主Frame
        main_frame = tk.Frame(self.root, bg="#f5f5f5", padx=20, pady=20)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 標題
        title_label = tk.Label(main_frame, text="多功能計數器", 
                              font=("Arial", 20, "bold"), bg="#f5f5f5")
        title_label.pack(pady=(0, 20))
        
        # 創建計數器區域
        self.create_counter_section(main_frame)
        
        # 創建控制區域
        self.create_control_section(main_frame)
        
        # 創建計時器區域
        self.create_timer_section(main_frame)
        
        # 創建歷史記錄區域
        self.create_history_section(main_frame)
        
    def create_counter_section(self, parent):
        """創建計數器顯示區域"""
        counter_frame = tk.LabelFrame(parent, text="計數器", 
                                     font=("Arial", 12, "bold"),
                                     padx=15, pady=15, bg="white")
        counter_frame.pack(fill=tk.X, pady=10)
        
        # 使用IntVar存儲計數值
        self.counter_var = tk.IntVar(value=0)
        
        # 大數字顯示
        counter_display = tk.Label(counter_frame, textvariable=self.counter_var,
                                  font=("Arial", 48, "bold"), bg="white", fg="#2c3e50")
        counter_display.pack(pady=10)
        
        # 計數器控制
        counter_controls = tk.Frame(counter_frame, bg="white")
        counter_controls.pack(pady=10)
        
        tk.Button(counter_controls, text="-10", font=("Arial", 10),
                 command=lambda: self.update_counter(-10), 
                 bg="#e74c3c", fg="white", width=6).pack(side=tk.LEFT, padx=5)
        
        tk.Button(counter_controls, text="-1", font=("Arial", 10),
                 command=lambda: self.update_counter(-1), 
                 bg="#e67e22", fg="white", width=6).pack(side=tk.LEFT, padx=5)
        
        tk.Button(counter_controls, text="+1", font=("Arial", 10),
                 command=lambda: self.update_counter(1), 
                 bg="#27ae60", fg="white", width=6).pack(side=tk.LEFT, padx=5)
        
        tk.Button(counter_controls, text="+10", font=("Arial", 10),
                 command=lambda: self.update_counter(10), 
                 bg="#2980b9", fg="white", width=6).pack(side=tk.LEFT, padx=5)
        
    def create_control_section(self, parent):
        """創建控制區域"""
        control_frame = tk.LabelFrame(parent, text="控制面板", 
                                     font=("Arial", 12, "bold"),
                                     padx=15, pady=15, bg="white")
        control_frame.pack(fill=tk.X, pady=10)
        
        # 預設值按鈕
        preset_frame = tk.Frame(control_frame, bg="white")
        preset_frame.pack(pady=5)
        
        tk.Label(preset_frame, text="預設值:", bg="white").pack(side=tk.LEFT)
        
        presets = [0, 100, 500, 1000]
        for value in presets:
            tk.Button(preset_frame, text=str(value), font=("Arial", 9),
                     command=lambda v=value: self.counter_var.set(v),
                     bg="#95a5a6", fg="white", width=6).pack(side=tk.LEFT, padx=2)
        
        # 操作按鈕
        operation_frame = tk.Frame(control_frame, bg="white")
        operation_frame.pack(pady=10)
        
        tk.Button(operation_frame, text="重置", font=("Arial", 10),
                 command=self.reset_counter, bg="#f39c12", fg="white", width=8).pack(side=tk.LEFT, padx=5)
        
        tk.Button(operation_frame, text="隨機", font=("Arial", 10),
                 command=self.random_counter, bg="#9b59b6", fg="white", width=8).pack(side=tk.LEFT, padx=5)
        
        # 自定義設置
        custom_frame = tk.Frame(control_frame, bg="white")
        custom_frame.pack(pady=5)
        
        tk.Label(custom_frame, text="自定義:", bg="white").pack(side=tk.LEFT)
        self.custom_entry = tk.Entry(custom_frame, width=10)
        self.custom_entry.pack(side=tk.LEFT, padx=5)
        tk.Button(custom_frame, text="設置", font=("Arial", 9),
                 command=self.set_custom_value, bg="#34495e", fg="white").pack(side=tk.LEFT, padx=5)
        
    def create_timer_section(self, parent):
        """創建計時器區域"""
        timer_frame = tk.LabelFrame(parent, text="自動計時器", 
                                   font=("Arial", 12, "bold"),
                                   padx=15, pady=15, bg="white")
        timer_frame.pack(fill=tk.X, pady=10)
        
        # 計時器控制
        timer_controls = tk.Frame(timer_frame, bg="white")
        timer_controls.pack(pady=5)
        
        self.timer_btn = tk.Button(timer_controls, text="開始計時", font=("Arial", 10),
                                  command=self.toggle_timer, bg="#27ae60", fg="white", width=12)
        self.timer_btn.pack(side=tk.LEFT, padx=5)
        
        # 間隔設置
        interval_frame = tk.Frame(timer_frame, bg="white")
        interval_frame.pack(pady=5)
        
        tk.Label(interval_frame, text="間隔(秒):", bg="white").pack(side=tk.LEFT)
        self.interval_var = tk.IntVar(value=1)
        interval_spinbox = tk.Spinbox(interval_frame, from_=1, to=60, 
                                     textvariable=self.interval_var, width=5)
        interval_spinbox.pack(side=tk.LEFT, padx=5)
        
        # 計時器狀態
        self.timer_status = tk.Label(timer_frame, text="計時器已停止", 
                                    bg="white", fg="#7f8c8d", font=("Arial", 9))
        self.timer_status.pack(pady=5)
        
    def create_history_section(self, parent):
        """創建歷史記錄區域"""
        history_frame = tk.LabelFrame(parent, text="操作歷史", 
                                     font=("Arial", 12, "bold"),
                                     padx=15, pady=15, bg="white")
        history_frame.pack(fill=tk.BOTH, expand=True, pady=10)
        
        # 歷史記錄文本框
        self.history_text = tk.Text(history_frame, height=6, wrap=tk.WORD,
                                   font=("Arial", 9), bg="#f8f9fa")
        self.history_text.pack(fill=tk.BOTH, expand=True)
        
        # 添加滾動條
        scrollbar = tk.Scrollbar(self.history_text)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.history_text.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.history_text.yview)
        
        # 歷史記錄控制
        history_controls = tk.Frame(history_frame, bg="white")
        history_controls.pack(fill=tk.X, pady=(5, 0))
        
        tk.Button(history_controls, text="清空歷史", font=("Arial", 9),
                 command=self.clear_history, bg="#e74c3c", fg="white").pack(side=tk.LEFT)
        
        # 綁定計數器變化事件
        self.counter_var.trace_add("write", self.on_counter_change)
        
    def update_counter(self, delta):
        """更新計數器"""
        current = self.counter_var.get()
        self.counter_var.set(current + delta)
        
    def reset_counter(self):
        """重置計數器"""
        self.counter_var.set(0)
        self.add_history("計數器已重置")
        
    def random_counter(self):
        """隨機設置計數器"""
        import random
        value = random.randint(0, 1000)
        self.counter_var.set(value)
        self.add_history(f"計數器隨機設置為: {value}")
        
    def set_custom_value(self):
        """設置自定義值"""
        try:
            value = int(self.custom_entry.get())
            self.counter_var.set(value)
            self.add_history(f"計數器設置為: {value}")
        except ValueError:
            pass
            
    def toggle_timer(self):
        """切換計時器狀態"""
        if not self.running:
            self.start_timer()
        else:
            self.stop_timer()
            
    def start_timer(self):
        """啓動計時器"""
        self.running = True
        self.timer_btn.config(text="停止計時", bg="#e74c3c")
        self.timer_status.config(text="計時器運行中...", fg="#27ae60")
        self.start_time = time.time()
        self.timer_tick()
        
    def stop_timer(self):
        """停止計時器"""
        self.running = False
        self.timer_btn.config(text="開始計時", bg="#27ae60")
        self.timer_status.config(text="計時器已停止", fg="#7f8c8d")
        
    def timer_tick(self):
        """計時器滴答"""
        if self.running:
            # 增加計數器
            current = self.counter_var.get()
            self.counter_var.set(current + 1)
            
            # 安排下一次執行
            interval = self.interval_var.get() * 1000  # 轉換為毫秒
            self.root.after(interval, self.timer_tick)
            
    def on_counter_change(self, *args):
        """計數器變化事件"""
        current_value = self.counter_var.get()
        # 可以在這裏添加其他響應邏輯
        
    def add_history(self, message):
        """添加歷史記錄"""
        timestamp = time.strftime("%H:%M:%S")
        self.history_text.insert(tk.END, f"[{timestamp}] {message}\n")
        self.history_text.see(tk.END)
        
    def clear_history(self):
        """清空歷史記錄"""
        self.history_text.delete(1.0, tk.END)

if __name__ == "__main__":
    root = tk.Tk()
    app = CounterApplication(root)
    root.mainloop()

示例3:投票系統

python

import tkinter as tk
from tkinter import ttk, messagebox
import json
import datetime

class VotingSystem:
    def __init__(self, root):
        self.root = root
        self.candidates = []
        self.votes = {}
        self.setup_ui()
        self.load_sample_data()
        
    def setup_ui(self):
        """設置用户界面"""
        self.root.title("投票系統 - IntVar示例")
        self.root.geometry("800x600")
        
        # 創建主Frame
        main_frame = tk.Frame(self.root, bg="#f5f5f5")
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 標題
        title_label = tk.Label(main_frame, text="在線投票系統", 
                              font=("Arial", 20, "bold"), bg="#f5f5f5")
        title_label.pack(pady=(0, 20))
        
        # 創建Notebook用於分頁
        notebook = ttk.Notebook(main_frame)
        notebook.pack(fill=tk.BOTH, expand=True)
        
        # 投票頁面
        self.create_voting_tab(notebook)
        
        # 結果頁面
        self.create_results_tab(notebook)
        
        # 管理頁面
        self.create_management_tab(notebook)
        
    def create_voting_tab(self, notebook):
        """創建投票標籤頁"""
        voting_frame = ttk.Frame(notebook)
        notebook.add(voting_frame, text="投票")
        
        # 投票區域
        vote_main_frame = tk.Frame(voting_frame, bg="white", padx=20, pady=20)
        vote_main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 標題
        vote_title = tk.Label(vote_main_frame, text="請選擇您要投票的候選人", 
                             font=("Arial", 16, "bold"), bg="white")
        vote_title.pack(pady=(0, 20))
        
        # 候選人選擇區域
        self.candidate_frame = tk.Frame(vote_main_frame, bg="white")
        self.candidate_frame.pack(fill=tk.BOTH, expand=True)
        
        # 使用IntVar存儲選擇的候選人ID
        self.selected_candidate = tk.IntVar(value=-1)  # -1表示未選擇
        
        # 投票按鈕
        vote_btn = tk.Button(vote_main_frame, text="提交投票", 
                            font=("Arial", 14), bg="#4CAF50", fg="white",
                            command=self.submit_vote, state=tk.DISABLED)
        vote_btn.pack(pady=20)
        
        # 綁定選擇事件
        self.selected_candidate.trace_add("write", 
                                         lambda *args: vote_btn.config(
                                             state=tk.NORMAL if self.selected_candidate.get() != -1 else tk.DISABLED
                                         ))
        
    def create_results_tab(self, notebook):
        """創建結果標籤頁"""
        results_frame = ttk.Frame(notebook)
        notebook.add(results_frame, text="投票結果")
        
        # 結果區域
        results_main_frame = tk.Frame(results_frame, bg="white", padx=20, pady=20)
        results_main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 標題
        results_title = tk.Label(results_main_frame, text="投票結果統計", 
                                font=("Arial", 16, "bold"), bg="white")
        results_title.pack(pady=(0, 20))
        
        # 結果顯示區域
        self.results_text = tk.Text(results_main_frame, wrap=tk.WORD, 
                                   font=("Arial", 11), height=15)
        self.results_text.pack(fill=tk.BOTH, expand=True)
        
        # 添加滾動條
        scrollbar = tk.Scrollbar(self.results_text)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.results_text.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.results_text.yview)
        
        # 刷新按鈕
        refresh_btn = tk.Button(results_main_frame, text="刷新結果", 
                               font=("Arial", 12), bg="#2196F3", fg="white",
                               command=self.update_results)
        refresh_btn.pack(pady=10)
        
    def create_management_tab(self, notebook):
        """創建管理標籤頁"""
        management_frame = ttk.Frame(notebook)
        notebook.add(management_frame, text="管理")
        
        # 管理區域
        management_main_frame = tk.Frame(management_frame, bg="white", padx=20, pady=20)
        management_main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 添加候選人區域
        add_candidate_frame = tk.LabelFrame(management_main_frame, text="添加候選人", 
                                           font=("Arial", 12, "bold"),
                                           padx=15, pady=15, bg="white")
        add_candidate_frame.pack(fill=tk.X, pady=10)
        
        # 候選人姓名輸入
        name_frame = tk.Frame(add_candidate_frame, bg="white")
        name_frame.pack(fill=tk.X, pady=5)
        
        tk.Label(name_frame, text="姓名:", bg="white").pack(side=tk.LEFT)
        self.candidate_name = tk.Entry(name_frame, width=30)
        self.candidate_name.pack(side=tk.LEFT, padx=10)
        
        # 候選人描述輸入
        desc_frame = tk.Frame(add_candidate_frame, bg="white")
        desc_frame.pack(fill=tk.X, pady=5)
        
        tk.Label(desc_frame, text="描述:", bg="white").pack(side=tk.LEFT)
        self.candidate_desc = tk.Entry(desc_frame, width=30)
        self.candidate_desc.pack(side=tk.LEFT, padx=10)
        
        # 添加按鈕
        add_btn = tk.Button(add_candidate_frame, text="添加候選人", 
                           bg="#4CAF50", fg="white", command=self.add_candidate)
        add_btn.pack(pady=10)
        
        # 重置投票按鈕
        reset_frame = tk.LabelFrame(management_main_frame, text="投票管理", 
                                   font=("Arial", 12, "bold"),
                                   padx=15, pady=15, bg="white")
        reset_frame.pack(fill=tk.X, pady=10)
        
        tk.Button(reset_frame, text="重置所有投票", 
                 bg="#f44336", fg="white", command=self.reset_votes).pack(pady=5)
        
        # 導出數據按鈕
        export_btn = tk.Button(management_main_frame, text="導出投票數據", 
                              bg="#FF9800", fg="white", command=self.export_data)
        export_btn.pack(pady=10)
        
    def load_sample_data(self):
        """加載示例數據"""
        sample_candidates = [
            {"id": 1, "name": "張三", "description": "經驗豐富的領導者"},
            {"id": 2, "name": "李四", "description": "創新的思想家"},
            {"id": 3, "name": "王五", "description": "團隊合作專家"},
            {"id": 4, "name": "趙六", "description": "技術先鋒"}
        ]
        
        for candidate in sample_candidates:
            self.candidates.append(candidate)
            self.votes[candidate["id"]] = 0
            
        self.update_candidate_display()
        self.update_results()
        
    def update_candidate_display(self):
        """更新候選人顯示"""
        # 清空現有內容
        for widget in self.candidate_frame.winfo_children():
            widget.destroy()
            
        # 顯示所有候選人
        for candidate in self.candidates:
            candidate_frame = tk.Frame(self.candidate_frame, bg="white", relief=tk.GROOVE, bd=1)
            candidate_frame.pack(fill=tk.X, pady=5, padx=10)
            
            # 單選按鈕
            radio = tk.Radiobutton(candidate_frame, text="", 
                                  variable=self.selected_candidate, 
                                  value=candidate["id"], bg="white")
            radio.pack(side=tk.LEFT, padx=10)
            
            # 候選人信息
            info_frame = tk.Frame(candidate_frame, bg="white")
            info_frame.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5, pady=10)
            
            name_label = tk.Label(info_frame, text=candidate["name"], 
                                 font=("Arial", 12, "bold"), bg="white")
            name_label.pack(anchor="w")
            
            desc_label = tk.Label(info_frame, text=candidate["description"], 
                                 font=("Arial", 9), bg="white", fg="#666")
            desc_label.pack(anchor="w")
            
    def submit_vote(self):
        """提交投票"""
        candidate_id = self.selected_candidate.get()
        
        if candidate_id == -1:
            messagebox.showwarning("警告", "請選擇一個候選人!")
            return
            
        # 記錄投票
        self.votes[candidate_id] += 1
        
        # 顯示成功消息
        candidate_name = next(c["name"] for c in self.candidates if c["id"] == candidate_id)
        messagebox.showinfo("成功", f"您已成功投票給: {candidate_name}")
        
        # 重置選擇
        self.selected_candidate.set(-1)
        
        # 更新結果
        self.update_results()
        
    def update_results(self):
        """更新投票結果"""
        self.results_text.delete(1.0, tk.END)
        
        total_votes = sum(self.votes.values())
        
        if total_votes == 0:
            self.results_text.insert(tk.END, "暫無投票數據")
            return
            
        # 計算百分比並排序
        results = []
        for candidate in self.candidates:
            candidate_id = candidate["id"]
            vote_count = self.votes[candidate_id]
            percentage = (vote_count / total_votes) * 100 if total_votes > 0 else 0
            results.append((candidate, vote_count, percentage))
            
        # 按票數排序
        results.sort(key=lambda x: x[1], reverse=True)
        
        # 顯示結果
        self.results_text.insert(tk.END, f"總投票數: {total_votes}\n\n")
        
        for candidate, votes, percentage in results:
            # 創建進度條表示
            bar_length = int(percentage / 2)  # 50個字符表示100%
            bar = "█" * bar_length + "░" * (50 - bar_length)
            
            result_text = (
                f"{candidate['name']} - {candidate['description']}\n"
                f"票數: {votes} ({percentage:.1f}%)\n"
                f"{bar}\n\n"
            )
            
            self.results_text.insert(tk.END, result_text)
            
    def add_candidate(self):
        """添加候選人"""
        name = self.candidate_name.get().strip()
        description = self.candidate_desc.get().strip()
        
        if not name:
            messagebox.showwarning("警告", "請輸入候選人姓名!")
            return
            
        # 生成新ID
        new_id = max([c["id"] for c in self.candidates], default=0) + 1
        
        # 添加候選人
        new_candidate = {
            "id": new_id,
            "name": name,
            "description": description
        }
        
        self.candidates.append(new_candidate)
        self.votes[new_id] = 0
        
        # 清空輸入框
        self.candidate_name.delete(0, tk.END)
        self.candidate_desc.delete(0, tk.END)
        
        # 更新顯示
        self.update_candidate_display()
        self.update_results()
        
        messagebox.showinfo("成功", f"候選人 {name} 添加成功!")
        
    def reset_votes(self):
        """重置所有投票"""
        if messagebox.askyesno("確認", "確定要重置所有投票數據嗎?"):
            for candidate_id in self.votes:
                self.votes[candidate_id] = 0
                
            self.update_results()
            messagebox.showinfo("成功", "所有投票數據已重置!")
            
    def export_data(self):
        """導出投票數據"""
        try:
            data = {
                "export_time": datetime.datetime.now().isoformat(),
                "candidates": self.candidates,
                "votes": self.votes,
                "total_votes": sum(self.votes.values())
            }
            
            with open("voting_data.json", "w", encoding="utf-8") as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
                
            messagebox.showinfo("成功", "投票數據已導出到 voting_data.json")
        except Exception as e:
            messagebox.showerror("錯誤", f"導出失敗: {str(e)}")

if __name__ == "__main__":
    root = tk.Tk()
    app = VotingSystem(root)
    root.mainloop()

IntVar的主要方法和屬性

# 創建IntVar
int_var = tk.IntVar()

# 主要方法
int_var.set(100)            # 設置值
value = int_var.get()       # 獲取值

# 跟蹤值變化
def callback(*args):
    print("值改變了")

int_var.trace_add("write", callback)  # 寫入時跟蹤
int_var.trace_add("read", callback)   # 讀取時跟蹤  
int_var.trace_add("unset", callback)  # 刪除時跟蹤

# 移除跟蹤
trace_id = int_var.trace_add("write", callback)
int_var.trace_remove("write", trace_id)

# 獲取變量名
variable_name = int_var._name

# 與組件關聯
# Scale組件
scale = tk.Scale(root, variable=int_var)

# Spinbox組件  
spinbox = tk.Spinbox(root, textvariable=int_var)

# Radiobutton組件
radio = tk.Radiobutton(root, variable=int_var, value=1)

# Checkbutton組件 (使用onvalue/offvalue)
check = tk.Checkbutton(root, variable=int_var, onvalue=1, offvalue=0)

使用場景總結

  1. 計數器應用:數字的增減和顯示
  2. 投票系統:記錄和統計票數
  3. 設置對話框:數值參數的配置
  4. 進度跟蹤:任務進度和狀態顯示
  5. 遊戲開發:分數、生命值等數值管理
  6. 數據採集:數值數據的輸入和驗證
  7. 儀器控制:參數設置和讀數顯示

IntVar提供了強大的整數管理能力,特別適合需要數值控制和實時數據更新的GUI應用程序。通過與各種Tkinter組件的結合使用,可以創建出功能豐富、響應靈敏的用户界面。