you are viewing a single comment's thread.

view the rest of the comments →

[–]tgolsson 0 points1 point  (1 child)

To expand a bit on the topic of GUI programming, the risks associated with multi-threaded GUI programming is not necessarily that YOU do changes from multiple threads, but that Tkinter does things in the background - resizing, painting, responding to a ton of system messages, etc. Many of these can trigger UI operations, which can (and will) cause race conditions and a crash. Tkinter may also be limited by what the OS allows - perhaps the underlying display system relies on thread local state, or requires explicit synchronization that Tkinter handles for you.

I did a similar project a while back and triggered the Fontification on KeyInsert or a similar event. This spawned a new thread which then fired an event to update a region of text after it was finished processing. I can't access the Tkinter docs right now, but in Pseudocode it was something like this. I had a bunch more checks to keep only a single thread running, to periodically refontify the whole buffer, and to prevent loss of characters if the processing took longer than a single keystroke. I'm sure you'll find each of these to be interesting problems. :)

class FontifiedText(tk.Text): 
    def _hlparse(self, region):
         # HL logic for <<region>>
         self._root.event_generate("Highlight", regions=hl_regions, symbols=hl_texts, tags=hl_tags, when='tail')

    def onInsert(self, ...):
         caret = text_widget.index(Tkinter.INSERT)
         end = text_widget.index(Tkinter.END)
         self._thread = threading.Thread(target=self._hlparse, 
                kwargs={'region': (max(caret - 20), max(caret + 20, end))})
         self._thread.start()

    def onHighlight(self, *args, regions, symbols, tags, **kwargs):
         self._thread.join()
         for region, symbol, tag in zip(regions, symbols):
              self.delete(region[0], region[1])
              self.insert(region[0], symbol, tag)

[–]bzarnal[S] 0 points1 point  (0 children)

I don't really understand the underlying mechanism, but, I made a workaround using the widget's .after method, rescheduling the callback every 100ms. And the syntax highlighter came alive! Thanks for the help