In python is used to execute
def runTaskInNonEDT(): pass tRunTask = threading.Thread( target = runTaskInNonEDT ) tRunTask.start()
In Jython, I found that if I want to send a method to EDT, I need to go
def makeRunnableClass(): class RunnableClass( Runnable ): def run( rSelf ): pass return RunnableClass SwingUtilities.invokeAndWait( makeRunnableClass()() )
obviously you have all the related questions about passing parameters, etc. I'm just wondering if there could be a faster, more Pythoneque way to send a method to EDT?
@lvc
thank you ... yes I really understand that ... really an idiom
def makeSthgClass(): class SthgClass(): pass return SthgClass
is the one that I use, as a rule, to stop cluttering the namespace with the cool class names of the subclass.
I really got sthg to make the task easier
def runToMessageTree( self, method, *args, **kvargs ): if SwingUtilities.isEventDispatchThread(): method( *args, **kvargs ) else: def makeRunnableClass(): class RunnableClass( Runnable ): def run( self ): method( *args, **kvargs ) return RunnableClass SwingUtilities.invokeAndWait( makeRunnableClass()() )
so you can go
def doSthg(): pass self.runToMessageTree( doSthg )
... but there is nothing satisfactory to Pythonic about this.
later:
class EDTWorkerThread( WorkerThread ): def __init__( ewt_self, name ): super( EDTWorkerThread, ewt_self ).__init__( name ) class EDTWorker( SwingWorker ): def doInBackground(self ): check_event_thread( False ) while True: method_call_elements = ewt_self.input_queue.get() if method_call_elements is None: # "poison pill" break self.super__publish( [ method_call_elements ]) ewt_self.input_queue.task_done() return def process( self, chunks ): check_event_thread( True ) for chunk in chunks: assert type( chunk ) is list assert chunk # ie must have at least one element! # check that first item is callable assert hasattr( chunk[ 0 ], "__call__" ) method_call_elements = chunk method_args = method_call_elements[ 1 : ] method_call_elements[ 0 ]( *method_args ) ewt_self.input_queue.task_done() ewt_self.swing_worker = EDTWorker() def run( self ): self.swing_worker.execute()
ẀorkerThread is a very simple classic python idiom:
class WorkerThread( threading.Thread ): def __init__( self, *args, **kvargs ): threading.Thread.__init__( self, *args, **kvargs ) self.input_queue = Queue() def send( self, item ): assert type( item ) is list assert item # ie must have at least one element! # check that first item is callable assert hasattr( item[ 0 ], "__call__" ) self.input_queue.put( item ) def close( self ): self.input_queue.put( None ) self.input_queue.join() def run( self ): while True: method_call_elements = self.input_queue.get() if method_call_elements is None: # "poison pill" break method_args = method_call_elements[ 1 : ] method_call_elements[ 0 ]( *method_args ) self.input_queue.task_done() self.input_queue.task_done() return
so you submit a method followed by optional arguments ... and this method then runs in EDT using the appropriate arguments. No runnables should be created ...
Of course, another possibility is to subclass from SwingWorker ... then you would not have this slightly disturbing "double queue" (ie WorkerThread Queue and your own EDT queue that delivers process ()) ... but then you have there should be a rather inelegant loop (using sleep ()) in doInBackground ...
People watching will be interesting