Well, I never thought I’d be blogging about GUIs (Graphical User Interfaces), at least not in the context of my moon clock. After all, a clock is the original and best GUI of them all!
But I want to be able to check that the clock hands are showing the times that the software thinks they should be showing. The clock starts automatically in the background on power up and by default any output that it writes will disappear. You can redirect it to stdout, which will display in a terminal window, or redirect it to a file, but this is a scrolling display that isn’t easy to read.
I would like the current settings to be displayed in a nice, clear, fixed window.
Python doesn’t have a ‘windows’ display built in but there is a big choice of GUI libraries that give a graphical interface. The most popular seems to be tkinter, which is a Python wrapper for a GUI called Tcl. Like most GUIs, tkinter is event-driven. It runs in an infinite loop, and when the user does something, such as clicking a button, this creates an ‘event’. This causes tkinter to transfer control to the relevant function to deal with the button click, and when this has completed, it then returns to the infinite loop until another event occurs. This makes sense for most apps, as it means that control always returns to the user via the GUI.
I knocked together a few lines of code using Tkinter, but found that it would not display unless I called the infinite loop or the update function, and once in the loop, execution of the code would not proceed further. Basically, it wanted user input. Since the clock is driven by timer events rather than an external user, this might not matter – as long as tkinter passed control to the timer event – but on the other hand it might not work. (The documentation doesn’t seem to address this point.) Even if it could work, it is quite involved and would need some changes to my own waiting loop.
I searched around for a GUI that is not event driven and came across easyGUI. This uses the Tk/Tcl drivers but is not event-driven. Each GUI feature is a separate function. However, after displaying the window relevant to the function, again it waits for user input, which it will never get, so it’s no better than Tkinter.
Suddenly, the light dawned. My question about getting a simple text output in a window has been asked on a lot of forums, and all the advice is to use a GUI. But this is wrong! You only need a graphics routine that can draw on the screen in a window. I searched around for something very simple, and came across csc161graphics. This uses a library called graphics.py written by John Zelle. It is said to be a wrapper for Tkinter! But it is for creating things on-screen, not a GUI. I downloaded and installed it using the following command.
sudo pip3 install –upgrade http://bit.ly/csc161graphics
csc161graphics is actually a computer course in the USA, so it has helpful tutorial material. I only want to create a Text Box with some writing in it, that will stay on-screen, and can be updated.
This was very easy to do. After importing the graphics library, you call a function to open the window as follows:
from graphics import * # Create window with title and dimensions win = GraphWin('Moon Clock', 600, 200) # Set the background colour fill of the window win.setBackground('turquoise4') # Compose the text to display label = Text(Point(300,100),'The clock is now up and running') # Set the text colour label.setTextColor('yellow') # Set the text size label.setSize(12) # Write the text into the window label.draw(win)
I’m only showing some dummy text ‘The clock is now up and running’. The hardest bit was to format the real numerical information that I want to show in the window. The spacing still isn’t perfect – it is difficult to get this right with a proportional-spaced font – but you will notice that the numbers are displayed in the format you’d expect. I would have to cover that in another post.
Of course, now I have text display using a graphics interface, it is tempting to consider making a replica graphical clock display too!