Building a Simple Keyboard using Anvil
Anvil is a free and open-source drag and drop web app builder. It is equivalent to the likes of Gradio application. The framework uses the Python programming language only. No HTML, no CSS, and no Javascript.
<!--more-->
This tutorial will leverage this framework to build a functional keyboard similar to the one on your computer.
Prerequisites
To follow through with this tutorial, you need to be conversant with:
- The Python programming language.
- HTML, CSS, and Javascript programming languages.
Outline
- Creating a web page with Anvil
- Creating the components needed for a keyboard
- Creating a panel to replicate how a keyboard appears
- Implementing the different button callbacks
- Testing the functionality of the keyboard
- Styling the keyboard
- Publishing the web app
- Further reading
Creating a web page with Anvil
To get started, we will begin by navigating to the Anvil website. On the top-right corner of the webpage, you will see a Start Building
button. Click on it. You will be prompted to create an account before you can start building. This sign-up process is free.
A verification email will be sent to your email to complete the sign-up process. Once you complete the verification process, you should be redirected to the login page, and the following webpage will appear:
Image Source: Anvil
Select the New Blank App
option. Since we plan to start from scratch and create a custom HTML page, we'll select the Custom HTML
option. Additionally, we can select the Blank Panel
option. At this point, your webpage should look like this:
Image Source: Anvil
Now, we can begin designing our interface.
Creating the components needed for a keyboard
With Anvil, we can drag in whichever component we would like to use in the interface itself. For example, if we want to add a Date Picker
component, we will drag and drop the Date Picker
component from the sidebar into our interface. You can also set some basic properties of this component by scrolling down on the sidebar until you see the properties
option.
One of the most vital components of a keyboard is the input field. For this, we will drag and drop the TextBox
component. Then, we will drag and drop it below the image component with our logo.
Next, we will add our buttons. A keyboard has several buttons. It will make more sense to code them rather than drag and drop all these buttons.
Creating a panel to replicate how a keyboard appears
We have both the Design
and the Code
options on our main interface. Select the Code
option. You will see some basic commands already written for you by the web app builder. You will see a class with an init
method to initialize the web app. We will build upon this code.
Image Source: Anvil
We will begin by creating a list of characters to represent our buttons and store it in a variable known as chars
. Next, we will assign this variable to a list of strings where we arrange these strings in the same order that we want to see our buttons appear on the page.
This is shown below:
chars = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
",", ".", "/", "-", "=", "+", "<--", "*", "Clr",
"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "A", "S", "D",
"F", "G", "H", "J", "K", "L", "Z", "X", "C", "V", "B", "N", "M"
]
This simple keyboard design consists of letters in capital letters, numbers, and punctuation marks. It also consists of +, -, *, /
signs to perform arithmetic. The first row, "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"
represents the first row on the keyboard and so forth.
The next step involves looping over these strings and using them to create button components. First, we will need to create an empty dictionary to store these buttons. We will call this dictionary self.btn
. Then, we will assign it to a set of curly brackets, which is an empty dictionary as shown:
self.btn = {}
Additionally, since we want to arrange these buttons in rows and columns, we need a grid. So we will create a GridPanel
in camel case and assign it to a variable called gridp
as shown:
gridp = GridPanel()
Now, we can place our buttons inside this panel.
for i in chars:
self.btn[i] = Button(text=i)
gridp.add_component(self.btn[i], row = 'A', col_xs = 1, width_xs = 1)
self.add_component(gridp)
The letter
i
represents different buttons.
We can now go ahead and run this code. You can find the Run
button in the topmost section of the webpage. You will be prompted to assign your application a name. Assign it any name you wish. We've assigned ours Simple_Keyboard
. The created webpage should now appear.
Image Source: Anvil
At this point, the components should be displayed on the screen. But they are all over the place. They are not arranged. We will need to arrange them nicely. We will do that later. For now, let's take care of their functionalities.
Implementing the different button callbacks
The goal is to collect the value of the button that we click. We can easily do this using a tag
property as shown:
self.btn[i].tag.name = i
After that, we can access it using a click event. Let's create a click method and connect it to all our buttons. We will write this method at the button of our current code block, outside of the init
method.
def click(self, **event_args):
print(event_args.['sender'].tag.name)
We've temporarily added the
print()
method to test the keys outputs.
Right before we add our buttons to the grid, we will add the following commands to add the click event method:
self.btn[i].set_event_handler('click', self.click)
Click on Run
to check if everything runs correctly and displays a pressed key as the output. Everything should work perfectly.
Make sure to expand the output bar to see the messages.
Once our buttons output the correct characters, we can concatenate them to our text box. Instead of printing the results on the terminal, we can add the following code to the click method to print to the text box instead.
def click(self, **event_args):
self.text_box_1.text += event_args['sender'].tag.name
When you click on a button, it should now display on the text box. It works as expected. The more we press the buttons, the longer our text box length becomes.
We have some buttons that have some special functionality to them, especially when we are dealing with numbers and arithmetic operators. For example, the Clear
and Delete
signs.
Let's go back to our code and add these special functionalities.
Testing the functionality of the keyboard
To make the code simpler to read, we will add the following code inside the click method, a new variable called val
:
def click(self, **event_args):
val = event_args['sender'].tag.name
if val == "=":
self.text_box_1.text = eval(self.text_box_1.text)
elif val == "Clr":
self.text_box_1.text = ""
elif val == "<--":
self.text_box_1.text = self.text_box_1.text[:-1]
else:
self.text_box_1.text += val
Perfect! Our special functionalities should now be working. Click on the Run
button to try it out. Add some numbers and click on the equality sign to output the result. Also, you can press the backspace button to clear characters one by one and the Clear
button to remove everything on the text box.
Now, our keyboard is functioning properly. Let's add some style to it.
Styling the keyboard
We begin by splitting our buttons into four different rows. We will count nine buttons for this build then jump to the next row. The enumerate()
method will help us with this. We will pass our list of characters into it. Enumerate returns two different values instead of one. So we will add an idx
to help count.
Let's add the following block of code:
for idx, i in enumerate(chars):
if idx < 9:
row = 'A'
elif 9 <= idx < 18:
row = 'B'
elif 18 <= idx < 27:
row = 'C'
elif 27 <= idx <36:
row = 'D'
else:
row = 'E'
After adding that new code block, run it to see if it works.
Image Source: Anvil
We replace the A
value in row = 'A'
, with row = row
in the code gridp.add_component(self.btn[i], row = 'A', col_xs = 1, width_xs = 1)
, which is our local variable.
We can also style our buttons to make them prettier. For example, let's add the following code:
self.btn[i] = Button(text=i, bold = True)
Let's also add the following code snippet:
self.space = Spacer(height=400)
self.add_component(self.space)
Publishing the web app
Once we are happy with our web application, we can deploy it. We need to press the Publish this app
button to do this with Anvil. It will generate a code that you can use to view the published web application on your browser. For this application, you can view the published web application here.
Wrapping up
We have deployed our keyboard online. It is beautiful, and we can share it with anyone we like. We have used graphic design tools to create our web application. But this is not the only way. We can also add them to the interface using code, as shown in this tutorial. Feel free to try creating one yourself. You could play around with the different components available that suits your project.
Happy coding!
Further reading
Peer Review Contributions by: Wilkister Mumbi