Tkinter - 快速开始

安装

Tkinter 随 Python 一同发行。验证其是否可用:

终端

python -c "import tkinter; print(tkinter.TkVersion)"
# 应输出:8.6

⚠️ Linux 用户

在 Ubuntu/Debian 上,运行:sudo apt-get install python3-tk

你的第一个窗口

每个 Tkinter 应用程序都遵循相同的三步模式:

  1. 创建根窗口 —— tk.Tk()
  2. 在窗口内添加控件
  3. 启动事件循环 —— root.mainloop()

first_window.py

import tkinter as tk

root = tk.Tk()
root.title("我的第一个应用")
root.geometry("400x300")  # 宽度 x 高度
root.mainloop()

完整应用:温度转换器

temp_converter.py

import tkinter as tk
from tkinter import ttk

class TempConverter(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("温度转换器")
        self.resizable(False, False)
        self.celsius    = tk.StringVar(value="0")
        self.fahrenheit = tk.StringVar(value="32")
        self._build_ui()
        self.celsius.trace_add("write", self._from_c)
        self.fahrenheit.trace_add("write", self._from_f)

    def _build_ui(self):
        f = ttk.Frame(self, padding=20)
        f.pack()
        ttk.Label(f, text="°C").grid(row=0, column=1)
        ttk.Entry(f, textvariable=self.celsius,    width=10).grid(row=0, column=0)
        ttk.Label(f, text=" = ").grid(row=0, column=2)
        ttk.Entry(f, textvariable=self.fahrenheit, width=10).grid(row=0, column=3)
        ttk.Label(f, text="°F").grid(row=0, column=4)

    def _from_c(self, *_):
        try: self.fahrenheit.set(f"{float(self.celsius.get())*9/5+32:.2f}")
        except: pass

    def _from_f(self, *_):
        try: self.celsius.set(f"{(float(self.fahrenheit.get())-32)*5/9:.2f}")
        except: pass

TempConverter().mainloop()

💡 基于类的应用
继承 tk.Tk 可以使你的代码组织更清晰,并且在应用规模扩大时保持良好的可扩展性。
这段代码实现了一个实时温度转换器,它会在输入摄氏温度或华氏温度时自动计算并更新另一个值。下面逐步分析:


1. 整体架构

class TempConverter(tk.Tk):
  • 类继承自 tk.Tk,即应用主窗口本身就是一个完整的 Tkinter 应用程序。
  • 这种面向对象的设计便于管理状态和方法,比面向过程的写法更易扩展。

2. __init__ 初始化方法

super().__init__()
self.title("温度转换器")
self.resizable(False, False)
  • super().__init__():调用父类 tk.Tk 的构造函数,完成窗口底层初始化。
  • title():设置窗口标题。
  • resizable(False, False):禁止用户拖拽改变窗口大小(宽和高均固定)。
self.celsius = tk.StringVar(value="0")
self.fahrenheit = tk.StringVar(value="32")
  • 创建两个 StringVar 变量,用于双向绑定输入框的内容。
  • 初始值分别为 "0""32"(0°C = 32°F),启动时即显示正确对应关系。
self._build_ui()
  • 调用私有方法构建界面控件。
self.celsius.trace_add("write", self._from_c)
self.fahrenheit.trace_add("write", self._from_f)
  • trace_add("write", callback):为变量添加写入监听器
  • 当摄氏输入框内容发生变化(用户键入或程序修改)时,自动调用 _from_c 更新华氏值。
  • 同理,华氏变化时调用 _from_f 更新摄氏值。
  • 这实现了双向实时同步,无需按钮触发。

3. _build_ui 界面布局

f = ttk.Frame(self, padding=20)
f.pack()
  • 创建一个 ttk.Frame 作为容器,padding=20 提供 20 像素的内边距。
  • pack() 将框架放入主窗口并自动填充。

布局结构(一行网格)

ttk.Label(f, text="°C").grid(row=0, column=1)
ttk.Entry(f, textvariable=self.celsius, width=10).grid(row=0, column=0)
ttk.Label(f, text=" = ").grid(row=0, column=2)
ttk.Entry(f, textvariable=self.fahrenheit, width=10).grid(row=0, column=3)
ttk.Label(f, text="°F").grid(row=0, column=4)

使用 grid() 在同一行(row=0)排布 5 列:

列 0 列 1 列 2 列 3 列 4
摄氏输入框 °C 标签 = 标签 华氏输入框 °F 标签

布局视觉效果:[ 输入框 ] °C = [ 输入框 ] °F


4. 转换回调方法

_from_c — 摄氏 → 华氏

def _from_c(self, *_):
    try: 
        self.fahrenheit.set(f"{float(self.celsius.get())*9/5+32:.2f}")
    except: 
        pass
  • 获取摄氏值,转为浮点数,计算华氏:°F = °C × 9/5 + 32
  • 结果保留两位小数(:.2f)后设置到 fahrenheit 变量。
  • 如果输入为空或非数字,float() 抛出异常,被 except 静默捕获(无操作)。

_from_f — 华氏 → 摄氏

def _from_f(self, *_):
    try: 
        self.celsius.set(f"{(float(self.fahrenheit.get())-32)*5/9:.2f}")
    except: 
        pass
  • 计算摄氏:°C = (°F - 32) × 5/9
  • 同样处理异常情况。

5. 启动应用

TempConverter().mainloop()
  • 创建 TempConverter 实例并启动 Tkinter 事件循环。
  • 窗口显示后,程序持续响应用户输入,直到关闭窗口。

6. 代码亮点总结

特性 实现方式
双向实时转换 StringVar.trace_add("write", callback) 监听变量变化
异常安全 空输入或无效字符时静默忽略,不会崩溃
界面布局 grid() 实现简洁的一行布局,Frame 提供内边距
面向对象 继承 tk.Tk,将窗口、变量、UI 构建、逻辑封装于一个类中
固定窗口大小 resizable(False, False) 保证布局不变形

7. 运行效果

  • 窗口标题为 "温度转换器"。
  • 两个输入框并排显示,初始为 "0" 和 "32"。
  • 在任一输入框中修改数值,另一个输入框会自动同步更新对应的温度值。
  • 输入无效内容(如字母或空值)时,另一个输入框保持不变(不更新)。

8. 潜在改进点

  • 输入验证:目前无效输入会被忽略,可以添加验证器或错误提示。
  • 支持更多温标:可扩展为开尔文、列氏度等。
  • 布局灵活性:可改用 gridstickypadx 调整控件间距。
  • 热键支持:可添加键盘快捷键(如 Enter 触发转换)。
posted @ 2026-07-09 07:57  箫笛  阅读(5)  评论(0)    收藏  举报