PyQt5打造高级多功能计算器

简介: 本文分享作者用PyQt5从零打造一款高效、安全、可定制的多功能计算器的过程:支持四则运算、科学函数、单位换算、键盘操作与美观界面,兼顾实用性与学习价值,强调“好工具是造出来的”这一理念。(239字)


你有没有遇到过这种场景——正在专心写代码或者处理报表,突然需要算点东西。打开系统自带的计算器,发现它只是个“小学生水平”的工具,开个根号都要切到科学模式,更别提算三角函数或者做单位换算了。你叹了口气,要么打开网页搜一个在线计算器,忍受一堆广告的轰炸,要么干脆手算。
代理 IP 使用小技巧 让你的数据抓取效率翻倍 (39).png

我当时的想法很简单:为什么不自己写一个?

反正天天跟Python打交道,PyQt5这框架也听说过不少次。与其让别人的工具打断工作流,不如亲手打造一个趁手的“兵器”。这篇文章就是我折腾出来的成果——一个能当主力工具用的多功能计算器,顺便聊聊踩过的那些坑。

从界面开始,像搭积木一样摆按钮
写GUI程序的第一步永远是搭界面。PyQt5有个好处,可视化工具Qt Designer可以直接拖拖拽拽把框架搭好,不过我习惯手写代码——这样以后改样式、加功能心里更有数。

界面布局其实挺像摆积木。最上面放一个QLCDNumber作为显示屏,要那种老式计算器的数字风格,看着舒服。下面用QGridLayout把按钮排成网格,四行四列不够就加行,数字、运算符、功能键各就各位。

颜色我做了区分:数字按钮白底蓝字,运算符灰底黑字,AC(清空)用红色,等号用绿色。这种视觉分组能让操作更快,不用仔细看就知道哪个区域是干嘛的。

from PyQt5.QtWidgets import
from PyQt5.QtCore import

import sys
import math

class Calculator(QMainWindow):
def init(self):
super().init()
self.setWindowTitle("多功能计算器")
self.setFixedSize(400, 500)

    # 显示屏
    self.display = QLCDNumber()
    self.display.setDigitCount(15)
    self.display.setSegmentStyle(QLCDNumber.Flat)

    # 按钮布局
    self.create_buttons()

这里有个小技巧:显示屏的digitCount设15位够用了,真要算天文数字也不会用这个计算器。setSegmentStyle让数字显示更现代一点,老式凸起风格有点过时。

按钮动起来,信号与槽的灵魂所在
PyQt最核心的机制叫“信号与槽”,听起来高大上,说白了就是“点一下按钮,做一件事”。每个按钮被点击时发出clicked信号,我们把这个信号连接到对应的处理函数上。

def create_buttons(self):
buttons = [
['7', '8', '9', '/'],
['4', '5', '6', '*'],
['1', '2', '3', '-'],
['0', '.', '=', '+'],
['C', '√', '^', 'AC']
]

grid = QGridLayout()
central_widget = QWidget()
central_widget.setLayout(grid)
self.setCentralWidget(central_widget)

# 把显示屏和按钮网格拼在一起
main_layout = QVBoxLayout()
main_layout.addWidget(self.display)
main_layout.addLayout(grid)
central_widget.setLayout(main_layout)

for row, row_buttons in enumerate(buttons):
    for col, btn_text in enumerate(row_buttons):
        btn = QPushButton(btn_text)
        btn.clicked.connect(self.on_button_clicked)
        grid.addWidget(btn, row, col)

上面代码里的connect就是关键。不管按了哪个按钮,都交给同一个on_button_clicked函数处理,通过按钮上的文字来判断要做什么。

计算逻辑,比想象中要麻烦一点
一开始我图省事,直接用Python的eval函数计算表达式。这玩意儿确实方便,你给它字符串"2+3*4",它真能算出14。但eval有个大问题——不安全。恶意输入可能执行系统命令,虽然计算器场景风险不高,但这习惯不好。

再说用户体验。eval计算时没有实时反馈,你按完一连串数字和运算符,最后按等号才出结果。更好的做法是维护两个状态:当前输入的数字和等待执行的运算。

def on_button_clicked(self):
text = self.sender().text()

if text.isdigit() or text == '.':
    # 数字或小数点,拼接到当前输入
    self.current_input += text
    self.display.display(self.current_input)

elif text in ['+', '-', '*', '/']:
    # 运算符,保存当前数字和运算符
    self.last_number = float(self.current_input)
    self.current_operator = text
    self.current_input = ''

elif text == '=':
    # 计算结果
    current = float(self.current_input)
    if self.current_operator == '+':
        result = self.last_number + current
    elif self.current_operator == '-':
        result = self.last_number - current
    # ... 其他运算
    self.display.display(result)
    self.current_input = str(result)

