对话框与面板类似,因为它也是一种可用于放置控件的窗口,但存在以下例外情况:
- 隐式地创建一个环绕的窗口。
- 对话框会自动被赋予额外的功能,比如在各个项目之间使用制表键切换(目前仅在Windows系统上支持)。
- 如果对话框是模态的,调用程序会被阻塞,直到对话框被关闭。
另请参阅wx.TopLevelWindow和wx.Window以了解继承的成员函数。控件中数据的验证内容在《验证器概述》中有介绍。
自动滚动对话框
随着种类越来越繁多的移动硬件进入市场,对于wxPython应用程序而言,在不给程序员带来过多负担的情况下适配这些平台变得愈发重要。wxPython能够提供帮助的一个方面是,让对话框适配那些因设备外形尺寸较小而不可避免出现的低分辨率屏幕。 因此,wx.Dialog提供了一个全局的wx.DialogLayoutAdapter类,该类为大多数基于布局管理器(sizer)的自定义对话框实现了自动滚动适配功能。因此,就对话框而言,许多应用程序应该能够在几乎或完全无需额外工作的情况下适配小屏幕显示。默认情况下,这种适配功能是关闭的。要在你的应用程序中全局开启滚动适配功能,请调用静态函数wx.Dialog.EnableLayoutAdaptation并传入参数True。你也可以通过调用wx.Dialog.SetLayoutAdaptationMode并传入wx.DIALOG_ADAPTATION_MODE_DEFAULT(使用全局设置)、wx.DIALOG_ADAPTATION_MODE_ENABLED或wx.DIALOG_ADAPTATION_MODE_DISABLED其中之一,来针对每个对话框单独调整适配设置。最后两种模式会覆盖全局适配设置。在启用适配功能的情况下,如果显示尺寸对于对话框来说过小,wxPython(确切地说是标准适配类wx.StandardDialogLayoutAdapter)会使对话框的一部分可滚动,同时将标准按钮保留在对话框底部的不可滚动部分。这是通过以下方式完成的,即在从wx.Dialog.Show或wx.Dialog.ShowModal内部调用的wx.DialogLayoutAdapter.DoLayoutAdaptation中进行:
- 如果wx.Dialog.GetContentWindow返回一个派生自wx.BookCtrlBase的窗口,那么这些页面将变为可滚动的,并且不会进行其他的适配操作。
- wxPython会查找一个wx.StdDialogButtonSizer,并将其用于不可滚动的部分。
- 如果上述查找失败,wxPython会查找一个包含一个或多个标准按钮(带有诸如wx.ID_OK和wx.ID_CANCEL之类标识符)的水平wx.BoxSizer。
- 如果这次查找也失败了,wxPython会找到“零散的”标准按钮(存在于任何类型的布局管理器中),并将它们添加到一个wx.StdDialogButtonSizer中。如果没有找到标准按钮,那么整个对话框的内容都将是可滚动的。
- 除了标准按钮之外的所有子控件都会被重新设置父窗口,成为一个新的wx.ScrolledWindow对象的子控件。会将原来的顶级布局管理器用于这个可滚动窗口,并创建一个新的顶级布局管理器来对这个可滚动窗口和标准按钮布局管理器进行布局。
自定义滚动适配
除了可以全局地或针对每个对话框开启和关闭适配功能外,你还可以通过设置wx.Dialog.SetLayoutAdaptationLevel来选择wxPython搜索标准按钮的积极程度。默认情况下,会执行上述所有步骤,但例如将级别设置为1时,你可以选择仅查找wx.StdDialogButtonSizer。你可以使用wx.Dialog.AddMainButtonId来添加那些在不可滚动区域也应被视为标准按钮的按钮标识符。你可以从wx.DialogLayoutAdapter或wx.StandardDialogLayoutAdapter派生自己的类,然后调用wx.Dialog.SetLayoutAdapter,并删除此函数返回的旧对象。重写CanDoLayoutAdaptation和DoLayoutAdaptation函数,以便测试适配的适用性并执行适配操作。你也可以在从wx.Dialog派生的类中重写wx.Dialog.CanDoLayoutAdaptation和wx.Dialog.DoLayoutAdaptation函数。
自动滚动适配可能会失败的情况
由于适配操作会重新排列你的布局管理器和窗口层级结构,它并非万无一失,可能会在以下情况下失败:
- 对话框未使用布局管理器。
- 对话框的实现对窗口层级结构存在一些预设条件,例如获取某个控件的父窗口并将其转换为对话框类。
- 对话框进行了自定义绘制和/或可滚动窗口未处理的事件处理。如果这个问题可以全局解决,你可以从wx.StandardDialogLayoutAdapter派生一个新的适配器类,并重写其CreateScrolledWindow函数,以返回你自己类的一个实例。
- 对话框具有不常见的布局,例如一个垂直布局管理器中混合包含了标准按钮和其他控件。
- 对话框对布局管理器层级结构存在一些预设条件,例如显示或隐藏顶级布局管理器的子项。不过,在调用Show或ShowModal之前,原始的布局管理器层级结构仍将保持不变。
你可以通过以下方式来确保你的对话框在适配后仍能正常工作:
- 避免出现上述情况和预设条件;
- 使用wx.StdDialogButtonSizer;
- 仅在对话框创建后即刻对层级结构做出预设;
- 在主布局管理器下使用一个中间布局管理器,即一个虚拟的顶级布局管理器,可依靠它来实现对其子布局管理器和窗口的操作;
- 如果你的对话框实现了页面功能,重写wx.Dialog.GetContentWindow以返回一个书本控件:这样一来,wxPython就只会让页面变得可滚动。
PropertySheetDialog和向导
对于wx.PropertySheetDialog的适配,总是通过简单地使页面可滚动来完成,因为wx.Dialog.GetContentWindow返回的是对话框的书本控件(管理页面的控件),而这由标准布局适配器来处理。wx.adv.Wizard使用它自己的CanDoLayoutAdaptation和DoLayoutAdaptation函数,而不是全局的适配器:同样,只有向导页面会被设置为可滚动。