I recently discovered Beeware/Toga
and I'm considering switching to it: it's so much nicer than Tkinter
and it seems to be more straighforward than wxPython
, and faster both at dev and run time. So I tried to build a few toy apps, one of them being a look-alike of SimpleSudoku.
The UI is simple: it shows the value in a solved cell, or the remaining "candidates" in a cell that's still unsolved. Then you select a cell by clicking it or moving to it with the arrow keys, and type the value you want to insert, or Alt-<value>
to remove a candidate value. There are a few more possibilities but let's ignore them for the moment.
The following code is a first attempt to build a preview (tested on Windows):
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
class SSClone(toga.App):
def startup(self):
main_box = toga.Box(style=Pack(direction=COLUMN, padding=5))
self.tiles = []
self.values = '123456789'
self.size = len(self.values)
label_text = ' '.join(self.values)
tile_size = 40
vbox = toga.Box(style=Pack(direction=COLUMN, padding=0, background_color='grey'))
for i,r in enumerate(range(self.size)):
hbox = toga.Box(style=Pack(direction=ROW, padding=(2,0,0,0), background_color='lightgrey'))
for c in range(self.size-1):
tile = toga.Label(label_text, style=Pack(padding=2, width=tile_size, height=tile_size, font_family='monospace', font_size=7))
hbox.add(tile)
self.tiles.append(tile)
tile = toga.Label(f' {self.values[i]}', style=Pack(padding=2, width=tile_size, height=tile_size, font_family='monospace', font_size=15, alignment='center', font_weight='bold', background_color='aqua'))
hbox.add(tile)
self.tiles.append(tile)
vbox.add(hbox)
main_box.add(vbox)
self.tiles[0].style.background_color='yellow'
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
I have used Label
here, but one may also think of TextInput
with readonly=True
, Canvas
(ouch!), or even a Button
for each candidate (ouch!). All of these alternatives have disadvantages, but do at least solve some issues. What I would need, however, is a way to capture all keystrokes and mouse clicks at the application level. In Tkinter
or wxPython
I would simply bind the relevant events
, respectively to the app
or to a panel
, but I can't find anything similar in Toga
. Can someone help?
Thanks
For games, or other apps where the exact appearance matters, I think you'll probably need to use Canvas
to get what you want. We've made some significant improvements to this in the current development version of Toga, which should be released within the next couple of weeks.
Canvas has handlers for mouse events, but not for key presses. However, Toga does have an application-level key press handler in the Command
API. There is some incomplete documentation for this (1, 2), which we'll improve in the next version. Meanwhile, you can find more example code in the example apps.