Glyph view not updating when using threading.thread

I experience unexpected behavior with treads in Glyphs 3.0.3 (3091):
Paths drawn by a thread ARE NOT updated in the glyph view.
Paths drawn by clicking a vanilla button ARE updated.
Both use the same method: drawPath.

import threading, time, random
from vanilla import *

class Controller(object):
	def __init__(self):
		self.w = Window((200, 50))
		self.controller = BackgroundTask(self.draw)
		self.w.bind('close', self.windowCloseCallback)
		self.w.button = Button((20, 20, -20, -20), "draw path", sizeStyle="small", callback=self.drawPath)
		self.w.open()

	def draw(self, time):
		print (time)
		self.drawPath(None)

	def drawPath(self, notification):
		newPath = GSPath()
		for i in range(5):
			node = GSNode()
			node.type = GSLINE
			node.position = (random.randint(0,500), random.randint(0,500))
			newPath.nodes.append( node )
		Layer.paths.append(newPath)
		print ('Drawing path. Do you see me?')
		
	def windowCloseCallback(self, sender):
		self.controller.killTask()

class BackgroundTask(object):
	def __init__(self, callback):
		self.kill = False
		self.thread = threading.Thread(target=self.run, args=(callback,))
		self.thread.start()

	def killTask(self):
		self.kill = True

	def run(self, callback):
		while(self.kill != True):
			if int(round(time.time() * 100000)) % 100000 == 0:
				callback(time.time())

task = Controller()

Updates to the UI need to be triggered from the main thread. Triggering it from a background thread will be ignored (previous versions of macOS would do crazy things in those cases).

I could add the redirect to the main thread but I first like to know what you are trying to accomplish. Because what you are doing is dangerous (the user and the script can do things at the same time) and will mess up the undo.

I want to hook up an additional input device that has its own API. I use the additional thread to connect to this API, listen for input and send the data to Glyphs. Everything runs fluently… with the only exception that the update of the glyph view only happens if some input or change is triggered from the main thread. I am also surprised that the b/w preview at the bottom of the glyph view gets updated correctly, while the large glyph view does not.

With the current implementation it is the easiest if you trigger the redraw yourself:

	def drawPath(self, notification):
		newPath = GSPath()
		for i in range(5):
			node = GSNode()
			node.type = GSLINE
			node.position = (random.randint(0,500), random.randint(0,500))
			newPath.nodes.append( node )
		Layer.paths.append(newPath)
		Font.currentTab.performSelectorOnMainThread_withObject_waitUntilDone_("redraw", None, False)
		print ('Drawing path. Do you see me?')
1 Like

Oh, yes. This works great!
Thanks so much for the quick help.