Python tkinter计算器开发:从零实现GUI应用与状态机设计
2026/7/31 3:35:48 网站建设 项目流程

1. 项目概述:为什么用Python和tkinter做计算器?

如果你刚开始学Python,或者已经学了一段时间语法但总觉得没做出什么“像样”的东西,那么用tkinter做一个图形界面的计算器,绝对是一个能让你信心大增的里程碑项目。这听起来可能有点老套,但别小看它。一个完整的计算器程序,几乎涵盖了入门级GUI开发的所有核心概念:窗口创建、布局管理、事件绑定、状态维护和逻辑处理。它不像“Hello World”那样简单,也不至于复杂到让人望而却步,是一个绝佳的“练手”项目。

我之所以推荐tkinter,是因为它是Python的标准GUI库,无需额外安装任何第三方包,开箱即用。对于新手来说,最大的障碍往往不是代码逻辑,而是环境配置。用tkinter,你只需要一个能运行Python的环境,就能立刻开始。这个项目能让你直观地看到代码如何变成屏幕上可点击的按钮和跳动的数字,这种即时反馈的成就感,是命令行程序难以比拟的。

这个计算器程序的目标是:实现一个具备基本四则运算(加、减、乘、除)、支持连续运算、包含清除和退格功能、并且界面清晰友好的桌面应用。通过完成它,你将掌握如何用代码“画”出界面,并让界面“活”起来响应用户操作。下面,我们就从零开始,一步步拆解实现过程,我会把其中容易踩的坑和提升体验的小技巧都分享出来。

2. 核心思路与界面设计拆解

在动手写代码之前,理清思路至关重要。一个计算器,本质上是一个状态机。它需要记住当前输入的数字、待执行的操作符、以及之前的结果。我们的设计将围绕这个核心状态来展开。

2.1 计算器的状态模型

我们可以用几个关键变量来模拟计算器的“记忆”:

  • current_input: 当前显示在屏幕上的字符串,代表用户正在输入或已计算的结果。
  • previous_value: 存储上一次计算的结果或第一个操作数。
  • pending_operation: 存储待执行的运算符(如+,-,*,/)。当用户按下运算符按钮时,我们需要保存它,并等待下一个数字输入。
  • should_reset_input: 一个布尔标志。当一次计算完成,或刚按下运算符后,下一次数字输入应该清空当前显示,而不是追加。这个标志是处理连续运算逻辑的关键。

这个状态模型决定了我们后续所有按钮点击事件的处理逻辑。理解了这个,代码写起来就不会混乱。

2.2 界面布局规划

一个典型的计算器界面分为两大区域:显示区域按钮区域

  • 显示区域: 通常是一个只读的文本框(Entry)或标签(Label),用于实时显示输入和结果。我们选择Entry组件,并将其状态设置为readonly,这样可以防止用户键盘误输入,同时保留文本高亮等原生特性。
  • 按钮区域: 由数字按钮(0-9)、运算符按钮(+、-、*、/)、功能按钮(=、C、CE、←)和小数点(.)组成。

布局上,我们采用grid网格布局管理器。它比pack更灵活,能精确控制每个部件的位置,非常适合这种行列整齐的按钮矩阵。我们将设计一个4x5的网格来排列所有按钮。

注意: 在规划按钮布局时,要符合用户习惯。数字通常按照电话键盘布局(7、8、9在上排),运算符在右侧,“=”键通常独占一行且尺寸较大。清晰符合直觉的布局能极大提升用户体验。

3. 开发环境准备与tkinter基础

工欲善其事,必先利其器。虽然tkinter是内置的,但一个顺手的编码环境依然很重要。

3.1 Python环境确认

首先,确保你的Python环境已就绪。打开终端(Windows上是CMD或PowerShell,macOS/Linux上是Terminal),输入以下命令:

python --version

或者

python3 --version

你应该能看到类似Python 3.8.10的输出。只要是Python 3.x版本(建议3.6以上),都完全支持tkinter。如果提示“不是内部或外部命令”,则需要先去Python官网下载并安装。

3.2 选择代码编辑器

任何文本编辑器都可以写Python,但我强烈推荐使用VSCodePyCharm这类集成开发环境(IDE)。

  • VSCode: 轻量、免费、插件生态丰富。安装Python扩展后,能提供代码补全、语法高亮、调试等功能,对新手非常友好。
  • PyCharm Community Edition: JetBrains出品,专为Python开发设计,功能更为强大和智能,同样是免费的。

