first commit

This commit is contained in:
鲁学坤 2025-04-19 23:26:19 +08:00
commit b25f9f97b5
11 changed files with 431 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
.venv/
__pycache__/
.pytest_cache/
.idea/

3
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

10
.idea/calculator.iml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.12 (calculator)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,12 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="DrissionPage.*" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

6
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.12 (calculator)" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/calculator.iml" filepath="$PROJECT_DIR$/.idea/calculator.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

88
README.md Normal file
View File

@ -0,0 +1,88 @@
# 简易计算器GUI程序
![Calculator Screenshot](screenshot.png) <!-- 需添加实际截图 -->
[![Python Version](https://img.shields.io/badge/python-3.7%2B-blue)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
## 功能特性
- **四则运算**:支持加(+)、减(-)、乘(×)、除(÷)基本运算
- **连续计算**:自动保留计算结果用于后续运算
- **智能显示**
- 自动去除小数点后多余的零
- 大数字自动适应显示区域
- **错误处理**
- 除零错误检测与提示
- 无效操作拦截
- 异常崩溃防护
- **交互设计**
- 退格键(←)支持
- 一键清零(C)功能
- 实时输入反馈
- **界面特性**
- 半透明窗口效果
- 响应式布局
- 中文宋体显示
## 快速开始
### 环境要求
- Python 3.7+
- Tkinter通常随Python默认安装
### 安装与运行
```bash
1. 克隆仓库
git clone https://github.com/yourusername/calculator-gui.git
2. 进入项目目录
cd calculator-gui
3. 运行程序
python calculator.py
```
## 技术细节
### 技术栈
- **核心框架**: Python标准库 Tkinter
- **状态管理**: 全局变量跟踪模式
- **错误处理**: Try/Except异常捕获机制
- **界面布局**: Grid网格布局系统
### 项目结构
```python
calculator.py
├── 全局状态变量 # current_input, first_operand, operator
├── 样式配置常量 # COLORS, FONT, LAYOUT
├── 事件处理函数 # on_number_click, on_operator_click, calculate等
├── UI构建模块 # 结果显示区、操作按钮矩阵、等号按钮
└── 主程序循环 # root.mainloop()
```
## 版本历史
| 版本号 | 作者 | 发布日期 | 主要变更 |
|--------|----|------------|----------------------|
| v1.0.0 | 鲁豫 | 2025-04-15 | 完善代码注释和结构 |
## 贡献指南
欢迎通过以下方式参与项目改进:
1. 提交Issue报告问题
2. Fork仓库并提交Pull Request
3. 优化代码注释或文档
**开发团队**
- 程序员:鲁豫 \<2085520973@qq.com>
- 代码审核Xuekun Lu \<luxuekun@forling.cn>
## 学习资源
- [Tkinter官方文档](https://docs.python.org/3/library/tkinter.html)
- [Python异常处理指南](https://docs.python.org/3/tutorial/errors.html)
- [GUI设计最佳实践](https://learn.microsoft.com/zh-cn/windows/win32/uxguide/guidelines)
## 许可证
本项目基于 [MIT License](LICENSE) 开源

288
calculator.py Normal file
View File

@ -0,0 +1,288 @@
"""
简易计算器GUI程序
[版本信息]
版本号 | 日期 | 作者 | 修改摘要
----------|------------|------------|------------------
v1.0.0 | 2025-04-19 | 鲁豫 | 初始版本实现基本加减法功能
[作者信息]
开发团队Python学习
程序员鲁豫<2085520973@qq.com>
代码审核Xuekun Lu
GitHub仓库https://github.com/learn-python/calculator-gui
版权声明本代码遵循MIT开源协议
[功能说明]
实现带图形界面的四则运算计算器支持以下特性
1. 基础运算加减乘除
2. 连续运算功能
3. 错误处理机制
4. 历史记录显示开发中
代码结构说明
1.全局状态使用三个变量跟踪计算器状态
2.样式配置集中管理颜色字体等视觉元素
3.事件处理5个函数处理不同按钮的点击逻辑
4.界面构建分模块创建各个界面组件
5.布局管理使用grid布局实现计算器按键矩阵
学习重点
1.StringVar的使用实现显示内容的动态更新
2.lambda表达式用于传递参数的按钮命令绑定
3.全局状态管理如何处理连续运算的中间状态
4.异常处理保证程序在错误输入时不会崩溃
5.布局技巧grid布局的跨列(rowspan)和跨行(columnspan)使用
测试建议
1.测试乘法5 × 3 = 15
2.测试除法9 ÷ 3 = 3
3.测试除零5 ÷ 0 显示"除零错误"
4.连续运算测试2 + 3 = 5 × 4 = 20
"""
# 导入Tkinter图形界面库Python标准库
import tkinter as tk
# ==================== 全局状态变量 ====================
# 这些变量用于跟踪计算器的当前状态
current_input = "" # 存储用户当前输入的数字(字符串形式,如"12.34"
first_operand = None # 存储第一个运算数字(当用户点击运算符时保存)
operator = None # 存储当前选择的运算符(+/-等)
# ==================== 界面样式常量配置 ====================
# 使用字典统一管理样式,方便后期修改和维护
COLORS = {
'operator': '#b1b2b2', # 运算符按钮背景色(浅灰色)
'number': '#eacda1', # 数字按钮背景色(米黄色)
'equal': '#eacda1' # 等号按钮背景色(与数字键相同)
}
FONT = {
'main': ('宋体', 20), # 显示屏字体(字体,字号)
'button': ('宋体', 16) # 按钮字体
}
LAYOUT = {
'pad': 4, # 按钮之间的水平间距(单位:像素)
'margin': 2 # 按钮之间的垂直间距
}
# ==================== 事件处理函数 ====================
# 以下函数用于响应按钮点击事件
def on_number_click(char):
"""处理数字和小数点按钮点击事件
参数char - 按钮对应的字符0-9 .
"""
global current_input # 声明使用全局变量
# 处理小数点输入限制
if char == '.' and '.' in current_input:
return # 如果已包含小数点,不做任何操作
current_input += char # 将新字符追加到当前输入
result_var.set(current_input) # 更新显示屏内容
def on_operator_click(op):
"""处理运算符按钮点击事件(+/-/*//
参数op - 运算符符号字符串
"""
global first_operand, operator, current_input
if current_input: # 确保有输入值时才执行
first_operand = float(current_input) # 将当前输入转为浮点数存储
operator = op # 记录运算符
current_input = "" # 清空当前输入,准备接收第二个数字
result_var.set(op) # 在显示屏显示当前运算符
def calculate():
"""执行计算并显示结果"""
global current_input, first_operand, operator
# 有效性检查:确保三个要素都存在
if first_operand is None or operator is None or not current_input:
return
try:
second_operand = float(current_input) # 将当前输入转为浮点数
# 根据运算符执行计算(新增乘除运算)
if operator == '+':
result = first_operand + second_operand
elif operator == '-':
result = first_operand - second_operand
elif operator == '*':
result = first_operand * second_operand
elif operator == '/':
if second_operand == 0:
raise ZeroDivisionError
result = first_operand / second_operand
else:
return # 无效运算符
# 格式化显示结果整数去零小数保留10位
if result.is_integer():
current_input = str(int(result)) # 5.0 → 5
else:
# 去除末尾多余的零和小数点
formatted = "{:.10f}".format(result).rstrip('0').rstrip('.')
current_input = formatted if formatted else "0"
result_var.set(current_input) # 更新显示
# 保留计算结果作为下一次运算的第一个操作数
first_operand = float(current_input)
operator = None # 重置运算符需手动选择
except ZeroDivisionError:
result_var.set("除零错误")
# reset_calculator()
except Exception as e:
result_var.set("错误"+e.__cause__) # 显示错误提示
# reset_calculator() # 重置计算器
def reset_calculator():
"""重置所有状态到初始值"""
global current_input, first_operand, operator
current_input = ""
first_operand = None
operator = None
result_var.set('0') # 显示屏归零
def backspace():
"""删除最后一个输入的字符"""
global current_input
if current_input:
current_input = current_input[:-1] # 移除最后一个字符
result_var.set(current_input if current_input else '0') # 显示剩余内容或0
# ==================== 主窗口初始化 ====================
# 创建主窗口并设置基本属性
root = tk.Tk() # 创建Tkinter主窗口对象
root.title('简易计算器') # 窗口标题
root.geometry('295x280+100+100') # 窗口尺寸宽x高和初始位置x+y
root.attributes("-alpha", 0.9) # 设置窗口透明度0.0完全透明-1.0不透明)
# ==================== 结果显示区域 ====================
# 使用StringVar实现动态更新显示内容
result_var = tk.StringVar(value='0') # 创建绑定到显示区域的变量
# 创建显示标签(显示屏)
display = tk.Label(
root,
textvariable=result_var, # 绑定动态变量
font=FONT['main'], # 使用主字体
height=2, # 高度(行数)
width=20, # 宽度(字符数)
justify=tk.LEFT, # 文本左对齐
anchor=tk.SE # 文本定位到右下角(东南角)
)
# 使用grid布局管理器定位跨4列显示
display.grid(row=1, column=1, columnspan=4)
# ==================== 操作符按钮行 ====================
# 定义第一行操作符按钮的配置(清除、退格、除、乘)
operator_buttons = [
# 格式:(显示文本, 行号, 列号, 点击命令)
('c', 2, 1, reset_calculator), # 清除按钮
('', 2, 2, backspace), # 退格按钮
('/', 2, 3, lambda: on_operator_click('/')), # 除法按钮
('×', 2, 4, lambda: on_operator_click('*')) # 乘法按钮
]
# 批量创建操作符按钮
for text, row, col, command in operator_buttons:
tk.Button(
root,
text=text,
width=5, # 按钮宽度(字符数)
font=FONT['button'], # 使用按钮字体
relief=tk.FLAT, # 扁平化按钮样式
bg=COLORS['operator'], # 设置背景色
command=command # 绑定点击事件处理函数
).grid(
row=row,
column=col,
padx=LAYOUT['pad'],
pady=LAYOUT['margin']
)
# ==================== 数字按钮布局 ====================
# 定义数字按钮的布局配置(使用嵌套元组)
button_configs = [
# 每行按钮配置(格式:(按钮1配置, 按钮2配置, ...)
# 第三行7、8、9、减号
(('7', 3, 1), ('8', 3, 2), ('9', 3, 3), ('-', 3, 4, lambda: on_operator_click('-'))),
# 第四行4、5、6、加号
(('4', 4, 1), ('5', 4, 2), ('6', 4, 3), ('+', 4, 4, lambda: on_operator_click('+'))),
# 第五行1、2、3
(('1', 5, 1), ('2', 5, 2), ('3', 5, 3)),
# 第六行0、小数点
(('0', 6, 1), ('.', 6, 3))
]
# 遍历配置创建数字按钮
for row_group in button_configs:
for config in row_group:
# 解析按钮配置
parts = list(config)
text, row, col = parts[0:3] # 前三个元素固定
# 确定点击命令:数字/小数点调用on_number_click运算符调用on_operator_click
command = parts[3] if len(parts) > 3 else (lambda t=text: on_number_click(t))
# 创建按钮对象
btn = tk.Button(
root,
text=text,
width=5 if text != '0' else 12, # 0按钮特殊宽度
font=FONT['button'],
relief=tk.FLAT,
bg=COLORS['number'] if text in '1234567890.' else COLORS['operator'],
command=command # 绑定点击事件
)
# 布局按钮0按钮需要跨列
if text == '0':
btn.grid(
row=row,
column=col,
columnspan=2, # 跨2列
padx=LAYOUT['pad'],
pady=LAYOUT['margin']
)
else:
btn.grid(
row=row,
column=col,
padx=LAYOUT['pad'],
pady=LAYOUT['margin']
)
# ==================== 等号按钮 ====================
# 创建特殊尺寸的等号按钮
tk.Button(
root,
text='=',
width=5, # 宽度(字符数)
height=3, # 高度(行数)
font=FONT['button'],
relief=tk.FLAT,
bg=COLORS['equal'], # 使用等号专用颜色
command=calculate # 绑定计算函数
).grid(
row=5,
column=4,
rowspan=2, # 跨5-6两行
padx=LAYOUT['pad'],
pady=LAYOUT['margin']
)
# ==================== 启动程序 ====================
root.mainloop() # 进入Tkinter事件循环等待用户操作

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB