python, tkinter & co

Last two weeks evenings I spent programming in python. No, let’s start from the beginning: some weeks ago I conducted some tests with an oscilloscope, and we have a lovely old app to copy and annotate screenshots. But this app has some annoying bugs, and some functions simply don’t work.

So, the last two weeks evenings I spent programming in python. Writing new, better, feature-rich, app. And fixing the most annoying bugs.

On this way, I learned some new things, and want to document these learnings.

I started cleaning up my zoo from different and outdated python versions and packets, installing fresh Visual Studio Code and python 3.11.1, and installing fresh packets. One of the reasons – the old pyinstaller generated .exe with a size >300Mb. So, after updated everything, the resulting .exe was only 25Mb.

I quickly programmed a simple flask server to mock the oscilloscope features, it helped a lot to debug features.

After many hundreds of lines of code, I was ready to test first prototype on the lab PC. And first fail – “no DLL, fatal error, …” A lot of googling, some misleading links, and the root of the problem – python 3.11 doesn’t run on Windows 7. Installation of python 3.7.9 solved the problem.

And I learned a bit about virtual environments, I should’ve done it a long time ago!

One of the problems for each widget, for any event you can bind only one command.

For example, I wanted for Button <Enter> event to display the tooltip and highlight the corresponding entry fields.

Of course, if you need two commands, you can use bind one function, which calls two others. I wanted a more elegant solution.

class Events():
    '''events.bind(widget, event, command) #repeat as much as you need'''
    def __init__(self):
        self._events = {}
    def bind(self, widget, event, command):
        if not widget in self._events:
            self._events[widget] = {}
        if not event in self._events[widget]:
            self._events[widget][event] = {command}
        else:
            self._events[widget][event].add(command)
        
        widget.bind(event, lambda *args: self.run(widget, event, *args))
    def run(self, widget, event, *args):
        for cmd in self._events[widget][event]:
            cmd(*args)

events = Events()

#########################

# instead of:
widget.bind('<Event>', command)
# use:
events.bind(widget, '<Event>', command1)
events.bind(widget, '<Event>', command2)

This class creates dict of a widget, with dicts of a assigned events, with sets of a assigned commands; and binds a lambda for function, to iterate through the commands. Simple and elegant.

And I found an amazing ascii-text generator:

https://patorjk.com/software/taag/

It has 317 different font styles! I spent way too much time selecting the best one 🙂

Join the Conversation

1 Comment

Leave a comment

Your email address will not be published. Required fields are marked *