小白白也能学会的 PyQt 教程 —— 实战简易计算器

news2024/11/24 3:35:50

文章目录

    • 导言
    • 一、从 0 到 1:简易计算器实现
      • 1、功能实现
      • 2、代码分析
      • 3、实现效果
    • 二、由简入繁:优化简易计算器的 UI
      • 1、开始布局
      • 2、实现 Driver
      • 3、Driver 代码
      • 4、效果展示
    • 总结

导言

PyQt5 是一个用于创建桌面应用程序的 Python 库,它提供了丰富的 GUI 组件和工具,使得开发者可以快速地构建出美观、易用的界面。在本文中,我们将介绍如何使用 PyQt5 编写一个简易计算器。虽然这个计算器功能简单,但是它可以帮助我们更好地理解 PyQt5 的基本用法和编程思想。通过学习这个计算器,我们可以掌握 PyQt5 的核心概念,例如窗口、布局、事件处理等,并能够应用这些概念来开发更复杂的应用程序。希望本文能够帮助大家入门 PyQt5,并提高自己的编程能力。

在这里插入图片描述

一、从 0 到 1:简易计算器实现

计算器总体上分为两部分,一是数字显示部分,二是数字输入部分,两者依次垂直分布,使用垂直布局(QVBoxLayout)即可解决该问题。对于数字显示部分,我们可以使用 QLabel、QLineEdit 等可以显示文字的组件进行代替;对于数字输入部分,可以看到其是由一个个按钮(QPushButton)组成,这些按钮通过网格布局(QGridLayout)依次排列。将上述部分组合,就是我们常见的计算器的简易实现。

1、功能实现

根据上述需求描述,我们可以编写以下代码:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QPushButton, QGridLayout

