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)
使用場景總結
- 計數器應用:數字的增減和顯示
- 投票系統:記錄和統計票數
- 設置對話框:數值參數的配置
- 進度跟蹤:任務進度和狀態顯示
- 遊戲開發:分數、生命值等數值管理
- 數據採集:數值數據的輸入和驗證
- 儀器控制:參數設置和讀數顯示
IntVar提供了強大的整數管理能力,特別適合需要數值控制和實時數據更新的GUI應用程序。通過與各種Tkinter組件的結合使用,可以創建出功能豐富、響應靈敏的用户界面。