使用IDE的好处是,你可以直接运行代码,并能通过调试器一步步跟踪变量的变化,这对于理解我们前面提到的“状态机”逻辑非常有帮助。

3.3 tkinter的“Hello World”

在开始计算器之前,我们先花两分钟感受一下tkinter。创建一个新文件,比如叫calculator.py,输入以下代码:

import tkinter as tk # 创建主窗口 root = tk.Tk() root.title("我的第一个tkinter窗口") # 创建一个标签部件并放置 label = tk.Label(root, text="你好,tkinter!") label.pack() # 启动主事件循环 root.mainloop()

保存并运行这个文件(在终端中进入文件所在目录,执行python calculator.py)。你会看到一个带有标题和文字的小窗口弹出。tk.Tk()创建了根窗口,root.mainloop()启动了GUI的事件循环,让窗口能够持续响应你的操作(如移动、关闭)。

这个简单的例子包含了tkinter程序的基本骨架。接下来,我们将用更复杂的部件和布局来替换它。

4. 计算器核心功能模块实现

现在,我们进入核心编码阶段。我将把计算器拆解成几个模块,逐一实现。

4.1 创建主窗口与显示框

首先,我们创建主窗口,并设置一个合适的大小和标题。然后,创建最重要的显示框。

import tkinter as tk def create_calculator(): # 创建主窗口 root = tk.Tk() root.title("Python 计算器") # 设置窗口初始大小(宽x高),并禁止缩放以固定布局 root.geometry("320x420") root.resizable(False, False) # 创建显示框 display_var = tk.StringVar() # 用于关联显示文本的特殊变量 display_entry = tk.Entry( root, textvariable=display_var, font=('Arial', 24), bd=10, # 边框宽度 insertwidth=4, # 插入光标宽度(虽然只读,但设置一下无妨) justify='right', # 文本右对齐,符合计算器习惯 state='readonly', # 设置为只读,防止键盘输入 readonlybackground='white' # 只读状态下的背景色 ) # 将显示框放在窗口顶部,填充横向空间,并设置上下内边距 display_entry.grid(row=0, column=0, columnspan=4, sticky='nsew', padx=10, pady=10) # ... 后续按钮代码将在这里添加 ... root.mainloop() if __name__ == "__main__": create_calculator()

运行这段代码,你会看到一个顶部有白色长条显示框的窗口。StringVar()是一个Tkinter特有的变量类,它能将界面上的显示内容与后台Python变量动态绑定。当display_var的值改变时,显示框的内容会自动更新,反之亦然。这是我们实现交互的基础。

实操心得: 将Entrystate设置为'readonly'而非'disabled'是关键区别。'disabled'状态下的输入框会变灰,且文本无法被选中复制。而'readonly'保持了正常的视觉外观,并允许用户选中显示的结果进行复制,这是一个更友好的设计。

4.2 定义按钮布局与事件处理框架

接下来,我们定义按钮的标签和它们在网格中的位置。然后,创建一个函数来统一处理所有按钮的点击事件。

# 在 create_calculator 函数内,创建显示框之后 # 初始化计算器状态 current_input = "0" previous_value = None pending_operation = None should_reset_input = False # 更新显示框的函数 def update_display(): display_var.set(current_input) # 按钮点击事件处理函数(框架) def button_click(value): nonlocal current_input, previous_value, pending_operation, should_reset_input # 后续所有逻辑都将在这里实现 print(f"按钮被点击: {value}") # 暂时用打印来测试 # 按钮定义: (显示文本, 行, 列, 列跨度) buttons = [ ('C', 1, 0), ('CE', 1, 1), ('←', 1, 2), ('/', 1, 3), ('7', 2, 0), ('8', 2, 1), ('9', 2, 2), ('*', 2, 3), ('4', 3, 0), ('5', 3, 1), ('6', 3, 2), ('-', 3, 3), ('1', 4, 0), ('2', 4, 1), ('3', 4, 2), ('+', 4, 3), ('0', 5, 0, 2), # ‘0’键横跨两列 ('.', 5, 2), ('=', 5, 3) ] # 创建并放置按钮 for btn_info in buttons: text = btn_info[0] row = btn_info[1] col = btn_info[2] # 处理可能存在的列跨度参数 col_span = btn_info[3] if len(btn_info) > 3 else 1 # 创建按钮,绑定点击事件,并指定一个好看的字体 btn = tk.Button( root, text=text, font=('Arial', 18), padx=20, pady=20, command=lambda val=text: button_click(val) # 使用lambda传递参数 ) # 将按钮放置在网格中 btn.grid(row=row, column=col, columnspan=col_span, sticky='nsew', padx=2, pady=2) # 配置网格权重,使按钮能随窗口(虽然我们禁止了缩放)均匀拉伸填充 for i in range(6): # 0-5行 root.grid_rowconfigure(i, weight=1) for i in range(4): # 0-3列 root.grid_columnconfigure(i, weight=1) # 初始化显示 update_display()

