【问题标题】:wxPython: Setting focus with a wx.PostEvent does not work if destroying a modal dialogwxPython:如果破坏模式对话框,使用 wx.PostEvent 设置焦点不起作用
【发布时间】:2014-12-11 13:32:12
【问题描述】:

在模式对话框被销毁后,我无法设置按钮的焦点。

我可以调用来销毁模态对话框或阻止它成为模态然后销毁它吗?

当 wx.PostEvent 触发一个事件时,它会强制在模式对话框上进行 Destroy,但是据我了解,它不会立即被销毁,这意味着当我执行 SetFocus() 时按钮仍然被禁用。

import wx
import wx.lib.newevent
from threading import Thread
import time
processFinishes, EVT_PROCESS_FINISHES = wx.lib.newevent.NewEvent()

class Dummy(Thread):
    def __init__(self, arg):
        super(Dummy, self).__init__()
        self.arg = arg

    def run(self):
        time.sleep(15)
        print "Posting"
        wx.PostEvent(self.arg , processFinishes(result=(None)))


class MyRegion(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent)
        self.button = wx.Button(self, label="Click me!")
        self.mybutton2 = wx.Button(self, label="I should have focus!!!")
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.button, 0, wx.ALL)
        sizer.Add(self.mybutton2, 0, wx.ALL)
        self.SetSizerAndFit(sizer)
        self.Bind(wx.EVT_BUTTON, self.OnButton)
        self.Bind(EVT_PROCESS_FINISHES, self.OnFinish)
        self.progress = None
        self.t = Dummy(self)

    def OnButton(self, event):
        self.progress = wx.ProgressDialog("Processing",
                                          "Please wait while the processing finishes.")
        self.progress.Pulse()
        self.progress.ShowModal()
        self.t.start()

    def OnFinish(self, _event):
        print "destroyed"
        self.progress.Destroy()
        print "now setting foucs"
        self.mybutton2.SetFocus()

if __name__ == "__main__":
    app = wx.App()
    frame = MyRegion(None)
    frame.Show()
    app.MainLoop()

编辑:

当试图阻止进度对话框成为模态时,以下代码给出错误,表明 ProgressDialog 不是模态的,而它显然是:

    .....
    def OnButton(self, event):
        # wx.ProgressDialog can also be created with
        # style=wx.wx.PD_APP_MODAL which cannot be made non-modal later on
        # i.e. EndModal() does not work
        self.progress = wx.ProgressDialog("Processing",
                                          "Please wait while the processing finishes.")
        self.progress.Pulse()
        self.progress.ShowModal()
        self.t.start()

    def OnFinish(self, _event):
        print "destroyed"
        # By changing this line
        # wx complains indicating that the progress dialog
        # is not modal whereas a ShowModal was used

        self.progress.EndModal(0) # -> produces a "wx._core.PyAssertionError: C++ assertion "IsModal()" failed at ..\..\src\msw\dialog.cpp(221) in wxDialog::EndModal(): EndModal() called for non modal dialog"
        print "now setting foucs"
        self.mybutton2.SetFocus()

【问题讨论】:

    标签: wxpython wxwidgets


    【解决方案1】:

    模态对话框在ShowModal() 返回时重新启用所有内容,因此只需直接从OnButton() 调用OnFinish()

    但是请注意,wxProgressDialog 根本不是一个模态对话框(如果它是你将无法调用 Update() 的话,那将毫无用处!),所以在这种情况下你应该直接销毁当你完成它时它(或使用wxPD_AUTO_HIDE 风格告诉它在达到最大进度值时自行消失)。

    【讨论】:

    • 但问题是说 OnButton 和 OnFinish 之间的计算是一项长时间运行的任务,并且 GUI 会由于该计算而阻塞,如何将计算的开始和计算的结束联系起来与 ShowModal() 及其回报? P.s 这是我看到的问题的一个虚拟示例
    • 好的,我明白了。你根本不应该在wxProgressDialog 上使用ShowModal(),它不应该这样使用,请参阅任何使用示例。
    • 但无论我使用什么对话框,我都会遇到同样的问题。如果我在之前和之后使用 MessageBox 或任何其他形式的对话框,那么之前和之后都会导致问题。
    • 通常你不会,一个模态对话框会一直显示,直到它被用户关闭。但是如果你真的需要,你可以在上面调用EndModal(),重要的是要理解你必须从一些事件处理程序中执行它,因为你的显示对话框的代码在它被解除之前不会获得控制权。
    • 是的,从 OO 的角度来看,这不是一个很好的设计,因为您确实不能在此类上调用 ShowModal()。但在实践中这几乎不是问题,因为您不需要显示 progress 对话框,该对话框应该在显示时更新,无论如何在模态上都没有任何意义。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多