在Jython中,是否有Pythonesque方式将方法提交给EDT? [英] in Jython, is there a Pythonesque way of submitting a method to the EDT?

查看:93
本文介绍了在Jython中,是否有Pythonesque方式将方法提交给EDT?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Python中,一种习惯是

In Python one is used to doing

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

在Jython中,我发现如果要向EDT提交方法,我必须走

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()() )

很显然,您接下来会遇到所有与传递参数有关的问题,等等. 我只是想知道是否可能有一种更简单,更Python化的方法向EDT提交方法?

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?

@lvc

@lvc

谢谢...是的,事实上我明白了...实际上,这是成语

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()() )

所以你可以去

def doSthg():
  pass
self.runToMessageTree( doSthg )

...但是没有令人满意的Pythonic.

... but there's nothing satisfyingly Pythonic about it.

稍后:

  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是一个非常简单的经典python习语:

Ẁ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

,因此您提交了一个方法,后跟可选的args ...,然后该方法最终使用有问题的args在EDT中运行.无需创建Runnable ...

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...

当然,另一种可能性是从SwingWorker继承子类...那么您将不会有这种稍微麻烦的双队列"安排(即,WorkerThread队列和EDT自己的队列,该队列传递给process()). ..但是然后您必须在doInBackground中有一个相当不优雅的循环(使用sleep())...

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...

会对人们的观点感兴趣

推荐答案

要实现的主要事情是SwingUtilities.invokeAndWait需要一个单方法接口的实例,因为Java没有一流的功能.如果不使用SwingUtilities以外的其他东西(具有更多Pythonic界面)来实现此功能,则无法避免这一点.

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.

如果您愿意使用特定的API,则仍然可以避免使用包装器功能.只要做:

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())

使用包装函数的唯一原因是能够使用传递函数使用闭包在run中调用;您仍然可以通过将函数传递到RunnableClass.__init__并将其存储来完成此操作:

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()

请注意,func 不应self作为第一个参数-由于它是实例而不是类的属性,因此不会被视为方法.

Note that func shouldn't 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.

根据您的编辑-将func传递到RunnableClass.__init__的意义在于,它不再是一次性的子类-您不需要为每个函子使用Runnable的一个子类.重新运行,只是RunnableClass的一个实例. 类本身是从Python惯用语到Java惯用语的通用适配器,因此您不需要围绕它的函数即可完成相同的工作.

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 class itself 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.

这意味着您的runToMessageTree可能如下所示:

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))

这篇关于在Jython中,是否有Pythonesque方式将方法提交给EDT?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