现在运行代码,一个完整的计算器界面就出现了,虽然点击按钮还只是在控制台打印信息。这里有几个关键点:

  1. 使用nonlocal: 因为我们在嵌套函数button_click内需要修改外部函数create_calculator中的状态变量,所以必须使用nonlocal声明。这是Python闭包中的常见用法。
  2. Lambda表达式传参command=lambda val=text: button_click(val)这行代码是精髓。它创建了一个匿名函数,这个函数在被调用时,会将当前按钮的文本text作为参数val传递给button_click函数。如果不这样写,所有按钮的command都会指向最后一个text值。
  3. 网格权重配置grid_rowconfiguregrid_columnconfigure设置了行和列的“权重”。weight=1意味着当窗口有额外空间时,这些行和列会按比例分配空间,使得按钮能填满整个区域,看起来更美观。

4.3 实现数字与小数点输入逻辑

现在,我们来填充button_click函数的核心逻辑。首先处理数字(0-9)和小数点(.)的输入。

def button_click(value): nonlocal current_input, previous_value, pending_operation, should_reset_input if value.isdigit(): # 如果点击的是数字 if current_input == "0" or should_reset_input: current_input = value should_reset_input = False else: # 防止输入过长,可以加一个长度限制,例如15位 if len(current_input) < 15: current_input += value else: # 可以在这里添加一个提示,比如让显示框闪烁一下 pass update_display() elif value == '.': # 如果点击的是小数点 if should_reset_input: current_input = '0.' should_reset_input = False elif '.' not in current_input: # 确保当前数字中没有小数点 current_input += '.' update_display()

数字输入的逻辑需要考虑状态标志should_reset_input。当它为True时(例如刚完成一次计算或按下了运算符),新输入的数字应该替换当前显示,而不是追加。小数点输入则额外需要检查当前数字中是否已经包含了一个小数点,避免出现“123.45.6”这样的非法数字。

4.4 实现运算符与等号逻辑

这是计算器的大脑,负责处理加减乘除和触发计算。

def button_click(value): nonlocal current_input, previous_value, pending_operation, should_reset_input # ... 之前的数字和小数点处理逻辑 ... elif value in ('+', '-', '*', '/'): # 如果点击的是四则运算符 try: # 如果已经有待处理的操作,先执行它(实现连续运算) if pending_operation is not None and not should_reset_input: compute_result() # 将当前显示的值保存为“上一个值” previous_value = float(current_input) # 记录新的待处理操作 pending_operation = value # 设置标志,下一个数字输入将清空显示 should_reset_input = True except ValueError: # 如果当前输入不是有效数字(例如为空),则清除状态 clear_all() elif value == '=': # 如果点击的是等号 if pending_operation is not None and previous_value is not None: compute_result() # 计算完成后,清空待处理操作,为下一次独立计算做准备 pending_operation = None should_reset_input = True # 新增的计算函数 def compute_result(): nonlocal current_input, previous_value, should_reset_input try: current = float(current_input) if pending_operation == '+': result = previous_value + current elif pending_operation == '-': result = previous_value - current elif pending_operation == '*': result = previous_value * current elif pending_operation == '/': if current == 0: raise ZeroDivisionError result = previous_value / current else: return # 处理结果显示:如果是整数,则显示为整数形式;否则保留一定小数 if result.is_integer(): current_input = str(int(result)) else: # 限制小数位数,避免过长 current_input = f"{result:.10f}".rstrip('0').rstrip('.') previous_value = result # 更新previous_value为本次结果,支持连续按“=” update_display() except (ValueError, ZeroDivisionError): # 处理错误,例如除零错误 current_input = "错误" update_display() should_reset_input = True

