2016-08-17 17 views
1

私は、ユーザに「ok」、「cancel」型の質問を促すために使用するwxpythonダイアログ(ユーザの選択を返す関数呼び出しでラップする)を持っています。wxpythonダイアログで破棄するオプションを持つ値を返す

私は、ユーザーがボタンをクリックして緊急停止(wxpython)を実行できる別のスレッドを実行しています。非常停止ボタンがクリックされると、何かを実行して、それ自身のユーザーダイアログを表示します。

ここで、ポップアップメッセージがユーザーに「はい/いいえ」という質問を表示し、同時にユーザーが何かを見て緊急停止をクリックすると決めたとします。

現在のダイアログの質問を破棄し、最終的にestopスレッドの一部であるダイアログを表示できるようにする必要があります。

スレッドは1つのスレッドでダイアログを開始するコードを作成し、別のスレッドはestopボタンを押したときに画面に表示されるダイアログスレッドを強制終了するpub.sendMessage(...)を発行します。

これはうまくいきます。

問題は、スレッドがユーザーが選択したものを返すために戻って結合しないため、ユーザーダイアログ(はい、いいえ、キャンセルなど)から結果を取得できません。

私のコードに.join()を追加すると、私はユーザーの応答を得ますが、pub.sendMessage(...)が送信された場合、ダイアログは破棄されません。

HERESに疑似コード:十分なシンプル

1)start up thread to monitor user emergency stop button push 
2)start up test which may contain popup window (custom wxdialog) prompting user for answer 
3)return user selection from dialog if selected 
    OR if user has clicked estop button: destroy current dialog and display new dialog related to estop 

が、ラッパー関数の実装と(これは他の人が呼び出すためのコードであり、簡単な関数呼び出しを提供する必要がある)、その明らかに少し奇妙。しかし、それを再実装することは、今

HERESにいくつかのコード(自己参照がある理由の両方がthatsのように、より大きなクラスの一部である)

#the receiver of the pub message first: 

def DestroyUI(self): 
    print 'into destroy' 
    #self.Hide() 
    #self.Close() 
    self.Destroy() 

#these 2 fuctions are part of a different class 

def closeDialogs(self): 
    print 'into closeDialogs' 
    def destroyUI(): 
     if self.okToKill: 
      print 'closing wx dialogs' 
      pub.sendMessage("destroyUI") 
    ts = threading.Thread(target = destroyUI) 
    ts.start() 
    ts.join() 


def MB(self,blah,blah): 
    def runMB(*args): 
     self.okToKill= True 
     self.response = self.PromptUser(*args) 
     self.okToKill= False 

    tr = threading.Thread(target = runMB,args=(blah,blah)) 
    tr.start() 

    #if i add the join back in, i always return the user values 
    #but the dialog is never destroyed (if needed) before user 
    #clicks. 
    #without the join, the destroy pub send works great, but the 
    #user values are never returned 
    #tr.join() 

    return self.response 

私は、キュー、マルチプールを使用して試してみましたが、問題飛ぶしない場合がありますそれらはq.get()とasync_result().get()の両方がユーザーがクリックするまでブロックしているため、必要に応じて破棄を許可しません。

私の考えているのは、ユーザーがボタンをクリックしたときにユーザー値を取得する方法ですが、現在のダイアログを破棄して代わりに新しい緊急停止ダイアログを表示することもできます(カスタムボタンを使用)。

私はwxPythonのはちょうどにcloseAll():)また、私はタイトル名に基づいてウィンドウを閉じて試してみました

があったが、それは動作しますが、それは次のダイアログのための私のWXインスタンスをアップホースたいです。

アイデア? おかげ

+0

どのような質問ですか?私は理解していません –

+0

ポストのbottonの近くに: "どのように把握するのが大好きですユーザーがボタンをクリックした場合ユーザー値を取得する方法ですが、現在のダイアログを破棄し、代わりに新しい緊急停止ダイアログを表示することができる(カスタムボタン)。 " – pyNewbie

+0

あなたは何かが間違っている(私は思う)...あなたの不完全なコードはあなたの(おそらく間違った)回避策は本当にあなたがやろうとしていることを私に示していないし、あなたの説明は(少なくとも私に)明らかではありません...私はおそらくあなたが何をしようとしているのかを理解するのを助けることができればあなたの質問に答えることができます(もし必要ならば擬似コードを書くこと)(例えば 'wx.CallAfter'を使ってスレッドから直接メソッドを呼び出す)メインスレッドで実行されます))... pubsubはすばらしいですが、スレッド処理を行っているだけなので、必要はありません –

答えて

2

私は本当に私が代わりに取り組む、あなたが求めているものを理解しないので、「私は(wxPythonのがちょうどにcloseAllがあればいいのに):)」

def wx_closeAll(): 
    for win in wx.GetTopLevelWindows(): 
     win.Destroy() 

def closeAllButPrimary(): 
    for win in wx.GetTopLevelWindows(): 
     if win != wx.GetTopLevelWindow(): 
      win.Destroy() 

ノートこれは、すべてのフレームを閉じ、親がNoneのダイアログフレームまたはダイアログの親を設定して、その親ウィンドウが閉じられたときにダイアログが閉じられる場合

+0

このコードに感謝します。これは実際に私がすべてのpubsubと破壊の呼び出しなしで望むものを得ることを可能にしました。これはベテランのwxコーダーのための常識かもしれませんが、私はそれを知らなかったので、うまくいけば他の人にも役立ちます!もう一度ありがとう! – pyNewbie

2

スレッドからGUIを実行することはお勧めできません。

スレッドからメッセージボックスを表示するには、スレッドがメインスレッドにメッセージボックスを表示するように依頼する必要があります。

これを行うには、関数wx.CallAfter

+1

良い答え....私はどういうわけか 'wx.CallAfter'も正しい答えだと考えています。 –

+0

iveはこれ以外はスレッドがうまく動いていますが、単純なwx.CallAfter()を試してみました。まもなく試してみた – pyNewbie

関連する問題