Outils pour utilisateurs

Outils du site


issue207:python

Ceci est une ancienne révision du document !


Simple Calculator in PAGE

Greetings again fellow Sentient Lifeforms. Things here at landing pad 2997 on Terra haven't calmed down at all since last month. If anything, things are even busier. It looks like (at this time, Friday 5 July) that we will be having an unwanted visitor by the name of Hurricane Beryl. At this point, the chances are really good (or bad if you wish) that we will get at least a “drive by” visit. I’m going to have to get the ground crew to make sure the ship is lashed down and secure. However, I’m not going to let that keep me from sharing information with you.

This month, I’m going to take you through creating a simple calculator in PAGE 8.0, Tkinter. Why? Well, in the last month, I’ve seen two different articles about creating a simple calculator in straight Tkinter and in Wxpython, but nothing about using a great GUI designer like PAGE (and one of them was behind a paywall (ICK)), so I thought I’d throw my two cents into the mix.

Within the article, I’ll show you a couple of tricks that can be used within PAGE, or from just Tkinter if you want to “do it the hard way”.

Just because I’m a nice guy (according to some people), I’ve set up a github repository for you that you can download the entire project which includes all the PAGE files and Python files – so you don’t really have to deal with PAGE if you don’t want to. The URL for the repository can be found at the end of the article.

Basic Requirements

So, the basic requirements for our project will be to create a “4 banger” calculator. Since the phrase “4 banger” goes back to the early days of electronic calculators (1970s), you might not be aware of what that means. Simply put, it’s a calculator that does only addition, subtraction, multiplication and division. That’s it. No mod function, no parentheses, not even a square root function or percentage. Of course, you can add these functions yourself if you want, but I wanted to create a really quick project that wouldn’t make my article take up half of the magazine.

Of course, since it’s me, we will use PAGE 8.0 to design the GUI form. I’m not even going to go into depth on creating the form in PAGE, just some of the highlights. We won’t be using any graphics, only text on the buttons. The only “special characters” we will be using are the “<X]” character for the clear key (U+232B), and the “÷” for the division key (U+00F7).

Since we will be using PAGE 8.0, we’ll use one of the themes I created for it named “cornsilk-light”. Since we will be concentrating more on the Python code instead of the PAGE portion, I’ll give you a small function that will modify that theme to create a bold 18-point font that will apply to all the TButtons, and a slightly darker background to make them stand out from the background of the form a little bit.

Our callbacks for the buttons will be somewhat on the special side, since I’m going to use the lambda function to send a “key definition” via the command attribute for each of the TButtons.

The finished project should look something like this…

Creating the PAGE GUI

So, we’ll need to create a folder to hold our PAGE project, and the themes folder to hold the cornsilk-light theme files. Then copy from the PAGE 8.0 themes folder (or from the repository files) the cornsilk-light.tcl, and the entire cornsilk folder into a themes folder. Now, in a terminal window type

$ page calc1

Now, set your Toplevel form to width=359 and height to 467. Set the title to “Calc1”. Make sure that you are in the Absolute mode so the form won’t resize.

Add a TLabel widget at x=2, y=60, with a height of 50 and a width of 356. Set the background color to “white”, the relief to ‘sunken’, anchor to “w”, the textvar to “Display”, and the font to ‘DejaVu Sans’, size=20 and weight=bold.

Next, place a TButton widget at x=10, y=140, height=49 and width=62. Then set the text to “7”. Finally set the command attribute to “lambda : on_numKey(7)”. The theme will take care of all of the other attributes, and we’ll override some of those when we create our theme override later on in the _support module.

Now, add 10 more TButton widgets aligning them into a “keypad” orientation as in the image above. Set the text to the proper number for that key and the command to “lambda : on_numKey(X)” where X is the number of the key (or for the period key simply ‘.’. Be sure to use single quotes when using the PAGE command attribute text box).

Now, add 6 more TButtons, and set their text as seen in the image above. For the clear and divide keys, there’s a file in the repo called symbols.txt that has the two symbols. Just copy each and paste them into the text attribute column.

