Widget(組件)是Tkinter中構建用户界面的基本元素。以下是Tkinter中所有主要Widget的全面詳解。

基本概念

Widget是Tkinter中所有可視化組件的基類,提供了通用的功能和屬性。

導入和基本使用

import tkinter as tk
from tkinter import ttk, messagebox

# 創建主窗口
root = tk.Tk()
root.title("Tkinter Widget詳解")
root.geometry("800x600")

基礎Widget類

示例1:Widget基礎屬性和方法

import tkinter as tk
from tkinter import ttk

class WidgetBasics:
    def __init__(self, root):
        self.root = root
        self.setup_ui()
        
    def setup_ui(self):
        """設置用户界面"""
        self.root.title("Widget基礎")
        
        # 創建主Frame
        main_frame = ttk.Frame(self.root, padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 標題
        title_label = ttk.Label(main_frame, text="Widget基礎屬性和方法", 
                               font=("Arial", 16, "bold"))
        title_label.pack(pady=(0, 20))
        
        # 1. 基本Widget操作
        self.create_basic_widget_section(main_frame)
        
        # 2. 幾何管理
        self.create_geometry_section(main_frame)
        
        # 3. 事件處理
        self.create_event_section(main_frame)
        
        # 4. 狀態管理
        self.create_state_section(main_frame)
        
    def create_basic_widget_section(self, parent):
        """創建基本Widget操作部分"""
        section_frame = ttk.LabelFrame(parent, text="1. 基本Widget操作", padding=10)
        section_frame.pack(fill=tk.X, pady=10)
        
        # 創建一些基本Widget
        button = ttk.Button(section_frame, text="測試按鈕")
        button.pack(side=tk.LEFT, padx=5)
        
        entry = ttk.Entry(section_frame)
        entry.pack(side=tk.LEFT, padx=5)
        entry.insert(0, "輸入文本")
        
        checkbutton = ttk.Checkbutton(section_frame, text="複選框")
        checkbutton.pack(side=tk.LEFT, padx=5)
        
        # Widget信息顯示
        info_frame = ttk.Frame(section_frame)
        info_frame.pack(side=tk.LEFT, padx=20)
        
        self.info_label = ttk.Label(info_frame, text="選擇Widget查看信息")
        self.info_label.pack()
        
        # 綁定點擊事件顯示信息
        widgets = [button, entry, checkbutton]
        for widget in widgets:
            widget.bind('<Button-1>', lambda e, w=widget: self.show_widget_info(w))
            
    def create_geometry_section(self, parent):
        """創建幾何管理部分"""
        section_frame = ttk.LabelFrame(parent, text="2. 幾何管理", padding=10)
        section_frame.pack(fill=tk.X, pady=10)
        
        # 創建測試Widget
        test_frame = ttk.Frame(section_frame, height=100, relief='solid')
        test_frame.pack(fill=tk.X, pady=5)
        test_frame.pack_propagate(False)  # 防止Frame收縮
        
        self.test_label = ttk.Label(test_frame, text="測試標籤", background='lightblue')
        self.test_label.pack(pady=20)
        
        # 幾何控制按鈕
        control_frame = ttk.Frame(section_frame)
        control_frame.pack(fill=tk.X, pady=5)
        
        geometry_buttons = [
            ("獲取位置", self.get_position),
            ("獲取大小", self.get_size),
            ("移動到(10,10)", lambda: self.move_widget(10, 10)),
            ("移動到中心", self.move_to_center),
            ("改變大小", self.resize_widget)
        ]
        
        for text, command in geometry_buttons:
            ttk.Button(control_frame, text=text, command=command).pack(side=tk.LEFT, padx=2)
            
    def create_event_section(self, parent):
        """創建事件處理部分"""
        section_frame = ttk.LabelFrame(parent, text="3. 事件處理", padding=10)
        section_frame.pack(fill=tk.X, pady=10)
        
        # 事件測試Widget
        event_frame = ttk.Frame(section_frame)
        event_frame.pack(fill=tk.X, pady=5)
        
        self.event_button = ttk.Button(event_frame, text="事件測試按鈕")
        self.event_button.pack(side=tk.LEFT, padx=5)
        
        self.event_entry = ttk.Entry(event_frame)
        self.event_entry.pack(side=tk.LEFT, padx=5)
        
        # 事件日誌
        self.event_log = tk.Text(section_frame, height=4, width=50)
        self.event_log.pack(fill=tk.X, pady=5)
        
        # 綁定事件
        self.bind_events()
        
    def create_state_section(self, parent):
        """創建狀態管理部分"""
        section_frame = ttk.LabelFrame(parent, text="4. 狀態管理", padding=10)
        section_frame.pack(fill=tk.X, pady=10)
        
        # 狀態測試Widget
        state_frame = ttk.Frame(section_frame)
        state_frame.pack(fill=tk.X, pady=5)
        
        self.state_button = ttk.Button(state_frame, text="狀態測試按鈕")
        self.state_button.pack(side=tk.LEFT, padx=5)
        
        # 狀態控制
        control_frame = ttk.Frame(section_frame)
        control_frame.pack(fill=tk.X, pady=5)
        
        state_buttons = [
            ("正常", lambda: self.set_widget_state('normal')),
            ("禁用", lambda: self.set_widget_state('disabled')),
            ("只讀", lambda: self.set_widget_state('readonly')),
            ("獲取狀態", self.get_widget_state)
        ]
        
        for text, command in state_buttons:
            ttk.Button(control_frame, text=text, command=command).pack(side=tk.LEFT, padx=2)
            
    def show_widget_info(self, widget):
        """顯示Widget信息"""
        info = f"""
        Widget類型: {type(widget).__name__}
        Widget ID: {str(widget)}
        類: {widget.winfo_class()}
        父級: {widget.winfo_parent()}
        子級數量: {len(widget.winfo_children())}
        """
        self.info_label.config(text=info)
        
    def get_position(self):
        """獲取Widget位置"""
        x = self.test_label.winfo_x()
        y = self.test_label.winfo_y()
        self.log_event(f"標籤位置: x={x}, y={y}")
        
    def get_size(self):
        """獲取Widget大小"""
        width = self.test_label.winfo_width()
        height = self.test_label.winfo_height()
        self.log_event(f"標籤大小: {width}x{height}")
        
    def move_widget(self, x, y):
        """移動Widget"""
        self.test_label.place(x=x, y=y)
        self.log_event(f"移動到: ({x}, {y})")
        
    def move_to_center(self):
        """移動到中心"""
        self.test_label.place(relx=0.5, rely=0.5, anchor='center')
        self.log_event("移動到中心")
        
    def resize_widget(self):
        """改變大小"""
        self.test_label.config(text="更大的標籤")
        self.log_event("大小已改變")
        
    def bind_events(self):
        """綁定事件"""
        # 按鈕事件
        self.event_button.bind('<Button-1>', lambda e: self.log_event("按鈕點擊"))
        self.event_button.bind('<Enter>', lambda e: self.log_event("鼠標進入按鈕"))
        self.event_button.bind('<Leave>', lambda e: self.log_event("鼠標離開按鈕"))
        
        # 輸入框事件
        self.event_entry.bind('<FocusIn>', lambda e: self.log_event("輸入框獲得焦點"))
        self.event_entry.bind('<FocusOut>', lambda e: self.log_event("輸入框失去焦點"))
        self.event_entry.bind('<KeyPress>', lambda e: self.log_event(f"按鍵: {e.keysym}"))
        
    def set_widget_state(self, state):
        """設置Widget狀態"""
        self.state_button.config(state=state)
        self.log_event(f"按鈕狀態設置為: {state}")
        
    def get_widget_state(self):
        """獲取Widget狀態"""
        state = self.state_button.cget('state')
        self.log_event(f"按鈕狀態: {state}")
        
    def log_event(self, message):
        """記錄事件"""
        self.event_log.insert(tk.END, f"{message}\n")
        self.event_log.see(tk.END)

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

完整Widget分類展示

示例2:Widget大全

import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
from tkinter import colorchooser, filedialog
import datetime

class WidgetGallery:
    def __init__(self, root):
        self.root = root
        self.setup_ui()
        
    def setup_ui(self):
        """設置用户界面"""
        self.root.title("Tkinter Widget大全")
        self.root.geometry("1000x800")
        
        # 創建主容器
        main_container = ttk.Frame(self.root)
        main_container.pack(fill=tk.BOTH, expand=True)
        
        # 創建Notebook
        notebook = ttk.Notebook(main_container)
        notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 基本Widget標籤頁
        self.create_basic_widgets_tab(notebook)
        
        # 輸入Widget標籤頁
        self.create_input_widgets_tab(notebook)
        
        # 選擇Widget標籤頁
        self.create_selection_widgets_tab(notebook)
        
        # 容器Widget標籤頁
        self.create_container_widgets_tab(notebook)
        
        # 高級Widget標籤頁
        self.create_advanced_widgets_tab(notebook)
        
    def create_basic_widgets_tab(self, notebook):
        """創建基本Widget標籤頁"""
        frame = ttk.Frame(notebook, padding=15)
        notebook.add(frame, text="基本Widget")
        
        # Label
        label_frame = ttk.LabelFrame(frame, text="Label 標籤", padding=10)
        label_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(label_frame, text="普通標籤").pack(side=tk.LEFT, padx=5)
        ttk.Label(label_frame, text="帶樣式的標籤", foreground="blue", 
                 font=("Arial", 10, "bold")).pack(side=tk.LEFT, padx=5)
        ttk.Label(label_frame, text="圖片標籤").pack(side=tk.LEFT, padx=5)
        
        # Button
        button_frame = ttk.LabelFrame(frame, text="Button 按鈕", padding=10)
        button_frame.pack(fill=tk.X, pady=5)
        
        ttk.Button(button_frame, text="普通按鈕", 
                  command=lambda: self.show_message("按鈕點擊")).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="禁用按鈕", 
                  state="disabled").pack(side=tk.LEFT, padx=5)
        
        # Frame
        frame_frame = ttk.LabelFrame(frame, text="Frame 框架", padding=10)
        frame_frame.pack(fill=tk.X, pady=5)
        
        inner_frame = ttk.Frame(frame_frame, relief="solid", borderwidth=1)
        inner_frame.pack(fill=tk.X, padx=5, pady=5)
        ttk.Label(inner_frame, text="內部框架內容").pack(pady=10)
        
    def create_input_widgets_tab(self, notebook):
        """創建輸入Widget標籤頁"""
        frame = ttk.Frame(notebook, padding=15)
        notebook.add(frame, text="輸入Widget")
        
        # Entry
        entry_frame = ttk.LabelFrame(frame, text="Entry 輸入框", padding=10)
        entry_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(entry_frame, text="普通輸入框:").pack(side=tk.LEFT)
        ttk.Entry(entry_frame).pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        
        # 密碼輸入框
        ttk.Label(entry_frame, text="密碼輸入框:").pack(side=tk.LEFT, padx=(20,0))
        ttk.Entry(entry_frame, show="*").pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        
        # Text
        text_frame = ttk.LabelFrame(frame, text="Text 文本框", padding=10)
        text_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        text_widget = scrolledtext.ScrolledText(text_frame, height=8)
        text_widget.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        text_widget.insert(tk.END, "這是一個多行文本框...\n可以輸入大量文本。")
        
        # Spinbox
        spinbox_frame = ttk.LabelFrame(frame, text="Spinbox 數字輸入框", padding=10)
        spinbox_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(spinbox_frame, text="數字選擇:").pack(side=tk.LEFT)
        ttk.Spinbox(spinbox_frame, from_=0, to=100, increment=1).pack(side=tk.LEFT, padx=5)
        
        # Scale
        scale_frame = ttk.LabelFrame(frame, text="Scale 滑塊", padding=10)
        scale_frame.pack(fill=tk.X, pady=5)
        
        self.scale_var = tk.IntVar(value=50)
        ttk.Scale(scale_frame, from_=0, to=100, variable=self.scale_var,
                 orient=tk.HORIZONTAL).pack(fill=tk.X, padx=5)
        ttk.Label(scale_frame, textvariable=self.scale_var).pack()
        
    def create_selection_widgets_tab(self, notebook):
        """創建選擇Widget標籤頁"""
        frame = ttk.Frame(notebook, padding=15)
        notebook.add(frame, text="選擇Widget")
        
        # Checkbutton
        check_frame = ttk.LabelFrame(frame, text="Checkbutton 複選框", padding=10)
        check_frame.pack(fill=tk.X, pady=5)
        
        self.check_var1 = tk.BooleanVar()
        self.check_var2 = tk.BooleanVar(value=True)
        self.check_var3 = tk.BooleanVar()
        
        ttk.Checkbutton(check_frame, text="選項1", variable=self.check_var1).pack(side=tk.LEFT, padx=5)
        ttk.Checkbutton(check_frame, text="選項2", variable=self.check_var2).pack(side=tk.LEFT, padx=5)
        ttk.Checkbutton(check_frame, text="選項3", variable=self.check_var3).pack(side=tk.LEFT, padx=5)
        
        # Radiobutton
        radio_frame = ttk.LabelFrame(frame, text="Radiobutton 單選按鈕", padding=10)
        radio_frame.pack(fill=tk.X, pady=5)
        
        self.radio_var = tk.StringVar(value="A")
        ttk.Radiobutton(radio_frame, text="選項A", variable=self.radio_var, 
                       value="A").pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(radio_frame, text="選項B", variable=self.radio_var, 
                       value="B").pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(radio_frame, text="選項C", variable=self.radio_var, 
                       value="C").pack(side=tk.LEFT, padx=5)
        
        # Listbox
        listbox_frame = ttk.LabelFrame(frame, text="Listbox 列表框", padding=10)
        listbox_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        listbox_container = ttk.Frame(listbox_frame)
        listbox_container.pack(fill=tk.BOTH, expand=True)
        
        listbox = tk.Listbox(listbox_container)
        listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 添加滾動條
        scrollbar = ttk.Scrollbar(listbox_container, orient=tk.VERTICAL, command=listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        listbox.config(yscrollcommand=scrollbar.set)
        
        # 添加示例數據
        for i in range(1, 21):
            listbox.insert(tk.END, f"列表項 {i}")
            
        # Combobox
        combo_frame = ttk.LabelFrame(frame, text="Combobox 組合框", padding=10)
        combo_frame.pack(fill=tk.X, pady=5)
        
        self.combo_var = tk.StringVar()
        combo = ttk.Combobox(combo_frame, textvariable=self.combo_var, 
                            values=["Python", "Java", "JavaScript", "C++", "Go"])
        combo.set("選擇編程語言")
        combo.pack(fill=tk.X, padx=5)
        
    def create_container_widgets_tab(self, notebook):
        """創建容器Widget標籤頁"""
        frame = ttk.Frame(notebook, padding=15)
        notebook.add(frame, text="容器Widget")
        
        # LabelFrame
        labelframe = ttk.LabelFrame(frame, text="LabelFrame 帶標籤框架", padding=10)
        labelframe.pack(fill=tk.X, pady=5)
        
        ttk.Label(labelframe, text="這是一個LabelFrame的內容").pack(pady=5)
        ttk.Button(labelframe, text="框架內按鈕").pack(pady=5)
        
        # PanedWindow
        paned_frame = ttk.LabelFrame(frame, text="PanedWindow 可調整面板", padding=10)
        paned_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        paned = ttk.PanedWindow(paned_frame, orient=tk.HORIZONTAL)
        paned.pack(fill=tk.BOTH, expand=True)
        
        left_pane = ttk.Frame(paned, relief="sunken", borderwidth=1)
        right_pane = ttk.Frame(paned, relief="sunken", borderwidth=1)
        
        ttk.Label(left_pane, text="左側面板").pack(pady=20)
        ttk.Label(right_pane, text="右側面板").pack(pady=20)
        
        paned.add(left_pane, weight=1)
        paned.add(right_pane, weight=1)
        
        # Notebook
        notebook_frame = ttk.LabelFrame(frame, text="Notebook 標籤頁", padding=10)
        notebook_frame.pack(fill=tk.X, pady=5)
        
        inner_notebook = ttk.Notebook(notebook_frame)
        inner_notebook.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        tab1 = ttk.Frame(inner_notebook)
        tab2 = ttk.Frame(inner_notebook)
        
        inner_notebook.add(tab1, text="標籤1")
        inner_notebook.add(tab2, text="標籤2")
        
        ttk.Label(tab1, text="標籤1的內容").pack(pady=20)
        ttk.Label(tab2, text="標籤2的內容").pack(pady=20)
        
    def create_advanced_widgets_tab(self, notebook):
        """創建高級Widget標籤頁"""
        frame = ttk.Frame(notebook, padding=15)
        notebook.add(frame, text="高級Widget")
        
        # Progressbar
        progress_frame = ttk.LabelFrame(frame, text="Progressbar 進度條", padding=10)
        progress_frame.pack(fill=tk.X, pady=5)
        
        self.progress = ttk.Progressbar(progress_frame, orient=tk.HORIZONTAL, 
                                       length=200, mode='determinate')
        self.progress.pack(pady=5)
        self.progress['value'] = 50
        
        ttk.Button(progress_frame, text="增加進度", 
                  command=self.increase_progress).pack(side=tk.LEFT, padx=5)
        ttk.Button(progress_frame, text="重置進度", 
                  command=self.reset_progress).pack(side=tk.LEFT, padx=5)
        
        # Treeview
        tree_frame = ttk.LabelFrame(frame, text="Treeview 樹形視圖", padding=10)
        tree_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        tree = ttk.Treeview(tree_frame, columns=("姓名", "年齡", "城市"), show="headings")
        tree.heading("姓名", text="姓名")
        tree.heading("年齡", text="年齡")
        tree.heading("城市", text="城市")
        
        # 添加示例數據
        data = [
            ("張三", "25", "北京"),
            ("李四", "30", "上海"),
            ("王五", "28", "廣州"),
            ("趙六", "35", "深圳")
        ]
        
        for item in data:
            tree.insert("", tk.END, values=item)
            
        tree.pack(fill=tk.BOTH, expand=True)
        
        # Separator
        separator_frame = ttk.LabelFrame(frame, text="Separator 分隔符", padding=10)
        separator_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(separator_frame, text="上方內容").pack(pady=5)
        ttk.Separator(separator_frame, orient=tk.HORIZONTAL).pack(fill=tk.X, padx=10, pady=5)
        ttk.Label(separator_frame, text="下方內容").pack(pady=5)
        
        # Sizegrip
        sizegrip_frame = ttk.LabelFrame(frame, text="Sizegrip 大小調整柄", padding=10)
        sizegrip_frame.pack(fill=tk.X, pady=5)
        
        ttk.Sizegrip(sizegrip_frame).pack(side=tk.RIGHT)
        ttk.Label(sizegrip_frame, text="拖動右下角調整窗口大小").pack(side=tk.LEFT)
        
    def show_message(self, message):
        """顯示消息"""
        messagebox.showinfo("消息", message)
        
    def increase_progress(self):
        """增加進度"""
        current = self.progress['value']
        if current < 100:
            self.progress['value'] = current + 10
            
    def reset_progress(self):
        """重置進度"""
        self.progress['value'] = 0

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

實際應用示例

示例3:綜合應用程序

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

class TaskManagerApp:
    def __init__(self, root):
        self.root = root
        self.tasks = []
        self.setup_ui()
        self.load_sample_tasks()
        
    def setup_ui(self):
        """設置用户界面"""
        self.root.title("任務管理器 - Tkinter Widget綜合應用")
        self.root.geometry("1200x800")
        
        # 創建主容器
        main_container = ttk.Frame(self.root)
        main_container.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 創建標題
        title_label = ttk.Label(main_container, text="個人任務管理器", 
                               font=("Arial", 20, "bold"))
        title_label.pack(pady=(0, 20))
        
        # 創建主要內容區域
        content_frame = ttk.Frame(main_container)
        content_frame.pack(fill=tk.BOTH, expand=True)
        
        # 左側任務列表
        self.create_task_list_panel(content_frame)
        
        # 右側任務詳情
        self.create_task_detail_panel(content_frame)
        
        # 底部狀態欄
        self.create_status_bar(main_container)
        
    def create_task_list_panel(self, parent):
        """創建任務列表面板"""
        list_frame = ttk.LabelFrame(parent, text="任務列表", padding=10)
        list_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))
        
        # 搜索和過濾
        search_frame = ttk.Frame(list_frame)
        search_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(search_frame, text="搜索:").pack(side=tk.LEFT)
        self.search_var = tk.StringVar()
        search_entry = ttk.Entry(search_frame, textvariable=self.search_var)
        search_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        search_entry.bind('<KeyRelease>', self.filter_tasks)
        
        # 過濾選項
        filter_frame = ttk.Frame(list_frame)
        filter_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(filter_frame, text="狀態過濾:").pack(side=tk.LEFT)
        self.status_filter = ttk.Combobox(filter_frame, values=["全部", "待辦", "進行中", "完成"], 
                                         state="readonly")
        self.status_filter.set("全部")
        self.status_filter.pack(side=tk.LEFT, padx=5)
        self.status_filter.bind('<<ComboboxSelected>>', self.filter_tasks)
        
        # 任務列表
        list_container = ttk.Frame(list_frame)
        list_container.pack(fill=tk.BOTH, expand=True)
        
        # 創建Treeview
        columns = ("ID", "標題", "優先級", "狀態", "截止日期")
        self.task_tree = ttk.Treeview(list_container, columns=columns, show="headings", height=15)
        
        # 設置列
        self.task_tree.heading("ID", text="ID")
        self.task_tree.heading("標題", text="標題")
        self.task_tree.heading("優先級", text="優先級")
        self.task_tree.heading("狀態", text="狀態")
        self.task_tree.heading("截止日期", text="截止日期")
        
        self.task_tree.column("ID", width=50)
        self.task_tree.column("標題", width=200)
        self.task_tree.column("優先級", width=80)
        self.task_tree.column("狀態", width=80)
        self.task_tree.column("截止日期", width=100)
        
        # 滾動條
        scrollbar = ttk.Scrollbar(list_container, orient=tk.VERTICAL, command=self.task_tree.yview)
        self.task_tree.configure(yscrollcommand=scrollbar.set)
        
        self.task_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 綁定選擇事件
        self.task_tree.bind('<<TreeviewSelect>>', self.on_task_select)
        
        # 列表操作按鈕
        list_buttons_frame = ttk.Frame(list_frame)
        list_buttons_frame.pack(fill=tk.X, pady=(10, 0))
        
        ttk.Button(list_buttons_frame, text="新建任務", 
                  command=self.create_new_task).pack(side=tk.LEFT, padx=2)
        ttk.Button(list_buttons_frame, text="刪除任務", 
                  command=self.delete_task).pack(side=tk.LEFT, padx=2)
        ttk.Button(list_buttons_frame, text="刷新列表", 
                  command=self.refresh_task_list).pack(side=tk.LEFT, padx=2)
        
    def create_task_detail_panel(self, parent):
        """創建任務詳情面板"""
        detail_frame = ttk.LabelFrame(parent, text="任務詳情", padding=10)
        detail_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(10, 0))
        
        # 任務表單
        form_frame = ttk.Frame(detail_frame)
        form_frame.pack(fill=tk.X, pady=5)
        
        # 標題
        ttk.Label(form_frame, text="標題:").grid(row=0, column=0, sticky="w", pady=2)
        self.title_var = tk.StringVar()
        title_entry = ttk.Entry(form_frame, textvariable=self.title_var, width=40)
        title_entry.grid(row=0, column=1, sticky="ew", pady=2, padx=5)
        
        # 描述
        ttk.Label(form_frame, text="描述:").grid(row=1, column=0, sticky="nw", pady=2)
        self.description_text = scrolledtext.ScrolledText(form_frame, width=40, height=8)
        self.description_text.grid(row=1, column=1, sticky="ew", pady=2, padx=5)
        
        # 優先級
        ttk.Label(form_frame, text="優先級:").grid(row=2, column=0, sticky="w", pady=2)
        self.priority_var = tk.StringVar(value="中")
        priority_combo = ttk.Combobox(form_frame, textvariable=self.priority_var,
                                     values=["低", "中", "高"], state="readonly")
        priority_combo.grid(row=2, column=1, sticky="w", pady=2, padx=5)
        
        # 狀態
        ttk.Label(form_frame, text="狀態:").grid(row=3, column=0, sticky="w", pady=2)
        self.status_var = tk.StringVar(value="待辦")
        status_combo = ttk.Combobox(form_frame, textvariable=self.status_var,
                                   values=["待辦", "進行中", "完成"], state="readonly")
        status_combo.grid(row=3, column=1, sticky="w", pady=2, padx=5)
        
        # 截止日期
        ttk.Label(form_frame, text="截止日期:").grid(row=4, column=0, sticky="w", pady=2)
        date_frame = ttk.Frame(form_frame)
        date_frame.grid(row=4, column=1, sticky="w", pady=2, padx=5)
        
        self.due_date = ttk.Entry(date_frame, width=15)
        self.due_date.pack(side=tk.LEFT)
        ttk.Button(date_frame, text="今天", 
                  command=self.set_today_date).pack(side=tk.LEFT, padx=5)
        
        # 配置權重
        form_frame.columnconfigure(1, weight=1)
        
        # 詳情操作按鈕
        detail_buttons_frame = ttk.Frame(detail_frame)
        detail_buttons_frame.pack(fill=tk.X, pady=10)
        
        ttk.Button(detail_buttons_frame, text="保存任務", 
                  command=self.save_task, style='Accent.TButton').pack(side=tk.LEFT, padx=5)
        ttk.Button(detail_buttons_frame, text="清除表單", 
                  command=self.clear_form).pack(side=tk.LEFT, padx=5)
        
        # 任務統計
        stats_frame = ttk.LabelFrame(detail_frame, text="任務統計", padding=10)
        stats_frame.pack(fill=tk.X, pady=10)
        
        self.stats_label = ttk.Label(stats_frame, text="總任務: 0 | 完成: 0 | 進行中: 0 | 待辦: 0")
        self.stats_label.pack()
        
    def create_status_bar(self, parent):
        """創建狀態欄"""
        status_frame = ttk.Frame(parent, relief="sunken", borderwidth=1)
        status_frame.pack(fill=tk.X, pady=(10, 0))
        
        self.status_var = tk.StringVar(value="就緒")
        status_label = ttk.Label(status_frame, textvariable=self.status_var)
        status_label.pack(side=tk.LEFT, padx=10)
        
        # 當前時間
        self.time_var = tk.StringVar()
        time_label = ttk.Label(status_frame, textvariable=self.time_var)
        time_label.pack(side=tk.RIGHT, padx=10)
        
        self.update_time()
        
    def load_sample_tasks(self):
        """加載示例任務"""
        sample_tasks = [
            {
                "id": 1,
                "title": "學習Tkinter",
                "description": "深入學習Tkinter的各種組件和功能",
                "priority": "高",
                "status": "進行中",
                "due_date": "2024-01-15"
            },
            {
                "id": 2,
                "title": "編寫項目文檔",
                "description": "完成項目需求文檔和技術文檔",
                "priority": "中",
                "status": "待辦",
                "due_date": "2024-01-20"
            },
            {
                "id": 3,
                "title": "代碼審查",
                "description": "審查團隊成員的代碼提交",
                "priority": "中",
                "status": "完成",
                "due_date": "2024-01-10"
            }
        ]
        
        self.tasks = sample_tasks
        self.refresh_task_list()
        
    def refresh_task_list(self):
        """刷新任務列表"""
        # 清空現有數據
        for item in self.task_tree.get_children():
            self.task_tree.delete(item)
            
        # 添加任務數據
        for task in self.tasks:
            self.task_tree.insert("", tk.END, values=(
                task["id"],
                task["title"],
                task["priority"],
                task["status"],
                task["due_date"]
            ))
            
        self.update_stats()
        
    def filter_tasks(self, event=None):
        """過濾任務"""
        search_text = self.search_var.get().lower()
        status_filter = self.status_filter.get()
        
        # 清空現有數據
        for item in self.task_tree.get_children():
            self.task_tree.delete(item)
            
        # 過濾並添加任務
        for task in self.tasks:
            if search_text and search_text not in task["title"].lower():
                continue
                
            if status_filter != "全部" and status_filter != task["status"]:
                continue
                
            self.task_tree.insert("", tk.END, values=(
                task["id"],
                task["title"],
                task["priority"],
                task["status"],
                task["due_date"]
            ))
            
    def on_task_select(self, event):
        """任務選擇事件"""
        selection = self.task_tree.selection()
        if selection:
            item = selection[0]
            values = self.task_tree.item(item, "values")
            task_id = int(values[0])
            
            # 查找任務詳情
            task = next((t for t in self.tasks if t["id"] == task_id), None)
            if task:
                self.load_task_to_form(task)
                
    def load_task_to_form(self, task):
        """加載任務到表單"""
        self.title_var.set(task["title"])
        self.description_text.delete(1.0, tk.END)
        self.description_text.insert(1.0, task["description"])
        self.priority_var.set(task["priority"])
        self.status_var.set(task["status"])
        self.due_date.delete(0, tk.END)
        self.due_date.insert(0, task["due_date"])
        
        self.current_task_id = task["id"]
        
    def create_new_task(self):
        """創建新任務"""
        self.clear_form()
        self.current_task_id = None
        self.status_var.set("新建任務")
        
    def save_task(self):
        """保存任務"""
        if not self.title_var.get().strip():
            messagebox.showerror("錯誤", "請輸入任務標題")
            return
            
        task_data = {
            "title": self.title_var.get(),
            "description": self.description_text.get(1.0, tk.END).strip(),
            "priority": self.priority_var.get(),
            "status": self.status_var.get(),
            "due_date": self.due_date.get()
        }
        
        if hasattr(self, 'current_task_id') and self.current_task_id:
            # 更新現有任務
            task = next((t for t in self.tasks if t["id"] == self.current_task_id), None)
            if task:
                task.update(task_data)
        else:
            # 創建新任務
            new_id = max([t["id"] for t in self.tasks], default=0) + 1
            task_data["id"] = new_id
            self.tasks.append(task_data)
            
        self.refresh_task_list()
        messagebox.showinfo("成功", "任務已保存")
        
    def delete_task(self):
        """刪除任務"""
        selection = self.task_tree.selection()
        if not selection:
            messagebox.showwarning("警告", "請選擇要刪除的任務")
            return
            
        if messagebox.askyesno("確認", "確定要刪除選中的任務嗎?"):
            item = selection[0]
            values = self.task_tree.item(item, "values")
            task_id = int(values[0])
            
            self.tasks = [t for t in self.tasks if t["id"] != task_id]
            self.refresh_task_list()
            self.clear_form()
            
    def clear_form(self):
        """清除表單"""
        self.title_var.set("")
        self.description_text.delete(1.0, tk.END)
        self.priority_var.set("中")
        self.status_var.set("待辦")
        self.due_date.delete(0, tk.END)
        
        if hasattr(self, 'current_task_id'):
            del self.current_task_id
            
    def set_today_date(self):
        """設置今天日期"""
        today = datetime.datetime.now().strftime("%Y-%m-%d")
        self.due_date.delete(0, tk.END)
        self.due_date.insert(0, today)
        
    def update_stats(self):
        """更新統計信息"""
        total = len(self.tasks)
        completed = len([t for t in self.tasks if t["status"] == "完成"])
        in_progress = len([t for t in self.tasks if t["status"] == "進行中"])
        pending = len([t for t in self.tasks if t["status"] == "待辦"])
        
        self.stats_label.config(
            text=f"總任務: {total} | 完成: {completed} | 進行中: {in_progress} | 待辦: {pending}"
        )
        
    def update_time(self):
        """更新時間顯示"""
        current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.time_var.set(current_time)
        self.root.after(1000, self.update_time)

