[英]How to make a wxFrame behave like a modal wxDialog object
是否可以使 wxFrame 对象的行为类似于模式对话框,因为创建 wxFrame 对象的窗口停止执行,直到 wxFrame 对象退出?
我正在开发一个小游戏并遇到了以下问题。 我有一个承载主应用程序(战略部分)的主程序窗口。 有时,我需要将控制权转移到第二个窗口以解决部分游戏(战术部分)。 在第二个窗口中,我希望第一个窗口中的处理停止并等待在第二个窗口中完成的工作完成。
通常,模态对话框可以解决问题,但我希望新窗口具有一些我似乎无法通过 wxDialog 获得的功能,即底部的状态栏以及调整大小/最大化/最小化窗口的能力(这应该是可能的,但不起作用,请参阅此问题如何让最小化和最大化按钮出现在 wxDialog 对象上)。
作为补充说明,我希望第二个窗口的功能需要与主窗口完全分离,因为它最终会被分拆到一个单独的程序中。
有没有人做过这个或有什么建议?
我也在寻找类似的解决方案,并提出了这个解决方案,创建一个框架,通过执行 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()
这花了我很烦人的时间来弄清楚,但这里有一个从 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()
“停止执行”窗口实际上没有意义,因为窗口只处理发送给它的事件,例如鼠标、键盘或绘画事件,而忽略它们会使程序看起来挂起。 您应该做的是禁用框架中的所有控件,这将使它们变灰并使用户意识到此时无法与之交互的事实。
您还可以完全禁用父框架,而不是禁用其上的所有控件。 查看wxWindowDisabler类,构造函数有一个参数表示可以与之交互的窗口,应用程序的所有其他窗口都将被禁用。
如果您稍后想要执行辅助程序,那么您可以使用wxExecute()函数来执行此操作。
不确定这是一个很好的答案,但它有效。
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 并且从不绘制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.