I only recently overcame my usual inertia and responded to the invitations by VSCode to start using Copilot. Since then I've spent quite some time refining a fairly complex prompt, so I've decided to share my experience with the community.
I operate in the world of Python. In this world there really is no excuse for not using a graphical interface wherever one is appropriate. It's really easy to get Copilot to create a UI to accept input and present output, though a little harder to produce something that's also aesthetically pleasing. But there's a point at which a prompt takes longer to write than does coding the entire job manually.
The project I'm working on is a home heating control system, the control code and the user interface for which are both written in Python, the latter with some help from Copilot. The controller hardware is a 7-inch industrial computer from Ali Express, which arrived with a dreadful Android implementation but which I successfully reflashed to Debian Linux. Now it's a proper computer, but it lacks an essential feature; there's no virtual keyboard. (There seem to be a couple of truly appalling ones out there, but I wouldn't inflict them on a customer.)
So the need was for a Python virtual keyboard. Quite a tedious manual programming task, but I figured it would be ideal for Copilot to get its teeth into. I decided to emulate an Android keyboard, which has 4 views that switch when shift or mode keys are tapped, and above the keys there's a text field for the characters being typed. Here's the first view of the keyboard:
'Prompt engineering' is the term that refers to the skill needed to get effective results from an AI tool. As with most things in life, the GIGO principle applies; Garbage In, Garbage Out. I found it necessary to apply a good deal of guidance or the results had severe limitations and were a poor starting point for further manual embellishment. But if you're careful with your prompts you can get quite decent Python code from an AI engine.
I say "can" because there's a massive caveat coming. A keyboard is not an exceptionally complex item, but without a lot of guidance all the AI engines I tried produced poorly structured code that didn't behave properly. So I tried again, this time leveraging my existing knowledge of Python and PySide (the Qt graphics library module) to structure my prompt. I requested a series of classes - a keyboard button, a row of buttons, a keyboard view comprising several rows, and finally the keyboard itself - giving for each class a set of function definitions and letting Copilot fill in the details. It turned out to be quite a substantial task. In fact, the prompt - even though it's incomplete - is far longer than the final working Python code - somewhere around 500 lines versus 320 lines of Python.
One problem is that human-computer interfaces are a lot more complex that might be imagined, and a lot of details have to be spelled out in, well, excruciating detail. That's a job for a computer program, of course, which begs the question of what kind of language we should be using to write AI prompts. It's early days for this technology, but I feel there's a Eureka! moment waiting to be unearthed.
Sadly, the rather long prompt below will not create a complete keyboard. For example, there's no text box to receive the typed characters. And if your experience is anything like mine, you won't get a complete set of keyboard views; Copilot just generates a comment that views 1, 2 and 3 are similar to view 0 and invites you to do the rest yourself. It seems to be influenced by previous versions of your prompt and decides to ignore bits of the new one. However, what you do get is probably enough to make completing the job by hand relatively easy.
And that's my main take-away from this exercise. There are a lot of details that are simply too tedious to cover in an all-encompassing prompt script. You're far better off generating the main outline then using smaller prompts to fill in the nit-picky little details.
The bottom line is, AI isn't going to take away your job and do it better. Not yet, anyway. But it can be a most valuable assistant, so please start using it. And your comments are welcome - I'm still at the start of the learning curve.
(Cover image by Gemini)
This prompt describes a virtual keyboard,
to be written in Python using Pyside6 graphics.
I provide Python-style class definitions,
with constructor and function prototypes.
Python comments are general notes and instructions
to help build the classes.
#---------------------------------------------------------------
class KeyboardButton(QPushButton):
def __init__(self, width, height, callback, text, icon):
# The text to be shown on the button can be any string or None
# The icon to be shown on the button can be any graphic, or None
# The button has rounded corners of radius 20% of its height
# The font size is half the button height
# The background of the button is white
# Apply a light shadow to the right and bottom of the button
# When the button is clicked it moves 2 pixels down and right,
# waits 200ms then moves back to its original position.
# On click, call function 'callback' with the value of 'text'.
#---------------------------------------------------------------
class KeyboardRow(QHBoxLayout):
def __init__(self, list): # add the items in 'list'
#---------------------------------------------------------------
class KeyboardView(QVBoxLayout):
def __init__(self, list): # add the items in 'list'
#---------------------------------------------------------------
This class is a complete keyboard with 4 views,
which are added one by one and only one of which can be visible.
class VirtualKeyboard(QStackedWidget):
def __init__(self, buttonHeight):
super().__init__()
self.buttonHeight = buttonHeight
def addView(self, view): # Add 'view' to the VirtualKeyboard
def getCurrentView(self): # return the current index
def onClickChar(self, keycode): # Print the key code
def onClickShift(self, keycode): # Print 'Shift'.
# if currentView is 0 call AbstractKeyboard.setCurrentIndex(1)
# elif currentView is 1 call AbstractKeyboard.setCurrentIndex(0)
def onClickNumbers(self, keycode): # Print `Numbers`
# call AbstractKeyboard.setCurrentIndex(2)
def onClickLetters(self, keycode): # Print `Letters`
# call AbstractKeyboard.setCurrentIndex(3)
def onClickBack(self, keycode): # Print 'Back'
def onClickSpace(self, keycode): # Print `Space`
def onClickEnter(self, keycode): # Print 'Enter'
# This class sets up a keyboard
# __init__() calls each of the addKeyboardLayout() functions
The 4 keyboard views are as follows.
All buttons have the height given by buttonHeight.
All buttons have the same width as their height
unless specified otherwise.
#---------------------------------------------------------------
# View 0
Create an empty row list
Create a list of KeyboardButton with the characters in 'qwertyuiop'
The 'callback' function is onClickChar
Create a KeyboardRow with this list
Add the KeyboardRow to the row list
Create an empty list of widgets
Add a horizontal stretch to the widget list
Create a list of KeyboardButton with the characters into 'asdfghjkl'
The 'callback' function is onClickChar
Append this list to the widget list
Add a horizontal stretch to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create an empty list of widgets
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'up.png'
the 'callback' function is onClickShift
Append the KeyboardButton to the widget list
Append a spacer whose width is 5% of the standard height
Create a list of KeyboardButton with the characters in 'zxcvbnm'
The 'callback' function is onClickChar
Append this list to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'back.png'
the 'callback' function is onClickBack
Append the KeyboardButton to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create an empty list of widgets
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'numbers.png'
the 'callback' function is onClickNumbers
Append the KeyboardButton to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with the character ','
The 'callback' function is onClickChar
Append this button to the widget list
Create a KeyboardButton with
a width 500% of the standard height
the standard height
a text value None
an icon taken from the graphic 'space.png'
the 'callback' function is onClickSpace
Create a KeyboardButton with the character '.'
The 'callback' function is onClickChar
Append this button to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'enter.png'
the 'callback' function is onClickEnter
Append the KeyboardButton to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create a KeyboardView with the row list
Add the KeyboardView to this VirtualKeyboard
#---------------------------------------------------------------
# View 1
Create an empty row list
Create a list of KeyboardButton with the characters in 'QWERTYUIOP'
The 'callback' function is onClickChar
Create a KeyboardRow with this list
Add the KeyboardRow to the row list
Create an empty list of widgets
Add a horizontal stretch to the widget list
Create a list of KeyboardButton with the characters in 'ASDFGHJKL'
The 'callback' function is onClickChar
Append this list to the widget list
Add a horizontal stretch to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create an empty list of widgets
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'up.png'
the 'callback' function is onClickShift
Append the KeyboardButton to the widgt list
Append a spacer whose width is 5% of the standard height
Create a list of KeyboardButton with the characters in 'ZXCVBNM'
The 'callback' function is onClickChar
Append this list to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'back.png'
the 'callback' function is onClickBack
Append the KeyboardButton to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create an empty list of widgets
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'numbers.png'
the 'callback' function is onClickNumbers
Append the KeyboardButton to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with the character ','
The 'callback' function is onClickChar
Append this button to the widget list
Create a KeyboardButton with
a width 500% of the standard height
the standard height
a text value None
an icon taken from the graphic 'space.png'
the 'callback' function is onClickSpace
Create a KeyboardButton with the character '.'
The 'callback' function is onClickChar
Append this button to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'enter.png'
the 'callback' function is onClickEnter
Append the KeyboardButton to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create a KeyboardView with the row list
Add the KeyboardView to this VirtualKeyboard
#---------------------------------------------------------------
# View 2
Create an empty row list
Create a list of KeyboardButton with the characters in '1234567890'
The 'callback' function is onClickChar
Create a KeyboardRow with this list
Add the KeyboardRow to the row list
Create a list of KeyboardButton with the characters in '@#£&_-()=%'
The 'callback' function is onClickChar
Create a KeyboardRow with this list
Add the KeyboardRow to the row list
Create an empty list of widgets
Create a KeyboardButton with
the standard height
a text value None
an icon taken from the graphic 'symbols.png'
the 'callback' function is onClickSymbols
Append the KeyboardButton to the widgt list
Append a spacer whose width is 5% of the standard height
Create a list of KeyboardButton with the characters in '"*'
Add "'" to the list
Add the characters in ':/!?+' to the list
The 'callback' function for everything in this list is onClickChar
Append this list to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with
the standard height
a text value None
an icon taken from the graphic 'back.png'
the 'callback' function is onClickBack
Append the KeyboardButton to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create an empty list of widgets
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'letters.png'
the 'callback' function is onClickLetters
Append the KeyboardButton to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with
a width 500% of the standard height
the standard height
a text value None
an icon taken from the graphic 'space.png'
the 'callback' function is onClickSpace
Create a KeyboardButton with the character '.'
The 'callback' function is onClickChar
Append this button to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'enter.png'
the 'callback' function is onClickEnter
Append the KeyboardButton to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create a KeyboardView with the row list
Add the KeyboardView to this VirtualKeyboard
#---------------------------------------------------------------
# View 3
Create an empty row list
Create a list of KeyboardButton with the characters in '$€¥¢©®µ~¿¡'
The 'callback' function is onClickChar
Create a KeyboardRow with this list
Add the KeyboardRow to the row list
Create a list of KeyboardButton with the characters in '¼½¾[]{}<>^'
The 'callback' function is onClickChar
Create a KeyboardRow with this list
Add the KeyboardRow to the row list
Create an empty list of widgets
Create a KeyboardButton with
the standard height
a text value None
an icon taken from the graphic 'numbers.png'
the 'callback' function is onClickNumbers
Append the KeyboardButton to the widget list
Append a spacer whose width is 5% of the standard height
Create a list of KeyboardButton with the characters in '`;÷\∣|¬±'
The 'callback' function is onClickChar
Append this list to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with
the standard height
a text value None
an icon taken from the graphic 'back.png'
the 'callback' function is onClickBack
Append the KeyboardButton to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create an empty list of widgets
Create a KeyboardButton with
the standard height
a text value None
an icon taken from the graphic 'symbols.png'
the 'callback' function is onClickSymbols
Append the KeyboardButton to the widgt list
Append a spacer whose width is 5% of the standard height
Create a list of KeyboardButton with the characters in '"*'
Add "'" to the list
Add the characters in ':/!?+' to the list
The 'callback' function for everything in this list is onClickChar
Append this list to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with
the standard height
a text value None
an icon taken from the graphic 'back.png'
the 'callback' function is onClickBack
Append the KeyboardButton to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create an empty list of widgets
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'letters.png'
the 'callback' function is onClickLetters
Append the KeyboardButton to the widget list
Append a spacer whose width is 5% of the standard height
Create a KeyboardButton with the character ','
The 'callback' function is onClickChar
Append this button to the widget list
Create a KeyboardButton with
a width 300% of the standard height
the standard height
a text value None
an icon taken from the graphic 'space.png'
the 'callback' function is onClickSpace
Create a KeyboardButton with the character '.'
The 'callback' function is onClickChar
Append this button to the widget list
Append a spacer whose width is 5% of the standard height
Create a list of KeyboardButton with the characters in '✕§¶°'
The 'callback' function is onClickChar
Append this list to the widget list
Create a KeyboardButton with
a width 150% of the standard height
the standard height
a text value None
an icon taken from the graphic 'enter.png'
the 'callback' function is onClickEnter
Append the KeyboardButton to the widget list
Create a KeyboardRow with the widget list
Add the KeyboardRow to the row list
Create a KeyboardView with the row list
Add the KeyboardView to this VirtualKeyboard
#---------------------------------------------------------------
This is a test program:
Create a window 600 pixels wide and 350 high with background #ccc.
Compute a standard button height value, as 15% of the window height.
Create a VirtualKeyboard, giving it the computed height
Add the VirtualKeyboard to the window
Show the window
Note: QGraphicsDropShadowEffect is part of QtWidgets, not QtCore
And here are the control key graphics:
Top comments (0)