[Issue 19] Creating a PyQt Calculator Program with MVC Architecture/使用MVC架構製作PyQt計算機程式

Posted by


In this tutorial, we will be creating a simple calculator using the Model-View-Controller (MVC) architecture in PyQt. MVC is a design pattern that separates the application into three interconnected components: the model, the view, and the controller. The model represents the data and business logic of the application, the view is the user interface that displays the data, and the controller handles user input and updates the model and view accordingly.

Before we start coding, make sure you have PyQt installed on your system. If not, you can install it using pip:

pip install PyQt5

Now, let’s create the three components of our calculator program:

Model

The model will store the operand values and the result of the calculations. Create a new Python file called calculator_model.py and add the following code:

class CalculatorModel:
    def __init__(self):
        self.operand1 = ''
        self.operand2 = ''
        self.operation = ''
        self.result = ''

    def calculate(self):
        if self.operand1 and self.operand2 and self.operation:
            if self.operation == '+':
                self.result = str(float(self.operand1) + float(self.operand2))
            elif self.operation == '-':
                self.result = str(float(self.operand1) - float(self.operand2))
            elif self.operation == '*':
                self.result = str(float(self.operand1) * float(self.operand2))
            elif self.operation == '/':
                try:
                    self.result = str(float(self.operand1) / float(self.operand2))
                except ZeroDivisionError:
                    self.result = 'Error'
        else:
            self.result = ''

Controller

The controller will handle user input and update the model and view accordingly. Create a new Python file called calculator_controller.py and add the following code:

from calculator_model import CalculatorModel

class CalculatorController:
    def __init__(self):
        self.model = CalculatorModel()

    def set_operand(self, operand):
        if not self.model.operation:
            self.model.operand1 += operand
        else:
            self.model.operand2 += operand

    def set_operation(self, operation):
        self.model.operation = operation

    def calculate(self):
        self.model.calculate()

    def clear(self):
        self.model.operand1 = ''
        self.model.operand2 = ''
        self.model.operation = ''
        self.model.result = ''

View

The view will be the user interface of our calculator. Create a new Python file called calculator_view.py and add the following code:

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

from calculator_controller import CalculatorController

class CalculatorView(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('PyQt Calculator')
        self.setGeometry(100, 100, 400, 400)

        self.controller = CalculatorController()

        self.display = QLineEdit()

        self.buttons = {
            '1': QPushButton('1'),
            '2': QPushButton('2'),
            '3': QPushButton('3'),
            '4': QPushButton('4'),
            '5': QPushButton('5'),
            '6': QPushButton('6'),
            '7': QPushButton('7'),
            '8': QPushButton('8'),
            '9': QPushButton('9'),
            '0': QPushButton('0'),
            '+': QPushButton('+'),
            '-': QPushButton('-'),
            '*': QPushButton('*'),
            '/': QPushButton('/'),
            '=': QPushButton('=')
        }

        layout = QVBoxLayout()
        layout.addWidget(self.display)

        row1 = ['7', '8', '9', '+']
        row2 = ['4', '5', '6', '-']
        row3 = ['1', '2', '3', '*']
        row4 = ['C', '0', '=', '/']

        for row in [row1, row2, row3, row4]:
            h_layout = QHBoxLayout()
            for button_text in row:
                button = self.buttons[button_text]
                button.clicked.connect(lambda _, text=button_text: self.handle_button_click(text))
                h_layout.addWidget(button)
            layout.addLayout(h_layout)

        self.setLayout(layout)

    def handle_button_click(self, text):
        if text.isdigit() or text in '+-*/':
            self.controller.set_operand(text)
            self.display.setText(self.controller.model.operand1 + self.controller.model.operation + self.controller.model.operand2)
        elif text == '=':
            self.controller.calculate()
            self.display.setText(self.controller.model.result)
        elif text == 'C':
            self.controller.clear()
            self.display.clear()

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

Now that we have created the model, view, and controller for our calculator program, we can run the program by running the calculator_view.py file. You should see a simple calculator interface with buttons for inputting numbers and operations, a display for showing the current calculation, and a button for calculating the result.

That’s it! You have successfully created a PyQt calculator program using the MVC architecture. Feel free to customize the program further by adding more functionality or improving the user interface. Happy coding!