运算符逻辑的核心是“延迟计算”。当用户按下“+”时,我们并不立即计算,而是保存第一个数字(previous_value)和操作符(pending_operation),然后等待用户输入第二个数字。当用户再次按下运算符或等号时,才触发真正的计算(compute_result)。

compute_result函数是执行实际算术运算的地方。这里有几个细节处理:

  1. 类型转换: 显示框里的current_input是字符串,计算前需转换为float
  2. 除零保护: 对除法运算检查除数是否为零,并抛出异常。
  3. 结果显示优化: 使用is_integer()判断结果是否为整数,是则用整数形式显示,避免显示“2.0”。对于小数,使用格式化字符串限制最大位数,并用rstrip('0').rstrip('.')去掉末尾无意义的零和小数点,使“3.140000”显示为“3.14”
  4. 错误处理: 使用try...except捕获可能的错误(如无效输入、除零),并在显示框显示“错误”,同时重置状态。

4.5 实现清除与退格功能

最后,我们实现“C”(清除所有)、“CE”(清除当前输入)和“←”(退格)功能。

def button_click(value): nonlocal current_input, previous_value, pending_operation, should_reset_input # ... 之前的数字、小数点、运算符、等号处理逻辑 ... elif value == 'C': # 全部清除 clear_all() elif value == 'CE': # 清除当前输入 current_input = "0" update_display() elif value == '←': # 退格 if not should_reset_input and current_input != "0": if len(current_input) > 1: current_input = current_input[:-1] else: current_input = "0" update_display() # 新增的清除所有函数 def clear_all(): nonlocal current_input, previous_value, pending_operation, should_reset_input current_input = "0" previous_value = None pending_operation = None should_reset_input = False update_display()
  • C (Clear All): 重置所有状态变量,计算器恢复到初始状态。
  • CE (Clear Entry): 仅清除当前显示的数字current_input,重置为“0”,但不影响已存储的previous_valuepending_operation。这在输入错误时非常有用。
  • ← (Backspace): 删除当前输入数字的最后一个字符。如果删除后字符串为空或只剩一个字符,则显示“0”。注意,当should_reset_inputTrue时(刚算完),退格键应被禁用,因为此时显示的是结果,退格没有意义。

至此,一个功能完整的计算器核心逻辑就全部实现了。将上述所有代码段按顺序组合到create_calculator函数中,运行程序,你就可以进行基本的四则运算了。

5. 界面美化与交互增强

基础功能完成后,我们可以花些心思让计算器看起来更专业,用起来更舒服。

5.1 美化按钮与显示框

我们可以通过修改ButtonEntry的样式参数来美化界面。

# 修改显示框的创建,增加更多样式 display_entry = tk.Entry( root, textvariable=display_var, font=('Consolas', 28, 'bold'), # 改用等宽字体,更清晰 bd=8, insertwidth=0, # 隐藏插入光标 justify='right', state='readonly', readonlybackground='#f0f0f0', # 浅灰色背景 relief='flat' # 扁平边框 ) # 修改按钮创建的循环,根据按钮类型设置不同颜色 for btn_info in buttons: text = btn_info[0] row = btn_info[1] col = btn_info[2] col_span = btn_info[3] if len(btn_info) > 3 else 1 # 根据按钮功能定义颜色 if text in ('C', 'CE', '←'): bg_color = '#ff6b6b' # 红色系,用于清除功能 fg_color = 'white' elif text in ('/', '*', '-', '+', '='): bg_color = '#4ecdc4' # 青色系,用于运算符 fg_color = 'white' else: bg_color = '#ffffff' # 白色,用于数字和小数点 fg_color = 'black' btn = tk.Button( root, text=text, font=('Arial', 18, 'bold'), padx=20, pady=20, bg=bg_color, # 背景色 fg=fg_color, # 前景色(文字颜色) activebackground='#dddddd', # 按钮按下时的背景色 activeforeground=fg_color, relief='raised', # 3D凸起效果 bd=3, # 边框宽度 command=lambda val=text: button_click(val) ) btn.grid(row=row, column=col, columnspan=col_span, sticky='nsew', padx=2, pady=2)

