26092

in Jython, is there a Pythonesque way of submitting a method to the EDT?

Question:

In Python one is used to doing

def runTaskInNonEDT(): pass tRunTask = threading.Thread( target = runTaskInNonEDT ) tRunTask.start()

In Jython, I find that if I want to submit a method to the EDT I have to go

def makeRunnableClass(): class RunnableClass( Runnable ): def run( rSelf ): pass return RunnableClass SwingUtilities.invokeAndWait( makeRunnableClass()() )

obviously you then have all the attendant questions about passing parameters, etc. I was just wondering if there might be a snappier, more Pythonesque way of submitting a method to the EDT?

<em><strong>@lvc</strong></em>

thanks... yes in fact I get that... in fact the idiom

def makeSthgClass(): class SthgClass(): pass return SthgClass

is one I use habitually just to stop cluttering up the namespace with one-shot subclassed instances' classnames.

I have in fact got sthg to lighten the task

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's nothing satisfyingly Pythonic about it.

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 # i.e. 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 # i.e. 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 args ... and this method then ends up being run in the EDT, using the args in question. No Runnables have to be created...

Of course the other possibility is to subclass from SwingWorker... then you wouldn't have this slightly troubling "double-queue" arrangement (i.e. WorkerThread Queue, and the EDT's own queue, which delivers to process())... but then you have to have a rather inelegant loop (using sleep()) in doInBackground...

Would be interested in people's views

Answer1:

The major thing to realise is that SwingUtilities.invokeAndWait expects an instance of a single-method interface because Java doesn't have first-class functions. That bit isn't avoidable without using something other than SwingUtilities, with a more Pythonic interface, for this functionality.

If your heart is set on using that particular API, you can still avoid having the wrapper function. Just do:

class RunnableClass(Runnable): def run(self): pass SwingUtilities.invokeAndWait(RunnableClass())

The only reason for using the wrapper function is to be able to use pass a function in to invoke in run using closures; you can still do this by passing the function into RunnableClass.__init__ and storing it:

class RunnableClass(Runnable): def __init__(self, func): self._func = func def run(self): self._func()

Note that func <em>shouldn't</em> take self as a first parameter - since its an attribute on the instance rather than on the class, it doesn't get treated as a method.

Per your edit - the point of passing func into RunnableClass.__init__ is that it doesn't need to be a one-shot subclass anymore - you don't need one subclass of Runnable for every func you're going to run, just one instance of RunnableClass. The <em>class itself</em> is a generic adapter from the Python idiom to the Java one, so you don't need a function around it to do the same job.

This means your runToMessageTree can look like this:

def runToMessageTree(self, method, *args, **kwargs): if SwingUtilities.isEventDispatchThread(): method(*args, **kwargs) else: SwingUtilities.invokeAndWait(RunnableClass(method, *args, **kwargs))

Recommend

  • Getting Applets OutputStream throws an exception: What is wrong?
  • Pressing Ctrl+A is changing the Font in JTextPane
  • Buttons are being hidden by background image
  • Java scroll JScrollPane with JPanel within to bottom
  • EventQueue.invokeLater vrs SwingUtilities.invokeLater
  • Place buttons and text on new line and move them to the bottom of the screen in java
  • in Jython, is there a Pythonesque way of submitting a method to the EDT?
  • javafx in swing exception “Toolkit not initialized”
  • Thread and JLabel in Swing- Not working properly
  • How to store text from JOptionPane into text file
  • Input Verifier effect not work by click, just work by tab button
  • Is there a way in Ant (using Groovy?) to post info to an http URL and then parse the response?
  • A simple way to setting a bufferedImage into a single colored pixel without placing a image into it?
  • JPanel gets paintComponent gets called when child is entered
  • JavaFX Self-Contained Application Packaging for Mac without JRE
  • Validate an XML against a Schematron using PHP
  • JFrame maximized to screen size with Dimension
  • how to wait for a spawned thread to finish in python?
  • How to compose functions that return Validation?
  • How to make BMP fills the JPanel
  • `case` that refines arguments
  • Can i save result of a sql query in a property directly in ant
  • Java Console JPanel
  • Repainting Graphics Issue
  • Skip over levels of a directory when importing python package
  • How to create vertical TitledBorder in JPanel (javax swing)
  • Primitive int value conversion?
  • Display java JPanel in a JFrame
  • How to Cache Real-time Data?
  • Spring Data JPA custom method causing PropertyReferenceException
  • Possible to stop flickering java tooltip in heavyweight mode?
  • Checking variable from a different class in C#