【问题标题】:How to make a wxFrame behave like a modal wxDialog object如何使 wxFrame 表现得像模态 wxDialog 对象
【发布时间】:2010-10-27 09:04:08
【问题描述】:

是否有可能使 wxFrame 对象的行为类似于模式对话框,因为创建 wxFrame 对象的窗口会停止执行,直到 wxFrame 对象退出?

我正在处理small game 并遇到了以下问题。我有一个托管主应用程序(战略部分)的主程序窗口。有时,我需要将控制权转移到第二个窗口以解决部分游戏(战术部分)。在第二个窗口中,我希望第一个窗口中的处理停止并等待第二个窗口中完成的工作。

通常模式对话框可以解决问题,但我希望新窗口具有一些我似乎无法通过 wxDialog 获得的功能,即底部的状态栏以及调整大小/最大化/最小化的能力窗口(这应该是可能的,但不起作用,请参阅这个问题How to get the minimize and maximize buttons to appear on a wxDialog object)。

作为补充说明,我希望第二个窗口的功能需要与主窗口完全分离,因为它最终会被分离到一个单独的程序中。

有人做过这个或者有什么建议吗?

【问题讨论】:

  • 也许现在让第二个窗口成为第二个应用程序,并通过套接字在两个应用程序之间进行通信。这可能会简化您需要使用 wxWidgets 执行的操作。

标签: c++ wxwidgets


【解决方案1】:

“停止执行”窗口实际上并没有什么意义,因为窗口只处理发送给它的事件,例如鼠标、键盘或绘图事件,而忽略它们会使程序看起来挂起。您应该做的是禁用框架中的所有控件,这将使它们变灰并让用户意识到此时无法与之交互。

您也可以完全禁用父框架,而不是禁用其上的所有控件。查看wxWindowDisabler类,构造函数有一个参数表示可以与之交互的窗口,应用程序的所有其他窗口都将被禁用。

如果你以后想要执行一个辅助程序,那么你可以使用 wxExecute() 函数来执行它。

【讨论】:

  • 这实际上是目前所需的行为。第一个窗口中的程序流在继续前进之前应该真正具有第二个窗口中的交互结果。我认为我在这里遇到的是设计问题。我已经成为 Jeff 和 Joel 在他们最近的一个播客中谈论的效果的受害者,即当我还在学习它时必须在一个新框架中进行设计:-)。我来看看 wxWindowDisabler。感谢您的提示。
【解决方案2】:

我也在寻找类似的解决方案,并提出了这个解决方案,创建一个框架,通过执行 frame.MakeModal() 禁用其他窗口,并在显示框架后停止执行启动和事件循环,当框架关闭时退出事件循环,例如我这里是使用 wxpython 的示例,但在 wxwidgets 中应该是类似的。

import wx

class ModalFrame(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, style=wx.DEFAULT_FRAME_STYLE|wx.STAY_ON_TOP)

        btn = wx.Button(self, label="Close me")
        btn.Bind(wx.EVT_BUTTON, self.onClose)
        self.Bind(wx.EVT_CLOSE, self.onClose) # (Allows main window close to work)

    def onClose(self, event):
        self.MakeModal(False) # (Re-enables parent window)
        self.eventLoop.Exit()
        self.Destroy() # (Closes window without recursion errors)

    def ShowModal(self):
        self.MakeModal(True) # (Explicit call to MakeModal)
        self.Show()

        # now to stop execution start a event loop 
        self.eventLoop = wx.EventLoop()
        self.eventLoop.Run()


app = wx.PySimpleApp()
frame = wx.Frame(None, title="Test Modal Frame")
btn = wx.Button(frame, label="Open modal frame")

def onclick(event):
    modalFrame = ModalFrame(frame, "Modal Frame")
    modalFrame.ShowModal()
    print "i will get printed after modal close"

btn.Bind(wx.EVT_BUTTON, onclick)

frame.Show()
app.SetTopWindow(frame)
app.MainLoop()

【讨论】:

    【解决方案3】:

    我花了很长时间才弄明白,但这里有一个从 Anurag 的例子衍生而来的工作示例:

    import wx
    
    class ChildFrame(wx.Frame):
        ''' ChildFrame launched from MainFrame '''
        def __init__(self, parent, id):
            wx.Frame.__init__(self, parent, -1,
                              title=self.__class__.__name__,
                              size=(300,150))
    
            panel = wx.Panel(self, -1)
            closeButton = wx.Button(panel, label="Close Me")
    
            self.Bind(wx.EVT_BUTTON, self.__onClose, id=closeButton.GetId())
            self.Bind(wx.EVT_CLOSE, self.__onClose) # (Allows frame's title-bar close to work)
    
            self.CenterOnParent()
            self.GetParent().Enable(False)
            self.Show(True)
    
            self.__eventLoop = wx.EventLoop()
            self.__eventLoop.Run()
    
        def __onClose(self, event):
            self.GetParent().Enable(True)
            self.__eventLoop.Exit()
            self.Destroy()
    
    class MainFrame(wx.Frame):
        ''' Launches ChildFrame when button is clicked. '''
        def __init__(self, parent, id):
            wx.Frame.__init__(self, parent, id,
                              title=self.__class__.__name__,
                              size=(400, 300))
    
            panel = wx.Panel(self, -1)
            launchButton = wx.Button(panel, label="launch modal window")
    
            self.Bind(wx.EVT_BUTTON, self.__onClick, id=launchButton.GetId())
    
            self.Centre()
            self.Show(True)
    
        def __onClick(self, event):
            dialog = ChildFrame(self, -1)
            print "I am printed by MainFrame and get printed after ChildFrame is closed"
    
    if __name__ == '__main__':
        app = wx.App()    
        frame = MainFrame(None, -1)
        frame.Show()
        app.MainLoop()
    

    【讨论】:

      【解决方案4】:

      不确定这是一个很好的答案,但它确实有效。

      bool WinApp1::OnInit()
      {
        if (!wxApp::OnInit())
          return false;
      
        SettingsDialog dialog(m_settingsData);
        dialog.ShowModal();
      
        return false;
      }
      
      SettingsDialog::SettingsDialog(SettingsData& settingsData)
        : m_settingsData(settingsData)
      {
        SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
      
        wxWindow* parent = nullptr;
        Create(parent, wxID_ANY, "Preferences", wxDefaultPosition, wxDefaultSize,
          wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
      

      WinApp1 窗口永远不会被赋予 wxFrame 并且永远不会绘制。

      【讨论】:

        猜你喜欢
        • 2014-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-09
        • 1970-01-01
        相关资源
        最近更新 更多