class Calculator(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('简易计算器')
        self.setGeometry(300, 300, 300, 400)

        layout = QVBoxLayout()

        self.result_display = QLineEdit()
        layout.addWidget(self.result_display)

        buttons = [
            '7', '8', '9', '/',
            '4', '5', '6', '*',
            '1', '2', '3', '-',
            '0', '.', '=', '+'
        ]

        button_layout = QGridLayout()
        for i, button_text in enumerate(buttons):
            button = QPushButton(button_text)
            button.clicked.connect(self.on_button_clicked)
            button_layout.addWidget(button, i // 4, i % 4)

        layout.addLayout(button_layout)

        self.setLayout(layout)

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

        if key == '=':
            try:
                result = eval(self.result_display.text())
                self.result_display.setText(str(result))
            except Exception as e:
                self.result_display.setText('错误')
        else:
            current_text = self.result_display.text()
            if current_text == '':
                self.result_display.setText(key)
            else:
                self.result_display.setText(current_text + key)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    calculator = Calculator()
    calculator.show()
    sys.exit(app.exec_())

2、代码分析

1、创建一个 Calculator 类,继承自 QWidget。这个类是整个计算器程序的主体部分,它包含了界面的布局、控件的创建和事件处理等。

2、在 __init__ 方法中初始化界面,包括窗口标题、大小、结果显示框等。这个方法是类的构造函数,当创建一个新的 Calculator 实例时,会自动调用这个方法。

3、定义一个按钮布局,将数字和运算符按钮添加到布局中。这个布局是一个二维数组,其中每个元素表示一个按钮的位置和大小。通过设置布局中的元素,可以控制按钮在界面上的位置和排列方式。

4、将按钮布局添加到界面上。这个方法是将布局添加到窗口中的方法,它会根据布局的大小和位置信息,将按钮添加到窗口中。

5、为每个按钮绑定点击事件,当点击按钮时,调用 on_button_clicked 方法。这个方法是按钮的点击事件处理函数,它会在按钮被点击时被调用。在这个方法中,可以根据按钮的文本(即数字或运算符)进行相应的操作。

6、在 on_button_clicked 方法中,获取被点击的按钮的文本(即数字或运算符),并根据当前的结果显示框内容进行相应的操作。如果按下的是等号键,则尝试使用 Python 的 eval 函数计算表达式的结果,并将结果显示在结果显示框中;否则,将新的数字或运算符添加到结果显示框中。

7、在主程序中创建一个 Calculator 实例,并显示出来。这个实例是整个程序的入口点,它会创建一个窗口并显示出来。

在这里插入图片描述

3、实现效果

代码实现的简易计算器效果如下:

请添加图片描述

二、由简入繁:优化简易计算器的 UI

然而,上述的简易计算器不够高端大气上档次,不符合我们的气质,此时我们需要对 UI 进行优化,让这个计算器看起来不是那么普通,打开我们的 Qt Designer,开始进行接下来的操作,并创建一个 MainWindow。

在这里插入图片描述

在这里插入图片描述

1、开始布局

布局输出区与输入区,MainWindow 垂直布局上部分输出区为一个 QLCDNumber,用来显示像是计算器数字 LCD 数字;下部分输入区为 Frame,用来存放按键;

在这里插入图片描述

将输入区 Frame 的布局设置为网格布局(QGridLayout),并添加若干个按钮(QPushButton),并设置文本

在这里插入图片描述

设置按钮字体大小,字体样式,以及 Frame 大小,设置 MainWindow 固定;

在这里插入图片描述

保存一下 .ui 设计文件,并使用 pyurc 工具将 .ui 文件转换成 .py 文件;

pyuic5 calc.ui -o calc.py

转换后的代码如下:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'calc.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.setWindowModality(QtCore.Qt.NonModal)
        MainWindow.resize(380, 400)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMinimumSize(QtCore.QSize(380, 400))
        MainWindow.setMaximumSize(QtCore.QSize(380, 400))
        MainWindow.setStyleSheet("\n"
"")
        MainWindow.setTabShape(QtWidgets.QTabWidget.Rounded)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.lcdNumber = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcdNumber.setObjectName("lcdNumber")
        self.verticalLayout.addWidget(self.lcdNumber)
        self.frame = QtWidgets.QFrame(self.centralwidget)
        self.frame.setMinimumSize(QtCore.QSize(0, 0))
        self.frame.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.frame.setBaseSize(QtCore.QSize(0, 0))
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.gridLayout = QtWidgets.QGridLayout(self.frame)
        self.gridLayout.setObjectName("gridLayout")
        self.pushButton_subtract = QtWidgets.QPushButton(self.frame)
        self.pushButton_subtract.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_subtract.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_subtract.setFont(font)
        self.pushButton_subtract.setObjectName("pushButton_subtract")
        self.gridLayout.addWidget(self.pushButton_subtract, 3, 3, 1, 1)
        self.pushButton_multiply = QtWidgets.QPushButton(self.frame)
        self.pushButton_multiply.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_multiply.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_multiply.setFont(font)
        self.pushButton_multiply.setObjectName("pushButton_multiply")
        self.gridLayout.addWidget(self.pushButton_multiply, 2, 3, 1, 1)
        self.pushButton_add = QtWidgets.QPushButton(self.frame)
        self.pushButton_add.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_add.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_add.setFont(font)
        self.pushButton_add.setObjectName("pushButton_add")
        self.gridLayout.addWidget(self.pushButton_add, 4, 3, 1, 1)
        self.pushButton_n3 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n3.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n3.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n3.setFont(font)
        self.pushButton_n3.setObjectName("pushButton_n3")
        self.gridLayout.addWidget(self.pushButton_n3, 1, 2, 1, 1)
        self.pushButton_n5 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n5.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n5.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n5.setFont(font)
        self.pushButton_n5.setObjectName("pushButton_n5")
        self.gridLayout.addWidget(self.pushButton_n5, 2, 1, 1, 1)
        self.pushButton_n7 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n7.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n7.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n7.setFont(font)
        self.pushButton_n7.setObjectName("pushButton_n7")
        self.gridLayout.addWidget(self.pushButton_n7, 3, 0, 1, 1)
        self.pushButton_divide = QtWidgets.QPushButton(self.frame)
        self.pushButton_divide.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_divide.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_divide.setFont(font)
        self.pushButton_divide.setObjectName("pushButton_divide")
        self.gridLayout.addWidget(self.pushButton_divide, 1, 3, 1, 1)
        self.pushButton_n0 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n0.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n0.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n0.setFont(font)
        self.pushButton_n0.setObjectName("pushButton_n0")
        self.gridLayout.addWidget(self.pushButton_n0, 4, 0, 1, 1)
        self.pushButton_n4 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n4.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n4.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n4.setFont(font)
        self.pushButton_n4.setObjectName("pushButton_n4")
        self.gridLayout.addWidget(self.pushButton_n4, 2, 0, 1, 1)
        self.pushButton_n6 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n6.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n6.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n6.setFont(font)
        self.pushButton_n6.setObjectName("pushButton_n6")
        self.gridLayout.addWidget(self.pushButton_n6, 2, 2, 1, 1)
        self.pushButton_n9 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n9.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n9.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n9.setFont(font)
        self.pushButton_n9.setObjectName("pushButton_n9")
        self.gridLayout.addWidget(self.pushButton_n9, 3, 2, 1, 1)
        self.pushButton_n1 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n1.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n1.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n1.setFont(font)
        self.pushButton_n1.setObjectName("pushButton_n1")
        self.gridLayout.addWidget(self.pushButton_n1, 1, 0, 1, 1)
        self.pushButton_n2 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n2.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n2.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n2.setFont(font)
        self.pushButton_n2.setObjectName("pushButton_n2")
        self.gridLayout.addWidget(self.pushButton_n2, 1, 1, 1, 1)
        self.pushButton_n8 = QtWidgets.QPushButton(self.frame)
        self.pushButton_n8.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_n8.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_n8.setFont(font)
        self.pushButton_n8.setObjectName("pushButton_n8")
        self.gridLayout.addWidget(self.pushButton_n8, 3, 1, 1, 1)
        self.pushButton_equal = QtWidgets.QPushButton(self.frame)
        self.pushButton_equal.setMinimumSize(QtCore.QSize(0, 50))
        self.pushButton_equal.setMaximumSize(QtCore.QSize(16777215, 50))
        font = QtGui.QFont()
        font.setFamily("MF LiHei (Noncommercial)")
        font.setPointSize(17)
        font.setItalic(False)
        self.pushButton_equal.setFont(font)
        self.pushButton_equal.setObjectName("pushButton_equal")
        self.gridLayout.addWidget(self.pushButton_equal, 4, 1, 1, 2)
        self.verticalLayout.addWidget(self.frame)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 380, 23))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.action_clear = QtWidgets.QAction(MainWindow)
        self.action_clear.setObjectName("action_clear")
        self.menu.addAction(self.action_clear)
        self.menubar.addAction(self.menu.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "计算器"))
        self.pushButton_subtract.setText(_translate("MainWindow", "-"))
        self.pushButton_multiply.setText(_translate("MainWindow", "×"))
        self.pushButton_add.setText(_translate("MainWindow", "+"))
        self.pushButton_n3.setText(_translate("MainWindow", "3"))
        self.pushButton_n5.setText(_translate("MainWindow", "5"))
        self.pushButton_n7.setText(_translate("MainWindow", "7"))
        self.pushButton_divide.setText(_translate("MainWindow", "÷"))
        self.pushButton_n0.setText(_translate("MainWindow", "0"))
        self.pushButton_n4.setText(_translate("MainWindow", "4"))
        self.pushButton_n6.setText(_translate("MainWindow", "6"))
        self.pushButton_n9.setText(_translate("MainWindow", "9"))
        self.pushButton_n1.setText(_translate("MainWindow", "1"))
        self.pushButton_n2.setText(_translate("MainWindow", "2"))
        self.pushButton_n8.setText(_translate("MainWindow", "8"))
        self.pushButton_equal.setText(_translate("MainWindow", "="))
        self.menu.setTitle(_translate("MainWindow", "功能"))
        self.action_clear.setText(_translate("MainWindow", "清零"))