通过设置bg(背景色)、fg(前景色)、activebackground(激活背景色)和relief(边框样式),按钮的视觉层次和反馈感立刻增强了。将功能键(清除)、运算符和数字键用颜色区分,符合用户认知。

5.2 添加键盘支持

让用户可以用键盘输入数字和运算符,能极大提升操作效率。这需要用到tkinter的事件绑定。

# 在 create_calculator 函数内,创建所有部件并启动主循环之前,添加键盘绑定 def on_key_press(event): key = event.char keysym = event.keysym # 映射键盘按键到计算器功能 if key.isdigit(): button_click(key) elif key in ('+', '-', '*', '/'): button_click(key) elif key == '.' or key == ',': button_click('.') elif key == '\r' or keysym == 'Return': # 回车键 button_click('=') elif keysym == 'Escape': # ESC键 clear_all() elif keysym == 'BackSpace': # 退格键 button_click('←') # 将键盘事件绑定到主窗口 root.bind('<Key>', on_key_press) # 设置焦点,确保键盘事件能被捕获 root.focus_set()

on_key_press函数捕获键盘事件。event.char获取字符,event.keysym获取按键符号。我们根据按下的键,调用相应的button_click函数。注意,我们将小数点(.)和逗号(,)都映射到小数点功能,因为有些键盘布局下逗号更常用。绑定完成后,记得用root.focus_set()让窗口获得焦点,否则键盘事件可能无法被捕获。

5.3 添加动画与状态反馈

简单的动画能提升用户体验。例如,当按钮被点击时,可以有一个短暂的视觉反馈。

# 修改按钮创建命令,加入一个简单的“按下”反馈 def create_button_cmd(val): """创建一个带有反馈效果的按钮命令""" def cmd(): # 获取被点击的按钮对象(需要一些技巧,这里用简化方法) # 更健壮的做法是为每个按钮单独设置command,这里为演示简化 button_click(val) # 在实际项目中,可以在这里添加改变按钮颜色再恢复的动画 return cmd # 在创建按钮时,使用新的命令工厂函数 btn = tk.Button( ... # 其他参数不变 command=create_button_cmd(text) # 替换原来的lambda )

更高级的反馈可以模拟物理按键的“按下”和“弹起”效果,通过临时改变按钮的relief属性为'sunken',然后使用root.after延时恢复。由于代码稍复杂,这里仅提供思路。一个更简单的反馈是改变显示框的底色。例如,在button_click函数开始,临时将显示框背景色改为浅黄色,然后延时恢复。

def flash_display(): original_color = display_entry.cget('readonlybackground') display_entry.config(readonlybackground='#fffacd') # 浅黄色 root.after(100, lambda: display_entry.config(readonlybackground=original_color)) # 100ms后恢复 # 在 button_click 函数中,处理完逻辑后调用 flash_display()

6. 项目扩展与进阶思考

一个基础计算器完成后,你可以尝试以下扩展方向,这能让你对GUI编程和软件设计有更深的理解。

6.1 实现高级运算功能

尝试添加平方根()、百分号(%)、倒数(1/x)、正负号切换(±)等高级功能。这些都是一元运算,逻辑比二元运算更简单。例如,按钮的处理逻辑是:current_input = str(math.sqrt(float(current_input))),记得导入math模块。

6.2 添加计算历史记录

在界面侧边或底部增加一个文本框(Text部件)或列表框(Listbox),用于记录每一次完整的计算表达式和结果(例如:“5 + 3 = 8”)。这需要你修改计算逻辑,在按下=或连续运算时,将算式和结果格式化后存入一个列表,并更新显示历史记录的部件。

6.3 使用面向对象重构代码

目前我们的代码都写在一个大函数里,状态变量用nonlocal管理。当功能变多时,这会变得难以维护。更好的做法是使用**类(Class)**来封装计算器的状态和行为。

class Calculator: def __init__(self, root): self.root = root self.root.title("面向对象计算器") self.current_input = tk.StringVar(value="0") self.previous_value = None self.pending_operation = None self.should_reset_input = False self._create_widgets() self._layout_widgets() self._bind_events() def _create_widgets(self): self.display = tk.Entry(...) # 使用 self.current_input 作为 textvariable # ... 创建所有按钮,将 command 绑定到类的方法,如 self.on_button_click def on_button_click(self, value): # 将之前 button_click 的逻辑移到这里,访问 self.xxx 变量 pass # ... 其他方法如 compute_result, clear_all 等

