3

メインのGUIアプリからスレッドを実行して、GUIを存続させながらシリアルポートの送受信を行う方法を学ぼうとしています。私の最高のグーグルの試みは、いくつかの例を提供するhttp://wiki.wxpython.org/LongRunningTasksのwxpythonwikiにたどり着きました。私は最初の例を学ぶことに決めました。特定のボタンが選択されたときにワーカースレッドを開始することです。

カスタムイベント定義を理解するのに問題があります。

def EVT_RESULT(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_RESULT_ID, func)

class ResultEvent(wx.PyEvent):
    """Simple event to carry arbitrary result data."""
    def __init__(self, data):
        """Init Result Event."""
        wx.PyEvent.__init__(self)
        self.SetEventType(EVT_RESULT_ID)
        self.data = data

主に

def EVT_RESULT(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_RESULT_ID, func)

EVT_RESULTは、両方のクラスで呼び出し可能にするために、クラスの外部に配置されていると思います(グローバルにしますか?)

そして..メインGUIアプリは、以下を介してスレッドの進行状況を監視します。

# Set up event handler for any worker thread results
EVT_RESULT(self,self.OnResult)

また、多くの例で、ライターが

from wx import *

彼らは単に物事をバインドします

EVT_SOME_NEW_EVENT(self, self.handler)

とは対照的に

wx.Bind(EVT_SOME_NEW_EVENT, self.handler)

それは私がそれをより速く理解するのを助けません。ありがとう、

4

3 に答える 3

4

これは、カスタムイベントを定義する古いスタイルです。詳細については、移行ガイドを参照してください。

移行ガイドからの抜粋:

独自のカスタムイベントタイプとEVT_*関数を作成し、それらを上記のBindメソッドで使用できるようにする場合は、EVT_*をwx.PyEventBinder関数ではなくのインスタンスに変更する必要があります。たとえば、以前は次のようなものがありました。

myCustomEventType = wxNewEventType()
def EVT_MY_CUSTOM_EVENT(win, id, func):
    win.Connect(id, -1, myCustomEventType, func)

次のように変更します。

myCustomEventType = wx.NewEventType()
EVT_MY_CUSTOM_EVENT = wx.PyEventBinder(myCustomEventType, 1)

これは、あなたが探しているものを正確に実行するいくつかのサンプルプログラムで私が作成した別の投稿です。

于 2010-02-27T00:39:22.803 に答える
2

次のようなイベントを定義できます。

from wx.lib.newevent import NewEvent

ResultEvent, EVT_RESULT = NewEvent()

次のようにイベントを投稿します。

wx.PostEvent(handler, ResultEvent(data=data))

次のようにバインドします。

def OnResult(event):
    event.data

handler.Bind(EVT_RESULT, OnResult)

ただし、使用できるメインスレッドの非メインスレッドから呼び出す必要がある場合はwx.CallAfterここに例を示します。

カスタムイベントは、誰が何を担当するかをハードコーディングしたくない場合に役立ちます(オブザーバーデザインパターンを参照)。たとえば、メインウィンドウといくつかの子ウィンドウがあるとします。メインウィンドウで特定の変更が発生したときに、子ウィンドウの一部を更新する必要があるとします。このような場合、メインウィンドウはこれらの子ウィンドウを直接更新できますが、より洗練されたアプローチは、カスタムイベントを定義し、メインウィンドウにそれを投稿させることです(誰がそれに反応する必要があるかを気にする必要はありません)。次に、そのイベントに反応する必要のある子は、それにバインドすることで自分でそれを行うことができます(複数ある場合はevent.Skip()、バインドされたすべてのメソッドが呼び出されるように呼び出すことが重要です)。

于 2010-02-27T09:41:54.107 に答える
0

カスタムイベントではなく、Pythonスレッドとキューを使用することをお勧めします。大きなファイルをロードするwxPythonプログラム(OpenSTV )があり、ロード中にGUIがフリーズしました。フリーズを防ぐために、スレッドをディスパッチしてファイルをロードし、キューを使用してGUIとスレッドの間で通信します(たとえば、GUIに例外を通信するため)。

  def loadBallots(self):
    self.dirtyBallots = Ballots()
    self.dirtyBallots.exceptionQueue = Queue(1)
    loadThread = Thread(target=self.dirtyBallots.loadUnknown, args=(self.filename,))
    loadThread.start()

    # Display a progress dialog
    dlg = wx.ProgressDialog(\
      "Loading ballots",
      "Loading ballots from %s\nNumber of ballots: %d" % 
      (os.path.basename(self.filename), self.dirtyBallots.numBallots),
      parent=self.frame, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME
    )
    while loadThread.isAlive():
      sleep(0.1)
      dlg.Pulse("Loading ballots from %s\nNumber of ballots: %d" %
                (os.path.basename(self.filename), self.dirtyBallots.numBallots))
    dlg.Destroy()

if not self.dirtyBallots.exceptionQueue.empty():
  raise RuntimeError(self.dirtyBallots.exceptionQueue.get())
于 2010-03-01T21:33:30.583 に答える