avatarEsteban Thilliez

Summary

The provided content is a comprehensive guide on building a basic calculator application using Python with the PyQt framework, adhering to the Model-View-Controller (MVC) design pattern.

Abstract

The article is part of a series on building user interfaces with Python and specifically delves into creating a calculator app using PyQt. It assumes prior knowledge of PyQt and the MVC pattern, offering links to foundational articles for readers who need to catch up. The author guides the reader through using QtDesigner to design the UI, converting the design to Python code, and implementing the MVC architecture. The model handles the calculator's logic and token manipulation, the view manages the user interface and display, and the controller connects user actions to the model and view. The article concludes with encouragement for readers to enhance the basic application with additional features and actions.

Opinions

  • The author emphasizes the importance of understanding PyQt and the MVC pattern before proceeding with the tutorial, suggesting that these are key skills for Python UI development.
  • The use of QtDesigner is recommended for UI prototyping, indicating its utility in visualizing the application layout before coding.
  • The author provides their GitHub repository for readers to access the code and UI files, showing a commitment to open-source practices and community learning.
  • By using the built-in eval function for expression evaluation, the author opts for simplicity and readability in the model implementation, while also acknowledging the possibility of replacing it for a custom evaluation logic.
  • The view is designed with attention to detail, such as adjusting font and letter spacing for a more homogeneous display, reflecting the author's focus on user experience.
  • The controller is highlighted as the crucial component that binds the model and view, with the author advocating for keyboard shortcuts to improve user interaction.
  • The article encourages readers to go beyond the basic application, suggesting that complexity can be added by incorporating more buttons, actions, or modifying the evaluation function, which underscores the value of continuous learning and experimentation.
  • The author invites readers to engage with their other content on Medium, indicating a desire to build a community of readers interested in Python and UI development.

Build a Calculator App in Python with PyQt

This story follows the User Interfaces series. You can find the other related stories here:

To have a good understanding of this story, you should know PyQt and the MVC pattern. If you know either of these, you can find stories about them in the story just above.

Also, you can find the code used in this story in my GitHub, here.

After teaching you how to build user interfaces using PyQt and Tkinter, as well as the MVC pattern, it’s time to practice!

We’ll build a tiny calculator app with just some basic functionalities. We’ll try to make it as simple as possible.

QtDesigner

The first step when building user interfaces is to have an idea of how will look our application. As we’ve seen through the series, an easy way to do this is to use QtDesigner.

So let’s install QtDesigner in our project, and open it (if you don’t know how to do this, check this story). We can then create a main window.

Now, you can build your calculator user interface as you want. Look how mine looks:

  1. I’ve created a label and in the properties, I’ve put a border around it. Its initial text is “0”.
  2. I’ve used a vertical layout for the entire window.
  3. Below the label, I’ve added a grid layout to place my buttons.
  4. Some buttons are larger, you can do it easily by dragging and dropping.

If you're not sure about how I’ve done this in QtDesigner, you can find the .ui file in my GitHub whose link is above. It’s the file extension used by QtDesigner, and if you open this file using QtDesigner, you will have the same UI as mine.

Once you have finished your design in QtDesigner, you can save it in your project’s folder.

Now, you can use the following command to turn your .ui file into a .py file you can use in your application:

pyuic5 -o dest src

For example:

pyuic5 -o ./ui/main_window_ui.py ./ui/main_window.ui

Now, we can dive into the code!

Model

As I’ve said earlier, we’ll use the MVC pattern to build our application. So let’s start with the model.

What can be the model of a calculator app? Well, I think the model can just store a list of “tokens”. What I call a token is either a digit, or an operator (*, /, +, -). Our model should also be able to evaluate these digits to give a result.

So, if when we join our tokens, it gives this expression: “34+6*2”, our model should be able to calculate it and return 46 (34+(6*2)).

Here is my implementation of the model:

First, we define some functions to manipulate our tokens. The initial state is just a list only one token: 0. In the get_token function, there’s a little trick to avoid returning the leading 0.

Then, we define a function to calculate the expression stored. It just consists of the built-in eval function, which can evaluate an expression. If you want, you can change this function and don’t use the built-in eval to change the evaluation logic. We return our result as a list, because it’s seen by the application as a list of tokens.

View

The view is very simple. It just should display the current expression, and allow interactions with the user. The interactions will be defined in the controller, so for now we can just code a function for the display.

Here is my code:

As you can see, I change the font of the display when initializing the view. It’s because the letters were too spaced.

Then, my display_tokens function is a bit tricky. It’s because I split each string into characters. For example, if my tokens’ list is [12, “+”, 54], it will become [“1”, “2”, “+”, “5”, “4”].

Why did I do it this way? It’s because letter spacing is not the same if you display “54” than if you display “5” and “4”. To make things homogeneous, I’ve done it this way.

Then, I’ve wrote a little function to deal with events. More about that in the controller.

Finally, there’s a little function to connect our view to the controller.

Controller

The controller is the link between the view and the model.

First, it should connect each button in the view to an action. So, the button “0” should add a “0” to our tokens, the button “1” a “1”, the button “=” should show the result, etc… All these are defined in the controller.

I also used the controller to bind events to actions. I think it’s better to use a calculator using the keyboard than the mouse, so for each button, I’ve bound a key.

Here is my code:

As you can see, all the controller does is connecting buttons to actions, and events to actions.

When a token is added with a button click, it adds it to the model and the view is updated. When the clear button is clicked, it clears the tokens and updates the view. Etc…

Application

The last thing remaining to do is to mix together the view, the model and the controller to build a complete PyQt application.

There’s nothing much to say about the code. First we create a QApplication, like we have to for every Qt application. Then, we instance our objects. Finally, we display the view.

You can now run this code and play with your tiny calculator app!

Final Note

This application is very basic. But practicing is important, even if it’s not to build complex things. And no one said you can’t make this application complex, I even encourage you to modify it and try to add buttons, actions, or change the evaluation function, etc…

You can find the other stories of this series here:

To explore more of my Python stories, click here! You can also access all my content by checking this page.

If you liked the story, don’t forget to clap, comment, and maybe follow me if you want to explore more of my content :)

You can also subscribe to me via email to be notified every time I publish a new story, just click here!

If you’re not subscribed to medium yet and wish to support me or get access to all my stories, you can use my link:

Software Development
Python
Coding
Programming
User Interface
Recommended from ReadMedium