pyqt5 计算器
自己随便写写的,有完整注释,不单单是为了实现,而是尽可能完美
虽然还有不少bug
实现连续运算,退位等操作
ui按钮部分由https://github.com/maicss/PyQt5-Chinese-tutorial提供
原文并没有提供对栅格布局操作,我做的就是添加一个显示屏
然后对按钮信号处理,实现计算器
有bug可以提,但是我肯定懒得改,除非你告诉我怎么改
代码源
import sys
from PyQt5.QtWidgets import (QWidget, QGridLayout, QLCDNumber, QVBoxLayout,QMessageBox,
QPushButton, QApplication)
"""
栅格布局是一种特定的写法,通过位置来确定部件的方位,
[(0, 0 ), (0, 1 ), (0, 2 )
(1, 0 ), (1, 1 ), (1, 2 )
(2, 0 ), (2, 1 ), (2, 2 )]
以元组形式依次对其中的部件进行定义,可以用for循环,也可以自己一个个导入
以下写入的
button = QPushButton(name) # 需要写入的部件
grid.addWidget(button, *position
"""
class Example(QWidget):
def __init__(self):
super().__init__()
self.init_all() # 初始化数据
self.initUI() # ui
def init_all(self):
self.list_number_0 = str()
self.list_number_1 = str()
self.max_len_number = 7
self.Operator_equal = False
self.Operator = ''
def initUI(self):
vbox = QVBoxLayout()
grid = QGridLayout() # 构建栅格布局
self.led = QLCDNumber(self)
self.led.setDigitCount(self.max_len_number)
self.led.setSegmentStyle(QLCDNumber.Filled)
names = ['Cls', 'Bck', '', 'Close',
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', '=', '+']
positions = [(i, j) for i in range(5) for j in range(4)] # 构建四行五列的表格
for position, name in zip(positions, names):
if name == '':
continue
button = QPushButton(name) # 生成按钮添加在特定位置中,只在栅格布局中可以这样用
grid.addWidget(button, *position) # 并未设置信号槽机制
button.clicked.connect(self.button_clicked)
vbox.addWidget(self.led)
vbox.addLayout(grid)
self.setLayout(vbox)
self.resize(400, 300)
self.move(300, 150)
self.setWindowTitle('Calculator')
self.show()
def button_clicked(self):
source = self.sender().text() # 获取触发按键命名
if source.isnumeric(): # 判断命名是否为数字
if self.Operator == '': # 判断处理的是第一个数还是第二个数
if len(self.list_number_0) < self.max_len_number: # 限制输入的位数,可以通过接口直接改变
if self.list_number_0 != '0': # 防止出现显示0001情况,不用float是因为为了后面小数点时不显示问题(为了美观)
self.list_number_0 += source # 添加数字在第一个数后面
self.led.display(self.list_number_0) # 显示数字
else: # 第二个数处理
if len(self.list_number_1) < self.max_len_number:
if self.list_number_1 != '0':
self.list_number_1 += source
self.led.display(self.list_number_1)
if source == '+' or source == '-' or source == '/' or source == '*': # 可以不通过等于号获取结果,进行连续运算
if self.list_number_1: # 只要第二个数存在
if self.Operator == '+': # 按照运算符直接获取结果
value = float(self.list_number_0) + float(self.list_number_1)
self.led.display(value)
elif self.Operator == '-':
value = float(self.list_number_0) - float(self.list_number_1)
self.led.display(value)
elif self.Operator == '*':
value = float(self.list_number_0) * float(self.list_number_1)
self.led.display(value)
else:
if self.list_number_1 != '0': # 分母为0就弹出提示窗口
value = float(self.list_number_0) / float(self.list_number_1)
self.led.display(value)
else:
self.equal_0()
value = 0
self.list_number_0 = str(value) # 最后将数据赋值给第一个数,进行下一次运算
self.list_number_1 = str()
self.Operator_equal = True # 开启
self.Operator = source # 获取运算符
if source == '.': # 小数点处理
if not self.Operator_equal: # 判断第一个还是第二个
self.list_number_0 = str(self.led.value())[:-1]
self.led.display(self.list_number_0)
else:
self.list_number_1 = str(self.led.value())[:-1]
self.led.display(self.list_number_1)
if source == '=': # 等号运算
if self.list_number_1 != '': # 如果第二个值未出现不做任何操作
if self.Operator == '': # 判断是否存在第二个数
self.led.display(self.list_number_0)
else:
if self.Operator == '+': # 运算
value = float(self.list_number_0) + float(self.list_number_1)
self.led.display(value)
elif self.Operator == '-':
value = float(self.list_number_0) - float(self.list_number_1)
self.led.display(value)
elif self.Operator == '*':
value = float(self.list_number_0) * float(self.list_number_1)
self.led.display(value)
else:
if self.list_number_1 != '0': # 分母处理
value = float(self.list_number_0) / float(self.list_number_1)
self.led.display(value)
else:
self.equal_0() # 分母报错提示
value = 0
self.list_number_0 = str(value)
self.Operator_equal = True
if source == 'Bck': # 退位处理
if self.Operator_equal: # 第二个数字不等于空
if len(self.list_number_0) <= 1: # 如果位数小于1就显示0并且初始化
self.list_number_0 = str()
self.led.display('0')
else:
if self.list_number_0[-2] == '.': # 如果小数点存在倒数第二位就把小数点和最后一位数一起删掉
self.list_number_0 = self.list_number_0[:-2] + self.list_number_0[-1] # 也可以不删,但是为了美观
self.list_number_0 = self.list_number_0[:-1]
self.led.display(self.list_number_0)
else:
if self.Operator == '+' or self.Operator == '-' or self.Operator == '*' or self.Operator == '/':
if len(self.list_number_1) <= 1:
self.list_number_1 = str()
self.led.display('0')
else:
if self.list_number_1[-2] == '.':
self.list_number_1 = self.list_number_1[:-2] + self.list_number_1[-1]
self.list_number_1 = self.list_number_1[:-1]
self.led.display(self.list_number_1)
else:
if len(self.list_number_0) <= 1:
self.list_number_0 = str()
self.led.display('0')
else:
if self.list_number_0[-2] == '.':
self.list_number_0 = self.list_number_0[:-2] + self.list_number_0[-1]
self.list_number_0 = self.list_number_0[:-1]
self.led.display(self.list_number_0)
if source == 'Close': # 关闭按钮
self.close()
if source == 'Cls':
self.init_all() # 全部请0
self.led.display('0')
def equal_0(self): # 分母不为0
reply = QMessageBox.question(self, 'Message', f"分母不得为0",
QMessageBox.Retry, QMessageBox.Retry) # 弹出窗口游戏结算
if reply == QMessageBox.Close: # 信号判断
self.close() # 选择关闭
else:
self.init_all() # 选择重新开始
self.led.display('0')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
实现的不是那么好,写到后期发现实际上可以利用显示屏的.value()和.text()来回横跳,但是以欲罢不能了,有兴趣的同学可以沿着这条思路实现,让代码变得更简洁
不可转载