Pages

Friday, 26 April 2019

Three reasons to love guizero

I'm working on a Quiz runner project for my forthcoming book on the micro:bit.

The first version worked, but it was much too complicated and very hard to test.

After weeks of frustration I decided to go back to the drawing board and try a different approach.

The current design is shaping up well. It uses a conventional computer as well as micro-bits, and the program that runs on the big computer needs a Gui.

The micro:bit connected to the computer acts as a radio receiver; the micro:bits for each team transmit a signal when the team wants to answer a question.

The person running the quiz sees that a team is buzzed and asks them for their answer. Then they tell the program whether the answer is right or wrong so the computer can keep score.

The program on the computer needs a Gui. I've played with @codeboom's guizero before, and liked it, so I decided to use it for the project.

It's turned out to be an excellent choice, for several reasons:
  1. guizero has all the features I need for the project without any extra baggage.
  2. The documentation is really good, so it's easy to get started - and easy to carry on!
  3. It's simple to install on the Raspberry Pi, other Linux machines, Windows and OS X.  That's vital for the book I'm writing, since I don't want to restrict the potential audience.
So far I've hit one complication which turned out to be surprisingly easy to solve.

The big computer is connected to one of the micro:bits via a serial USB connection. It needs to read data from the micro:bit. It does that by reading the output from print statements on the micro:bit using pyserial.

The Gui needs to check the serial connection to see if something new needs attention. If you try to do that in a while loop the Gui will stop and eventually crash. That's a general issue with Guis, not a problem that's specific to guizero.

A very quick Google showed me the place in the guizero documentation which describes the problem and the very simple solution.

You put the code than needs to be run periodically in a call back function, and you then call a repeat method on one of the widgets in your application.

Here's some of the application code, showing App creation and the callback function.

...
 

def read():
    line = buffer.readline().strip()
    if len(line) > 0:
        message_queue.append(line)
    if len(message_queue) > 0:
        nm.enable()
        message = message_queue[0]
        text.value = message
    else:
        nm.disable()
        text.clear()
... 
 
app = App("Quiz Runner")
status = Text(app, text=working_on)
nm = PushButton(app, text='Next Message', command=next_message)
all_in_button = PushButton(app, text='All Checked In', command= all_in)
all_in_button.disable()
text = Text(app, text="")
text.repeat(100, read)  # Schedule call to counter() every 100ms
app.display() 

The whole application is a fraction of the size of the earlier version, and much easier to understand. If you're looking for a simple framework to build a Gui in Python, give guizero a try.

And if you'd like to know when the book comes out, follow me - @rareblog - on Twitter!