这种状态机的方式让计算器更“懂”你在做什么。按完“2+3”,显示屏清空让你输第二个数,最后按等号才出结果——这就是计算器该有的样子。

进阶功能,让计算器真正“高级”起来
光有四则运算称不上“高级”。科学计算器该有的东西得加上:三角函数、对数、开方、幂运算。

def calculate_function(self, func_name):
value = float(self.current_input)

if func_name == 'sqrt':
    result = math.sqrt(value)
elif func_name == 'sin':
    # 角度转弧度
    result = math.sin(math.radians(value))  
elif func_name == 'cos':
    result = math.cos(math.radians(value))
elif func_name == 'log':
    result = math.log10(value)
elif func_name == 'ln':
    result = math.log(value)
# ...

self.display.display(result)
self.current_input = str(result)

这里用Python标准库的math模块就够了,不需要额外安装东西。三角函数的坑是角度和弧度转换,很多人第一次用math.sin(90)发现不是1,就是因为传了角度进去,但函数要的是弧度。

还有个实用的功能是单位换算。长度、重量、温度之间的转换其实都是乘个系数,用字典存起来就行。比如长度换算:{'m':1, 'cm':0.01, 'km':1000, 'inch':0.0254},用户选“100 cm in m”这种格式,解析出来一乘一除就完事。

键盘支持,真正的效率提升
一个只能用鼠标点的计算器算不上趁手。加上键盘监听,让数字小键盘也能操作。

def keyPressEvent(self, event):
key = event.key()

if key in [Qt.Key_0, Qt.Key_1, ..., Qt.Key_9]:
    self.current_input += chr(key)
elif key == Qt.Key_Plus:
    self.set_operator('+')
elif key == Qt.Key_Return or key == Qt.Key_Enter:
    self.calculate_result()
elif key == Qt.Key_Backspace:
    self.current_input = self.current_input[:-1]
elif key == Qt.Key_Escape:
    self.clear_all()

self.display.display(self.current_input)

重写keyPressEvent方法后,用户甚至不需要碰鼠标。右手操作数字小键盘,左手辅助,这效率比系统计算器高太多了。

踩坑记录,给后来人的避坑指南
Qt Designer确实能拖出界面,但生成的.ui文件要转成.py,改一次转一次,特别烦。不如手写代码,版本控制也方便。

布局管理器用QVBoxLayout和QGridLayout组合,别用绝对坐标place()。不同屏幕分辨率下,写死的坐标会让界面乱掉。布局管理器会自动适配,省心。

除法要处理除零错误,开方不能开负数。这些边界条件不处理,程序一崩溃用户体验直接归零。try-except包一下,弹个提示框就行。

try:
result = self.last_number / current
except ZeroDivisionError:
QMessageBox.warning(self, "错误", "除数不能为零")
return
为什么需要自己的计算器
市面上计算器那么多,为什么非要自己写一个?因为没有人比你更懂你的工作流。

你可能经常需要把计算结果复制到某个特定格式里,或者要记录每一次计算的历史,又或者要用到某个冷门的物理常数。这些需求通用软件不会帮你实现,但自己的工具可以。代码就在那里,想加什么功能随时改。

写完之后我把这个计算器设成了快捷键启动,Ctrl+Alt+C呼出,算完自动把结果复制到剪贴板。这个功能实现起来也就十来行代码,但每天都能省下几十秒,一年算下来是个不小的数字。

好的工具不是买来的,是自己造的。当你需要的时候,动手写一个就是最好的选择。

目录
相关文章
|
6天前
|
人工智能 数据可视化 安全
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
本文详解如何用阿里云Lighthouse一键部署OpenClaw,结合飞书CLI等工具,让AI真正“动手”——自动群发、生成科研日报、整理知识库。核心理念:未来软件应为AI而生,CLI即AI的“手脚”,实现高效、安全、可控的智能自动化。
23064 14
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
|
18天前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
34363 141
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
7天前
|
人工智能 JSON 监控
Claude Code 源码泄露:一份价值亿元的 AI 工程公开课
我以为顶级 AI 产品的护城河是模型。读完这 51.2 万行泄露的源码,我发现自己错了。
4663 20
|
6天前
|
人工智能 API 开发者
阿里云百炼 Coding Plan 售罄、Lite 停售、Pro 抢不到?最新解决方案
阿里云百炼Coding Plan Lite已停售,Pro版每日9:30限量抢购难度大。本文解析原因,并提供两大方案:①掌握技巧抢购Pro版;②直接使用百炼平台按量付费——新用户赠100万Tokens,支持Qwen3.5-Max等满血模型,灵活低成本。
1509 3
阿里云百炼 Coding Plan 售罄、Lite 停售、Pro 抢不到?最新解决方案