2、实现 Driver

之后,我们需要编写 Driver 来通过 UI 调用我们的函数功能:

在这里插入图片描述

下面是代码部分:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

import operator

from calc import Ui_MainWindow

首先,我们导入了PyQt5的模块,包括QtGui、QtWidgets和QtCore。还导入了一个名为operator的模块,用于执行基本的算术运算。然后,从calc模块中导入了Ui_MainWindow类,这是使用Qt Designer设计的计算器主窗口的用户界面类。

START = 0
INPUT = 1

我们定义了两个常量STARTINPUT,分别表示计算器的起始状态和输入状态。

class Calculator(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(Calculator, self).__init__()
        self.setupUi(self)

接下来定义了一个名为Calculator的类,它继承自QMainWindowUi_MainWindow。通过调用super()函数,我们初始化了QMainWindow的构造函数和Ui_MainWindowsetupUi()方法,从而创建了计算器的主窗口。

for n in range(0, 10):
    getattr(self, 'pushButton_n%s' % n).pressed.connect(lambda v=n: self.input_number(v))

__init__函数中,使用循环将数字键与input_number函数绑定。通过getattr()函数,我们根据数字创建了按钮的名称,然后将其与input_number函数使用pressed.connect()方法进行绑定。这样,当用户按下数字键时,会调用相应的input_number函数。

self.pushButton_add.pressed.connect(lambda: self.operation(operator.add))
self.pushButton_subtract.pressed.connect(lambda: self.operation(operator.sub))
self.pushButton_multiply.pressed.connect(lambda: self.operation(operator.mul))
self.pushButton_divide.pressed.connect(lambda: self.operation(operator.truediv))
self.pushButton_equal.pressed.connect(self.equals)

类似地,我们将加号、减号、乘号、除号和等号按钮与相应的操作函数进行绑定。使用lambda函数将操作函数和相应的算术运算符绑定在一起。

self.action_clear.triggered.connect(self.reset)

我们还将"Clear"操作与reset函数进行绑定。当用户选择"Clear"操作时,将调用reset函数来重置计算器。

def display(self):
    self.lcdNumber.display(self.stack[-1])

display函数用于更新lcdNumber部件上显示的数字,它显示了计算器堆栈的顶部元素。

def reset(self):
    self.state = START
    self.stack = [0]
    self.last_operation = None
    self.current_op = None
    self.display()

reset函数将计算器重置为初始状态。它将状态设置为START,将堆栈设置为只包含0的列表,将上一次的操作和当前操作设置为None,然后调用display函数来更新显示。

def input_number(self, v):
    if self.state == START:
        self.state = INPUT
        self.stack[-1] = v
    else:
        self.stack[-1] = self.stack[-1] * 10 + v

    self.display()

input_number函数用于处理用户输入的数字。如果当前状态是START,则将状态设置为INPUT,并将堆栈的顶部元素设置为输入的数字v。如果当前状态是INPUT,则将输入的数字追加到堆栈的顶部元素上。然后,调用display函数来更新显示。

def operation(self, op):
    if self.current_op:
        self.equals()

    self.stack.append(0)
    self.state = INPUT
    self.current_op = op

operation函数用于处理用户输入的操作符。如果当前操作符不为空,则先执行equals函数来执行之前的操作。然后,将0追加到堆栈中,将状态设置为INPUT,并将当前操作符设置为输入的操作符op

def equals(self):
    if self.state == START and self.last_operation:
        s, self.current_op = self.last_operation
        self.stack.append(s)

    if self.current_op:
        self.last_operation = self.stack[-1], self.current_op

        try:
            self.stack = [self.current_op(*self.stack)]
        except Exception:
            self.lcdNumber.display('ERROR')
            self.stack = [0]
        else:
            self.current_op = None
            self.state = START
            self.display()

equals函数用于执行等号操作。如果当前状态是START且存在上一次的操作,则将上一次的结果和当前操作符添加到堆栈中。然后,执行当前操作符对堆栈中的数字进行计算。如果计算过程中出现异常,将在lcdNumber部件上显示"ERROR",否则将当前操作符和状态重置为NoneSTART,并调用display函数更新显示。

最后,通过创建一个QApplication对象并执行app.exec_()来运行整个应用程序。

这就是这段计算器程序的主要逻辑和功能。它使用PyQt5创建了一个具有图形用户界面的计算器,可以执行数字输入、算术运算和重置操作,并将结果显示在LCD显示屏上。

3、Driver 代码

Driver 代码如下:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

import operator

from calc import Ui_MainWindow


START = 0  # 表示计算器的起始状态的常量
INPUT = 1  # 表示计算器的输入状态的常量

class Calculator(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(Calculator, self).__init__()
        self.setupUi(self)

        # 将数字键与input_number函数绑定
        for n in range(0, 10):
            getattr(self, 'pushButton_n%s' % n).pressed.connect(lambda v=n: self.input_number(v))

        # 将操作符按钮(+、-、×、÷、=)与operation函数绑定
        self.pushButton_add.pressed.connect(lambda: self.operation(operator.add))
        self.pushButton_subtract.pressed.connect(lambda: self.operation(operator.sub))
        self.pushButton_multiply.pressed.connect(lambda: self.operation(operator.mul))
        self.pushButton_divide.pressed.connect(lambda: self.operation(operator.truediv))
        self.pushButton_equal.pressed.connect(self.equals)

        # 将“清除”操作与reset函数绑定
        self.action_clear.triggered.connect(self.reset)

        self.memory = 0
        self.reset()

        self.show()

    def display(self):
        # 在lcdNumber部件上显示堆栈的顶部元素
        self.lcdNumber.display(self.stack[-1])

    def reset(self):
        # 将计算器重置为初始状态
        self.state = START
        self.stack = [0]
        self.last_operation = None
        self.current_op = None
        self.display()

    def input_number(self, v):
        # 处理输入数字的逻辑
        if self.state == START:
            self.state = INPUT
            self.stack[-1] = v
        else:
            self.stack[-1] = self.stack[-1] * 10 + v

        self.display()

    def operation(self, op):
        # 处理输入操作符的逻辑
        if self.current_op:
            self.equals()

        self.stack.append(0)
        self.state = INPUT
        self.current_op = op

    def equals(self):
        # 当按下“=”按钮时进行计算
        if self.state == START and self.last_operation:
            s, self.current_op = self.last_operation
            self.stack.append(s)

        if self.current_op:
            self.last_operation = self.stack[-1], self.current_op

            try:
                self.stack = [self.current_op(*self.stack)]
            except Exception:
                self.lcdNumber.display('ERROR')
                self.stack = [0]
            else:
                self.current_op = None
                self.state = START
                self.display()


if __name__ == '__main__':
    app = QApplication([])
    app.setApplicationName("计算器")

    calc = Calculator()
    app.exec_()

4、效果展示

新版计算器效果如下:

请添加图片描述

总结

希望本文对初学者能够提供一个入门PyQt5编程的起点,并为大家进一步探索和应用PyQt5提供帮助。通过深入学习和实践,您可以利用PyQt5创建出丰富、交互性强的桌面应用程序,提升自己的编程能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/745232.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb 拦截器(interceptor)和过滤器(filter)的区别 总结

一、区别 实现原理使用和适用范围使用场景触发时机请求顺序 二、具体展开说明 2.1 实现原理 过滤器Filter :基于函数也就是方法回调来完成拦截和放行的操作。 拦截器(interceptor):拦截器则是通过Java 反射机制(动态代理)来实…

python_寻找底部股票

目录 写在前面: 下面开始进入正文,正文很长,先概述要点步骤,以防迷路。 先看最终结果(当前价格为2023-07-10收盘价) 1 下载股票基本信息、股票日数据 step one step two 2 从股票日数据中提取股票月数…

优思学院|如何衡量六西格玛中解决方案的有效性?

当你遇到任何质量问题,不论你使用的PDCA或者是六西格玛DMAIC策略,(1) 你都需要测量当前绩效,(2) 分析其原因,以至其根本原因,(3) 进行方案的试行、假设检验来进行验证,这就是解问题的必须步骤。 除了假设检…

计网笔记--运输层(vital)

1--运输层概述 运输层的任务: 为运行在不同主机上的应用进程提供直接的通信服务; 运输层为应用层提供了两种不同的运输协议: 面向连接的 TCP 和无连接的 UDP 协议; 2--端口号、复用与分用的概念 端口号: 端口号用于区分…

交互式绘图程序(MFC) 绘图例子

交互式绘图程序(MFC) 绘图例子 如需要项目源码,可自行下载 交互式绘图程序(MFC)GandyDraw-MFC项目源码-C#文档类资源-CSDN文库https://download.csdn.net/download/m0_71122770/87982379

Django实现简单的音乐播放器 4

在原有音乐播放器功能基础上,增加上传音乐功能。 效果: 目录 配置上传路径 配置路由 视图处理歌曲 引入类库 保存歌曲文件 模板上传 设置菜单列表 设置菜单列表样式 脚本设置 上传效果 1.显示菜单列表 2.点击上传歌曲 3.上传完成 4.查看保…

Python批量读取csv(xlsx)文件指定表头获取内容(表头可乱序)

程序背景 我们在日常办公中经常会遇到去csv或者excel文件中去剪切自己需要的列,然后重新粘贴在新的文件中,但是这样的工作方式非常的耗时,且效率低下,那么是否有一种方法,只要我提供表头就可以快速将我需要的表头生成一…

刚刚出炉!速看7月编程语言排行榜!

2023年已经过半,最新一期的编程语言排行榜你看了吗?刚刚,全球知名编程语言社区TIOBE公布了7月榜单,和播妞一起来看吧! TIOBE 7 月 TOP 15 编程语言: 详细榜单可参考官网: https://www.tiobe.co…

超越廉价: 制造一种稀缺性,产品/服务本身具有一种不可复制、与众不同的特性。

文章目录 I 超越廉价1.1 培养自己的稀缺性1.2 为核心客户提供一些价值I 超越廉价 制造一种稀缺性,产品/服务本身具有一种不可复制、与众不同的特性。 时效性:具有时效性的东西天然具有不可复制的特性直播的时效性是重播不可替代的地方人的技能也是有时效性的,当满大街都是某…

最大正方形(力扣)暴力 + 动态规划 JAVA

在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内,找到只包含 ‘1’ 的最大正方形,并返回其面积。 示例 1: 输入:matrix [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“…

陆航组训VR虚拟交互教学软件提高团队协作水平

出于陆航独特的空中环境,难以确保航空兵连队接受高质量的空中飞行训练,造成陆航连队无法保持良好的战备状态,随着VR虚拟现实技术越来越成熟,VR公司深圳华锐视点充分了解陆航训练教学的重点和难点,制作陆航训练VR教学课…

大模型技术发展概述 - (一)

文本内容参考论文《A Survey of Large Language Models》 论文标题:A Survey of Large Language Models 论文链接:https://arxiv.org/pdf/2303.18223v10.pdf 因为这个论文内容太多了,所以我的文章分成几篇来展示!目录如下&#x…

每日一练 | 华为认证真题练习Day76

1、标准STP模式下,下列非根交换机中的哪个端口会转发由根交换机产生的TC置位BPDU? A. 根端口 B. 备份端口 C. 预备端口 D. 指定端口 2、STP协议中根桥发出的配置BPDU报文中的Message Age为0。 A. 对 B. 错 3、STP中选举根端口时需要考虑以下哪些参…

若依官方前端手册 小笔记

提供确认窗体信息 this.$modal.confirm(确认信息).then(function() {... }).then(() > {... }).catch(() > {}); 提供遮罩层信息 // 打开遮罩层 this.$modal.loading("正在导出数据,请稍后...");// 关闭遮罩层 this.$modal.closeLoading(); 验证…

Android 进程与进程之间的通讯 详解及实现步骤 -- 两个app实现

详情如下: 一、Intent二、Messenger三、AIDL四、广播五、文件 分两个app -- 客户端为:jinc1application、服务端为:jinc2application 一、Intent 这是 Android 中最常用的通讯方式,主要用于启动 Activity、Service 等 jinc1applic…

校园网免认证/校园网pojie

我们的目标是xiao yuan wang pojie 我们使用一个简单的python脚本,用于jiechu /pojie校园网只能登录一台手机和一台电脑的限制,仅供学习。 原理 我们利用已有可正常上网的校园网账户作为跳板,连上网后在后台下线账号所登录的设备&#xff0…

CNVnator软件的安装

1. 下载CNVvator CNVvator软件比较难安装,其依赖root软件等 下载地址 点击其release,下载最新版本v0.4.1(CNVnator_v0.4.1.zip) 2. 安装依赖 root 软件 root 的下载地址 root , 选择下列Ubuntu 20版本 解压root压缩包: ##解压 tar -zxv…

pdf转图片操作方法是什么?分享两个简单的方法!

PDF转图片是一个常见的需求,无论是为了方便编辑、共享,还是为了其他用途,我们需要简单而有效的方法来实现这个目标。本文将介绍两种简单的PDF转图片方法:记灵在线工具和截图方法。 记灵在线工具是一个强大而易于使用的在线工具&a…

如何结合云原生和低代码

前言 云原生和低代码是当今IT领域最流行的两个概念。云原生是一种应用架构设计、应用部署乃至应用开发过程的方式,而低代码是一种快速开发应用的方法。这两者有什么关系?如何结合呢? 先思考一个问题——一个杯子和一个苹果如何结合&#xf…

七牛云的使用(图片超详讲解)

一、为什么要使用七牛云的OSS(对象存储服务)? 二、七牛云使用: 登录七牛云官网,注册并认证 (初次认证有30天免费使用权限)新建存储空间 点击创建的空间名字,进入 空间概括如下: 阅读帮助文档,在自己的…