At this point, the final step is to enter each of the command line attributes. The one for the Divide button would be “lambda : on_funcKey(‘Divide’)”. From there the text for the command attribute sets would be:

lambda : on_funcKey(‘Mult’) lambda : on_funcKey(‘Sub’) lambda : on_funcKey(‘Add’) lambda : on_funcKey(‘Equal’) lambda : on_funcKey(‘Clear’)

Once you have all your keys defined, save your project as “calc1” and generate the GUI.py file and the Support module.

Your Toplevel should look something like this…

You can close PAGE at this point. Again, none of the buttons have bold font or a background other than the cornsilk3 colour, which the theme contains.

The Code

Now we can begin to create our functions and callbacks in the support module (“calc1_support.py”).

PAGE created the majority of the program for us, but we still need to flesh the skeletons out.

First, we need to add an import statement. Near the top of the file are all of the import statements. Just after the “from tkinter.constants import *” line, you need to add

from tkinter.font import Font

This is because we will be defining a “custom” font in a little bit.

Next, scroll down to the main function. PAGE already created this for us, but we need to run a few extra commands before the form is displayed to you or your user. Just before the last line of the main function, add a line that contains “startup()”. I’ve included the function below with only the line to add in black (next page, top right).

At this point, we need to add the startup function code. I usually put this just after the main function.

The first task we do is clear the ‘Display’ Label widget by calling the .set() method of the Label widget. Then we define a global variable named “dbuf” and set it to an empty string. After that, we call a function called set_button_fonts(), which will create a custom theme for our buttons and finally set the title for the form (code shown above).

Here is the set_button_fonts() function. As you can see from the comments, we create an instance of the ttk.style object, define a new font using “DejaVu Sans”, font size 18 points and weight bold, and assign that a name of “myFont”. Then we call the style.configuration method to set the font to myFont and the background to “cornsilk4” to every TButton widget in the project. Finally we call the update function for the Toplevel to make sure it is done before we show it to the user.

At this point, we have only two more functions to deal with. They are the callbacks for the buttons that make up the “numKey” group and for those that make up the “funcKey” group. The on_numKey callback is REALLY easy (below).

We simply append the value that is sent into the on_numKey function from the button to the variable dbuf and display that in the TLable widget. When we set the command function for the number keys (and the period key), we use the lambda function that allows the command function to send a value into the callback. (Normally callbacks can not include any parameters. We can get around this by using the lambda function). So for the # 4 key, the command attribute would be…

lambda : on_numKey(4)

When it gets to the on_numKey, it is sent in to the *args, which contains all the arguments as a list. Since we are sending in only one value, it will come in as args[0]. That is converted into a string.

Unfortunately, the on_funcKey is a bit more complicated, but not horribly so. In fact it’s more repetitive than complicated. Rather than the “normal” if | elif |else tree, I decided to use the newer match case tree.

The first thing we do is assign the incoming string from the button command to a variable called which. Then the match compares this value to each of the case statements. The cases for “Add”, “Sub”, “Mult” and “Divide” are almost the same, just assigning a different character to match the function to the dbuf global variable. This time I decided to use the f-string method.

So for the “Add” function we add a “+” to the string and so on. Then we send it to the TLabel widget to show to the user.

For the Clear function, we simply set the TLabel widget and the dbuf variable to an empty string (shown right).

Now… the part of the function that makes everything work. That’s the “Equal” case. When the user clicks on the Equal button, we simply take the string that we’ve been building all along and then use python’s eval function.

So if the user clicks the buttons “2”, “+”, “2”, and then presses the equal key, the dbuf variable would be “2+2” and the eval then can deal this as a math statement. Therefore, the answer is (of course) 4.

Simple, but in no way, shape or form is it bullet-proof. I didn’t include any kind of error checking. I did say at the beginning that it was a SIMPLE calculator program.

You can find the repository at https://github.com/gregwa1953/FCM207 which contains all the information that you need to run the program, including the PAGE files, the theme folder and files, and the Python code.

Until next time, as always; stay safe, healthy, positive and creative!

issue207/python.1722068472.txt.gz · Dernière modification : 2024/07/27 10:21 de auntiee