使用面向对象的方式,状态(变量)和行为(方法)被清晰地组织在Calculator类中,代码结构更清晰,也更容易进行单元测试和功能扩展。

6.4 打包为可执行文件

如果你想把这个程序分享给没有安装Python的朋友,可以使用PyInstaller将其打包成独立的.exe(Windows)或.app(macOS)文件。

  1. 安装 PyInstaller:pip install pyinstaller
  2. 在终端中,进入你的calculator.py所在目录。
  3. 执行打包命令:pyinstaller --onefile --windowed calculator.py
    • --onefile: 打包成单个可执行文件。
    • --windowed: 对于GUI程序,不显示命令行窗口。
  4. 打包完成后,在生成的dist文件夹里就能找到可执行文件。

避坑指南: 打包时可能会遇到找不到tkinter依赖的问题。一个常见的解决方案是,如果你的主程序文件不是calculator.py,而是通过if __name__ == "__main__":调用的函数,PyInstaller可能无法正确分析依赖。可以尝试在命令中显式指定--hidden-import tkinter。另外,打包后的文件体积较大,因为它包含了Python解释器和所有依赖库。

7. 调试技巧与常见问题排查

在开发过程中,你肯定会遇到各种问题。这里分享一些实用的调试方法和常见问题的解决方案。

7.1 使用打印语句进行基础调试

在关键函数(如button_click)的开始和状态改变的地方,打印出所有状态变量的值,这是最简单有效的调试方法。

def button_click(value): nonlocal current_input, previous_value, pending_operation, should_reset_input print(f"[点击前] 值: {value}, 当前: {current_input}, 之前: {previous_value}, 操作: {pending_operation}, 重置标志: {should_reset_input}") # ... 处理逻辑 ... print(f"[点击后] 当前: {current_input}, 之前: {previous_value}, 操作: {pending_operation}, 重置标志: {should_reset_input}")

通过观察控制台输出,你可以清晰地看到每次点击后计算器内部状态的变化,从而定位逻辑错误。

7.2 常见问题与解决

  1. 按钮点击后界面无反应,但程序没报错

    • 可能原因: 事件绑定错误,或者mainloop()没有被调用。
    • 检查: 确保所有按钮的command参数都正确绑定到了函数。确保代码最后有root.mainloop()
  2. 连续运算结果错误(例如,输入2 + 3 =得5,再按+ 4 =期望得9,却得到7或其他)

    • 可能原因should_reset_input标志逻辑有误,或者在按下运算符后没有正确保存previous_value
    • 调试: 使用打印语句,仔细跟踪按下运算符和等号时,previous_valuecurrent_inputshould_reset_input的变化是否符合预期。
  3. 界面布局混乱,按钮大小不一

    • 可能原因: 网格(grid)的行列权重(weight)没有配置,或者部件使用了packgrid混合布局(严禁混合使用)。
    • 解决: 确保只使用一种布局管理器(这里全程用grid)。检查是否对所有行和列都正确配置了root.grid_rowconfigure(i, weight=1)root.grid_columnconfigure(i, weight=1)
  4. 打包成exe后运行闪退

    • 可能原因: 控制台错误信息被隐藏。或者缺少某些隐藏的依赖。
    • 解决: 尝试去掉--windowed参数打包,运行生成的exe时会弹出一个控制台窗口,里面会显示错误信息。根据错误信息排查。对于tkinter,确保在代码中显式导入(import tkinter)。
  5. 键盘输入无效

    • 可能原因: 窗口没有获得焦点,或者事件绑定键值不对。
    • 解决: 确认代码中有root.focus_set()。检查on_key_press函数中的键值映射,特别是回车(\r'Return')和退格('BackSpace')的keysym。可以打印event.keysymevent.char来确认按下的键到底传递了什么值。

这个项目虽然不大,但它串联起了Python基础语法、GUI编程思想、事件驱动模型和基本的软件状态管理。完成它之后,你完全可以自信地说自己已经入门了Python的实用开发。更重要的是,你获得了一个可以无限扩展和打磨的原型,无论是添加科学计算功能,还是换用更现代的GUI库如PyQt、Kivy,这个计算器都是你编程路上一个坚实的起点。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询