惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
The Last Watchdog
The Last Watchdog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
Troy Hunt's Blog
L
LINUX DO - 最新话题
C
Check Point Blog
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
V
Vulnerabilities – Threatpost
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
J
Java Code Geeks
Apple Machine Learning Research
Apple Machine Learning Research
大猫的无限游戏
大猫的无限游戏
S
Security @ Cisco Blogs
IT之家
IT之家
T
The Exploit Database - CXSecurity.com
The GitHub Blog
The GitHub Blog
D
Docker
Engineering at Meta
Engineering at Meta
AWS News Blog
AWS News Blog
S
Security Affairs
U
Unit 42
P
Palo Alto Networks Blog
V
Visual Studio Blog
Y
Y Combinator Blog
D
DataBreaches.Net
Forbes - Security
Forbes - Security
阮一峰的网络日志
阮一峰的网络日志
美团技术团队
Security Latest
Security Latest
aimingoo的专栏
aimingoo的专栏
Simon Willison's Weblog
Simon Willison's Weblog
A
Arctic Wolf
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Hacker News: Front Page
博客园 - 司徒正美
博客园 - Franky
宝玉的分享
宝玉的分享
TaoSecurity Blog
TaoSecurity Blog
Latest news
Latest news
Scott Helme
Scott Helme
MongoDB | Blog
MongoDB | Blog
量子位
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Cisco Blogs
P
Privacy International News Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog

博客园 - 箫笛

Tkinter - Label 组件 Tkinter - tk 变量 Tkinter - 事件与绑定 Tkinter - 几何管理器 Tkinter - 核心概念 Tkinter - 快速开始 Tkinter - 介绍 Python 编程 - 条件表达式 Python 编程 - 星号下划线参数释义 shell 编程 - shell 脚本的交互方式 Python insall - macOS 系统安装python的几种方式 Miniconda - Python 环境管理工具 Tkinter - Python GUI 开发 Python 编程 - 下划线命名的区别 Python 编程 - 元类编程 Python 编程 - 多重继承与MRO Python 编程 - 描述符协议 Python 编程 - 类型注解 Python 编程 - 生成器表达式 Python 编程 - 集合 Python 编程 - 装饰器 Python 编程 - 闭包 Python 编程 - 列表推导式 Python 编程 - 函数式编程 Python 编程 - lambda 函数 Python 编程 - 文件操作 Python 编程 - 输入与输出 Python 编程 - 面向对象编程 Python 编程 - 元组(tuple) Python 编程 - 字符串(str) Python 编程 - 字典(dict) Python 编程 - 列表(list) Python 编程 - 数据类型和数据结构 Python 编程 - 语句 Python 编程 - 函数 windows - WSL 的安装与使用 shell编程 - dialog 程序使用指南 FE Team - 如何做好前端代码审查 git 提交的撤销和恢复 React15 - redux-saga 如何在saga中实现轮询接口调用? React15 - React CSS Modules BEM命名实践 React15 - React 15 中 componentWillReceiveProps 为什么会多次调用, 同时componentDidUpdate 也会多次调用? React15 - React15类组件多次执行render方法的原因? React15 - React15应用中代码逻辑复用方案 React15 - React状态同步问题解决 React15 - React 15 中 React.pureComponent 的使用场景 React15 - React 15应用在页面渲染时会多次执行类组件的render 函数的原因 React15 - React 15 中能用 componetDidUpdate 代替 componentWillReceiveProps 吗? React15 - React 15 生命周期函数详解 React15 - 如何在React 15中实现自定义的事件订阅与发送(例如组件间通信) React15 - React15应用中的事件订阅和发送机制 React15 - CSS中的BEM规范 React15 - React CSS Modules BEM命名实践 React15 - 写sass 样式文件,嵌套的结构好,还是扁平的结构好? React15 - sass 中 @mixin 和 @extend 的区别是什么? React15 - React 15 应用 如何使用Css moudules 方式进行模块化开发 React15 - React15应用Sass使用指南 React15 - React 15 应用如何进行性能优化?
Tkinter - Button 组件
箫笛 · 2026-07-17 · via 博客园 - 箫笛

Button(按钮)
可点击的操作和命令触发器


tk.Buttonttk.Button

button_demo.py

ttk.Button(root, text="点击我", command=on_click).pack(pady=8)

# 加载状态模式
def on_submit():
    btn.state(["disabled"])
    btn.config(text="处理中…")
    def done():
        btn.config(text="提交")
        btn.state(["!disabled"])
    root.after(2000, done)   # 模拟工作

