wxpython对话框返回带有destroy选项的值

时间:2016-08-17 17:56:59

标签: python multithreading return wxpython

我有一个wxpython对话框(包含在一个返回用户选择的函数调用中),我用来提示用户输入“ok”,“取消”类型的问题。

我有另一个正在运行的线程,允许用户单击按钮并执行紧急停止(也是wxpython)。单击紧急停止按钮时,它会执行一些操作,然后显示自己的用户对话框。

现在,假设弹出消息已经提示用户是/否问题,同时,用户看到了火灾并决定点击紧急停止。

我需要能够销毁当前的对话框问题,并最终显示对象是estop线程的一部分。

我创建了一个代码,在一个线程和另一个线程中启动对话框,发出一个pub.sendMessage(...)来杀死对话框线程,如果它在按下estop按钮时显示在屏幕上。

这很好用。

问题是,我无法从用户对话框中获得结果(是,否,取消等),因为线程永远不会返回以返回用户选择的内容。

如果我在我的代码中添加.join(),我会得到用户响应,但如果发送了pub.sendMessage(...),则对话框不会被销毁。

heres pseudocode:

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

简单,但随着包装函数的实现(这是其他人调用的代码,需要提供简单的函数调用),它显然有点奇怪。但重新实现它可能不会立即飞行

继承了一些代码(两者都是较大类的一部分,这就是为什么自引用存在)

    #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实例以进行下一个对话框。

有什么想法吗? 感谢

2 个答案:

答案 0 :(得分: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()

注意这将关闭其父级为“无”的所有帧和对话框...如果为框架或对话框设置父级,则在其父窗口关闭时将关闭该对话框

答案 1 :(得分:2)

从线程执行GUI不是一个好主意,并且几乎总是会产生意想不到的结果。

为了显示一个线程的消息框,你需要让线程让主线程显示消息框。

使用函数wx.CallAfter

执行此操作