if __name__ == "__main__":
    root = tk.Tk()
    
    # 配置樣式
    style = ttk.Style()
    style.configure('Accent.TButton', foreground='white', background='#3498db')
    
    app = TaskManagerApp(root)
    root.mainloop()

Widget的主要方法和屬性

# 創建Widget
widget = tk.Widget(parent, **options)

# 幾何管理方法
widget.pack(**options)          # pack佈局
widget.grid(**options)          # grid佈局
widget.place(**options)         # place佈局

# 配置方法
widget.config(**options)        # 配置選項
widget.cget('option')           # 獲取選項值
widget.keys()                   # 獲取所有選項

# 狀態方法
widget['state'] = 'normal'      # 設置狀態
widget.state(['disabled'])      # 設置狀態 (ttk)

# 事件綁定
widget.bind('<event>', handler) # 綁定事件
widget.unbind('<event>')        # 解綁事件

# 信息獲取
widget.winfo_x()                # 獲取x座標
widget.winfo_y()                # 獲取y座標
widget.winfo_width()            # 獲取寬度
widget.winfo_height()           # 獲取高度
widget.winfo_children()         # 獲取子組件

# 焦點管理
widget.focus_set()              # 設置焦點
widget.focus_get()              # 獲取焦點組件

常用Widget選項

# 通用選項
text="文本"                    # 顯示文本
background="color"            # 背景色
foreground="color"            # 前景色
font=("Arial", 12)            # 字體
width=100                     # 寬度
height=50                     # 高度
state="normal"                # 狀態

# 佈局選項
padx=10                       # 水平間距
pady=10                       # 垂直間距
relief="solid"                # 邊框樣式
borderwidth=2                 # 邊框寬度

# 特定Widget選項
# Button
command=callback              # 點擊命令

# Entry
show="*"                      # 顯示字符
textvariable=var              # 文本變量

# Text
wrap="word"                   # 換行方式

# Listbox
selectmode="multiple"         # 選擇模式

使用場景總結

  1. 表單應用:數據輸入和驗證
  2. 數據展示:表格、樹形視圖顯示數據
  3. 文件管理:文件瀏覽和操作
  4. 設置界面:應用程序配置
  5. 儀表板:數據可視化和管理
  6. 文本編輯:代碼編輯器、文檔編輯
  7. 遊戲界面:遊戲控制和狀態顯示

Widget是Tkinter應用程序的基礎,通過合理組合和使用各種Widget,可以創建出功能豐富、用户友好的桌面應用程序。