btn = ttk.Button(root, text="提交", command=on_submit)
btn.pack(pady=12)

关键选项

选项 说明
text 按钮标签文字
command 点击时调用的函数(不传递参数)
textvariable 提供标签内容的 StringVar 变量
image / compound 图像与文字的排列方式
state normal/active/disabled(仅限 tk.Button);对于 ttk 请使用 state() 方法
width 宽度(以字符数为单位)

方法

  • button.invoke() —— 以编程方式模拟按钮点击
  • button.state(["disabled"]) —— ttk 状态标志(设置禁用)
  • button.state(["!disabled"]) —— ttk 移除标志(前缀 ! 表示移除)

代码释义

这段代码展示了 Tkinter 中 按钮点击响应的两种常见模式:一是简单的命令绑定,二是“加载状态”防重复点击模式(提升用户体验)。下面逐段拆解:

第一部分:最简按钮

ttk.Button(root, text="点击我", command=on_click).pack(pady=8)
  • 作用:创建一个文本为“点击我”的按钮,点击后立即执行 on_click 函数。
  • 注意:这段代码假设 on_click 函数已在前面定义(例如 def on_click(): print("被点了")),否则程序会报错 NameError
  • 按钮生成后直接 pack 布局,添加 8 像素垂直外间距。

第二部分:“加载状态”模式(核心)

def on_submit():
    btn.state(["disabled"])
    btn.config(text="处理中…")
    def done():
        btn.config(text="提交")
        btn.state(["!disabled"])
    root.after(2000, done)

btn = ttk.Button(root, text="提交", command=on_submit)
btn.pack(pady=12)

这段代码解决了一个常见痛点:用户点击提交按钮后,如果后端处理耗时较长,用户可能会疯狂反复点击,导致重复提交或界面卡死

执行流程拆解:

  1. 点击触发:用户点击“提交”按钮,调用 on_submit() 函数。
  2. 立即禁用并改文字(防止重复点击):
    • btn.state(["disabled"]):将按钮状态设为“禁用”(灰色不可点)。
    • btn.config(text="处理中…"):按钮文字变为“处理中…”,给用户视觉反馈“正在干活”。
  3. 定义收尾函数 done(闭包):
    • 这个函数嵌套在 on_submit 内部,可以访问外部的 btn 变量。
    • 执行时,将按钮文字改回“提交”,并移除禁用状态(["!disabled"]! 前缀表示移除该状态)。
  4. 定时执行收尾(模拟耗时任务):
    • root.after(2000, done):告诉 Tkinter 在 2000 毫秒(2秒)后执行 done 函数。
    • 这模拟了网络请求、数据处理等耗时操作。2 秒后,按钮自动恢复为可点击状态。

为什么要这样写?(Python 闭包特性)

这里有一个关键点需要留意:定义 btn 在前,还是定义 on_submit 在前?

代码中是先定义 on_submit(函数),后创建 btn(变量)

def on_submit():
    btn.state(["disabled"])   # 这里引用了 btn,但此时 btn 还没定义!
    ...

btn = ttk.Button(...)        # 后定义
  • 在 Python 中,函数体内部的变量只是在调用时才去查找。只要在 点击按钮之前btn 变量已经被创建并赋值,代码就能正常运行。
  • 按钮创建后,command=on_submit 将函数对象传给了按钮。当 2 秒后用户(或模拟完成)触发点击时,btn 早已存在于内存中,所以不会报错。

ttk.Button 状态语法说明

方法 含义
btn.state(["disabled"]) 添加 disabled 状态(按钮变灰不可点)
btn.state(["!disabled"]) 移除 disabled 状态(恢复可点击)
其他状态 ["pressed"](按下)、["focus"](聚焦)等

运行效果总结

  1. 窗口出现一个“提交”按钮。
  2. 点击后,按钮立即变灰,文字变为“处理中…”。
  3. 2 秒后,按钮自动恢复为可点击状态,文字变回“提交”。
  4. 期间如果再次点击,由于按钮已禁用,不会触发任何操作,完美防止重复提交。

潜在改进建议

  • 异常处理:如果模拟的真实操作可能报错,可以在 try...finally 中确保按钮恢复启用,防止因错误导致按钮永远“卡死”。
  • 进度条:如果耗时较长,可以将 root.after 换成真实的线程 + 进度条更新,替代单纯的文字提示。