0

Python では、これを行うことに慣れています。

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

Jython では、メソッドを EDT に提出したい場合は、行かなければならないことがわかりました。

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

明らかに、パラメーターの受け渡しなどに関するすべての付随する質問があります。EDT にメソッドを送信するための、よりスマートで Python 風の方法があるのではないかと思っていました。

@lvc

ありがとう...はい、実際に私はそれを理解しています...実際にはイディオム

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

ワンショットのサブクラス化されたインスタンスのクラス名で名前空間を混乱させるのをやめるために、私が習慣的に使用するものです。

私は実際にタスクを軽減するためにsthgを持っています

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は何もありません。

後で:

  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 のイディオムです。

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

したがって、メソッドに続いてオプションの引数を送信すると、このメソッドは問題の引数を使用して EDT で実行されます。Runnables を作成する必要はありません...

もちろん、他の可能性は SwingWorker からサブクラス化することです...そうすれば、この少し面倒な「二重キュー」配置 (つまり、WorkerThread キューと、process() に配信する EDT 独自のキュー) はありません... しかし、次に、doInBackground で (sleep() を使用して) かなり洗練されていないループを作成する必要があります...

人の意見に興味を持つ

4

1 に答える 1

1

SwingUtilities.invokeAndWaitJava にはファーストクラスの関数がないため、単一メソッド インターフェイスのインスタンスが必要であることに注意してください。SwingUtilitiesこのビットは、この機能のために、より Pythonic なインターフェイスを備えた以外のものを使用しないと回避できません。

その特定の API を使用したい場合でも、ラッパー関数を使用しないようにすることができます。ただ行う:

class RunnableClass(Runnable):
    def run(self):
       pass

SwingUtilities.invokeAndWait(RunnableClass())

ラッパー関数を使用する唯一の理由は、runクロージャを使用して呼び出すために関数を渡すことができるようにするためです。RunnableClass.__init__関数を渡して保存することで、これを行うことができます。

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

    def run(self):
       self._func()

func 最初のパラメーターとして使用しないでくださいself。クラスではなくインスタンスの属性であるため、メソッドとして扱われません。

funcあなたの編集によると、渡すポイントは、RunnableClass.__init__もうワンショットのサブクラスである必要がないというRunnableことです。実行する関数ごとにの 1 つのサブクラスは必要ありませんRunnableClassクラス自体は、Python のイディオムから Java のイディオムへの一般的なアダプターであるため、同じ仕事をするためにその周りの関数は必要ありません。

これは、次のrunToMessageTreeように見えることを意味します。

def runToMessageTree(self, method, *args, **kwargs):
    if SwingUtilities.isEventDispatchThread():
       method(*args, **kwargs)
    else:
       SwingUtilities.invokeAndWait(RunnableClass(method, *args, **kwargs))
于 2012-06-17T13:23:41.713 に答える