{"id":386,"date":"2023-02-04T19:26:17","date_gmt":"2023-02-04T19:26:17","guid":{"rendered":"https:\/\/www.jeskevic.info\/?p=386"},"modified":"2023-02-04T19:28:43","modified_gmt":"2023-02-04T19:28:43","slug":"python-tkinter-co","status":"publish","type":"post","link":"https:\/\/www.jeskevic.info\/?p=386","title":{"rendered":"python, tkinter &#038; co"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Last two weeks evenings I spent programming in python. No, let&#8217;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&#8217;t work.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So, the last two weeks evenings I spent programming in python. Writing new, better, feature-rich, app. And fixing the most annoying bugs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On this way, I learned some new things, and want to document these learnings.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p class=\"wp-block-paragraph\">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 &#8211; the old pyinstaller generated .exe with a size &gt;300Mb. So, after updated everything, the resulting .exe was only 25Mb.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I quickly programmed a simple flask server to mock the oscilloscope features, it helped a lot to debug features.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After many hundreds of lines of code, I was ready to test first prototype on the lab PC. And first fail &#8211; &#8220;no DLL, fatal error, &#8230;&#8221; A lot of googling, some misleading links, and the root of the problem &#8211; python 3.11 doesn&#8217;t run on Windows 7.  Installation of python 3.7.9 solved the problem.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And I learned a bit about virtual environments, I should&#8217;ve done it a long time ago!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One of the problems for each widget, for any event you can bind only one command. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, I wanted for Button &lt;Enter&gt; event to display the tooltip and highlight the corresponding entry fields.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Of course, if you need two commands, you can use bind one function, which calls two others. I wanted a more elegant solution.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"false\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Events():\n    '''events.bind(widget, event, command) #repeat as much as you need'''\n    def __init__(self):\n        self._events = {}\n    def bind(self, widget, event, command):\n        if not widget in self._events:\n            self._events[widget] = {}\n        if not event in self._events[widget]:\n            self._events[widget][event] = {command}\n        else:\n            self._events[widget][event].add(command)\n        \n        widget.bind(event, lambda *args: self.run(widget, event, *args))\n    def run(self, widget, event, *args):\n        for cmd in self._events[widget][event]:\n            cmd(*args)\n\nevents = Events()\n\n#########################\n\n# instead of:\nwidget.bind('&lt;Event>', command)\n# use:\nevents.bind(widget, '&lt;Event>', command1)\nevents.bind(widget, '&lt;Event>', command2)<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And I found an amazing ascii-text generator:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/patorjk.com\/software\/taag\/\">https:\/\/patorjk.com\/software\/taag\/<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"393\" height=\"66\" data-src=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2023\/02\/image.png\" alt=\"\" class=\"wp-image-387 lazyload\" data-srcset=\"https:\/\/www.jeskevic.info\/wp-content\/uploads\/2023\/02\/image.png 393w, https:\/\/www.jeskevic.info\/wp-content\/uploads\/2023\/02\/image-300x50.png 300w\" data-sizes=\"(max-width: 393px) 100vw, 393px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 393px; --smush-placeholder-aspect-ratio: 393\/66;\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">It has 317 different font styles! I spent way too much time selecting the best one \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last two weeks evenings I spent programming in python. No, let&#8217;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&#8217;t work. So, the last two weeks &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.jeskevic.info\/?p=386\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;python, tkinter &#038; co&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[55],"tags":[74,75,49,45],"class_list":["post-386","post","type-post","status-publish","format-standard","hentry","category-programming","tag-ascii","tag-multiple-commands-on-one-event","tag-python","tag-tkinter","entry"],"_links":{"self":[{"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/posts\/386","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=386"}],"version-history":[{"count":14,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/posts\/386\/revisions"}],"predecessor-version":[{"id":401,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=\/wp\/v2\/posts\/386\/revisions\/401"}],"wp:attachment":[{"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=386"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=386"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jeskevic.info\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=386"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}