WxFrame的样式
每个wxPython窗口部件都要求一个样式参数。这部分我们将讨论用于wx.Frame的样式。它们中的一些也适用于别的wxPython窗口部件。一些窗口部件也定义了一个SetStyle()方法,让你可以在该窗口部件创建后改变它的样式。所有的你能使用的样式元素都有一个常量标识符(如wx.MINIMIZE_BOX)。要使用多个样式,你可以使用或运算符|。例如,wx.DEFAULT_FRAME_STYLE样式就被定义为如下几个基本样式的组合:
wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX | wx.RESIZE_BORDER |wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX
要从一个合成的样式中去掉个别的样式,你可以使用^操作符。例如要创建一个默认样式的窗口,但要求用户不能缩放和改变窗口的尺寸,你可以这样做:
wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX)
如果你不慎使用了&操作符,那么将得到一个没有样式的、无边框图的、不能移动、不能改变尺寸和不能关闭的界面。
wx.Frame的最重要的样式:
- wx.CAPTION:在框架上增加一个标题栏,它显示该框架的标题属性。
- wx.CLOSE_BOX:指示系统在框架的标题栏上显示一个关闭框,使用系统默认的位置和样式。
- wx.DEFAULT_FRAME_STYLE:默认样式。
- wx.FRAME_SHAPED:用这个样式创建的框架可以使用SetShape()方法去创建一个非矩形的窗口。
- wx.FRAME_TOOL_WINDOW:通过给框架一个比正常更小的标题栏,使框架看起来像一个工具框窗口。在Windows下,使用这个样式创建的框架不会出现在显示所有打开窗口的任务栏上。
- wx.MAXIMIZE_BOX:指示系统在框架的标题栏上显示一个最大化框,使用系统默认的位置和样式。
- wx.MINIMIZE_BOX:指示系统在框架的标题栏上显示一个最小化框,使用系统默认的位置和样式。
- wx.RESIZE_BORDER:给框架增加一个可以改变尺寸的边框。
- wx.SIMPLE_BORDER:没有装饰的边框。不能工作在所有平台上。
- wx.SYSTEM_MENU:增加系统菜单(带有关闭、移动、改变尺寸等功能)和关闭框到这个窗口。在系统菜单中的改变尺寸和关闭功能的有效性依赖于wx.MAXIMIZE_BOX, wx.MINIMIZE_BOX和wx.CLOSE_BOX样式是否被应用。
使用样式
这些样式的使用非常简单,在大多数的控件的属性中都有一个属性叫做style,而前面这些常量名就可以作为这个属性的属性值传入进去,从而使这个控件具有这个常量所对应的样式。比如说我们想要创建一个不允许最大化的窗口,就可以将样式修改成像这样:
wx.Frame.init(self, None, -1, “My Frame Window”, (100, 100), (800, 600), style=wx.CAPTION | wx.MINIMIZE_BOX | wx.CLOSE_BOX)
这样创建出来的窗口最大化功能就是被禁用的,同理,如果想要这个窗口禁止最小化,首先要添加标题栏,然后添加关闭按钮样式和最大化按钮样式,但是不要添加最小化按钮样式,就可以禁止窗口最小化。
其中默认样式是最全面的,一般如果要做修改的话,只需要在默认样式里面进行移除样式就可以了。比如同样要实现禁止最大化的效果,可以这样来写:
wx.Frame.init(self, None, -1, “My Frame Window”, (100, 100), (800, 600), style = wx.DEFAULT_FRAME_STYLE ^ wx.MAXIMIZE_BOX)
添加组件
我们之前一直在玩一个单一的窗口,但是单一的窗口实在是没有什么好玩的地方,就拿我们最常见的一个登录界面来说吧,他最起码也是要有一个输入框,几个按钮,并且具有对应的功能,那么接下来,我们要做的就是在这个空白的页面中添加一些组件。
我们还是先来看一下效果,然后我们再来详细的介绍一下这里面的代码:
import wx # 导入wxPython库,用于创建GUI应用程序
class MyFrame(wx.Frame): # 定义一个继承自wx.Frame的类,MyFrame表示窗口框架
def __init__(self): # 定义MyFrame类的构造函数,初始化窗口
wx.Frame.__init__(self, None, -1, "My Frame Window", (100, 100), (300, 400), style = wx.DEFAULT_FRAME_STYLE ^ wx.MAXIMIZE_BOX) # 初始化窗口的具体属性,包括标题、位置、大小和风格
panel = wx.Panel(self, -1) # 在窗口中创建一个面板,面板是用于放置控件的容器
button = wx.Button(panel, -1, "Button", size=(100, 50), pos=(100, 100)) # 在面板上创建一个按钮,指定按钮的大小和位置
class MyApp(wx.App): # 定义一个继承自wx.App的类,MyApp表示应用程序
def OnInit(self): # 定义MyApp类的初始化方法,在应用程序启动时调用
frame = MyFrame() # 创建一个MyFrame实例,即窗口
self.SetTopWindow(frame) # 设置应用程序的顶级窗口
frame.Show() # 显示窗口
return True # 返回True,表示应用程序成功初始化
if __name__ == '__main__': # 检查当前模块是否是主程序入口
app = MyApp() # 创建一个MyApp实例,即应用程序
app.MainLoop() # 进入应用程序的主事件循环,等待用户操作
这这段代码的运行效果如下所示:
他在这个界面中添加了一个按钮的组件,就是这样的一个简单的效果。然后我们来看他具体是如何完成的。
类MyFrame的方法__init__创建了两子窗口。第一个是wx.Panel,它是其它窗口的容器,它自身也有一点功能。第二个是wx.Button,它是一个普通按钮。这个Panel对象,也叫做面板对象,大多数情况下,我们习惯将创建一个与你的wx.Frame大小一样的wx.Panel实例以容纳你的框架上的所有的内容。这样做可以让定制的窗口内容与其他如工具栏和状态栏分开。 在视觉效果上会更好一点,通过tab按钮,可以遍历wx.Panel中的元素,wx.Frame不能。这是Panel面板对象的一个小特性。
还有一个wxpython的优势就是,你不必像使用别的UI工具包那样,不需要显式调用一个增加方法来向父窗口中插入一个子窗口。在wxPython中,你只需在子窗口被创建时指定父窗口,这个子窗口就隐式地增加到父对象中了。之前我们说过,控件或者面板对象的第一个属性就是父窗口,如果我们想让某个控件属于某个其他的窗口或控件只需要在第一个参数这里指定父窗口的对象名就可以了,不需要再用多余的代码去指定或者添加。而顶级对象的父窗口是None,也就是空,没有父窗口。
你可能想知道在刚才的例子中,为什么wx.Button被创建时使用了明确的位置和尺寸,而wx.Panel没有。在wxPython中,如果只有一个子窗口的框架被创建,那么那个子窗口(案例中是wx.Panel)被自动重新调整尺寸去填满该框架的全部区域。这个自动调整尺寸将覆盖关于这个子窗口的任何位置和尺寸信息,尽管关于子窗口的信息已被指定,这些信息将被忽略。这个自动调整尺寸仅适用于框架内或对话框内的只有唯一元素的情况。这里按钮是panel的元素,而不是框架的,所以要使用指定的尺寸和位置。如果没有为这个按钮指定尺寸和位置,它将使用默认的位置(从panel的左上角开始计算)和基于按钮标签的长度的尺寸。
简单来说就是,窗口的第一个元素会被强制铺满全屏,所以我们一般使用面板对象当作窗口对象的第一个元素,然后其他的组件全部放在面板组件上,比如在上面的案例中,我们将面板对象去掉,直接将按钮对象的父窗口设置为顶级窗口的话,它会将这个按钮对象给放大铺满整个屏幕。
还有一点就是,再上一个案例中我们是通过调整窗口的大小和按钮的位置让这个按钮看起来处于窗口的居中位置,但其实这样是很不合理的。更重要的是,当用户调整窗口大小的时候,这使得子窗口的位置和大小不能作相应调整。为了解决这两个问题,wxPython使用了称为sizers的对象来管理子窗口的复杂布局。在之后我们会开一个新的章节来详细的介绍和学习sizers这个布局管理器。
给框架增加菜单栏、工具栏和状态栏。
状态栏
首先来看状态栏,状态栏比较简单,它分为创建和设置两个步骤,如下所示:
statusBar = self.CreateStatusBar() # 1 创建状态栏
statusBar.SetStatusText("这是状态栏的说明信息") # 2 设置状态栏显示的内容
他的显示效果如下所示:
效果就是在窗口的下面多了一个空间来放置一些说明信息,这些说明信息是可以随时刷新,随时更换的,比如我们打开了一个菜单栏,可以根据选择菜单栏的不同显示不同的信息。
工具栏
然后是工具栏,工具栏的创建比较麻烦一些,它分为三步,分别是创建工具栏,添加工具,显示工具栏,具体的代码如下所示:
toolbar = self.CreateToolBar() # 1 创建工具栏
toolbar.AddTool(1, "New", images.getPyBitmap(), "Create a new file", wx.ITEM_NORMAL) # 2 在工具栏上添加一个工具
toolbar.AddSeparator() # 3 在工具栏上添加一个分隔符
toolbar.AddTool(2, "Open", images.getPyBitmap(), "Open an existing file", wx.ITEM_NORMAL) # 4 在工具栏上添加一个工具
toolbar.Realize() # 5 显示工具栏
这段代码的显示效果如下所示:
上面的两个蛋糕的图标就是我们工具栏的图标。当我们的鼠标悬停在这个图标上面的时候,就可以看到我们刚才设置的提示信息。也可以通过修改工具栏的样式,选择显示文字,或者是显示图标和文字。
在添加工具栏的时候,他的参数比较多,这里来分别介绍一下他的完整参数分别是什么:
AddTool (self, toolId, label, bitmap, shortHelp=‘’, kind=ITEM_NORMAL)
- toolId (int) – 一个整数,可以在后续作中识别工具。
- label (string) – 要使用工具显示的字符串。此字符串可能包含助记符,即以 & (“&”) 为前缀的字符,但它们已从中删除,并且实际上不会显示在工具栏中,因为工具无法从键盘激活。
- bitmap (wx.BitmapBundle) – 图标。
- shortHelp(字符串)– 此字符串用于工具工具提示,鼠标悬停的时候显示的字符串
- kind (ItemKind) – 可以设置工具栏按钮的样式,属性值在这些里里面取值:ITEM_NORMAL(普通按钮样式),ITEM_CHECK(按下去打开,再按一次关闭的样式),ITEM_RADIO(一直保持选中的样式),ITEM_DROPDOWN(在工具栏旁边多了一个下拉菜单的样式)。
菜单栏
菜单栏是最复杂的一种,它分为创建菜单栏,创建菜单栏菜单,创建菜单栏菜单项,添加菜单项,添加菜单,添加菜单栏,我们一步一步的来他是如何实现的:
menu1 = wx.Menu() # 1 创建一个菜单
menu1.Append(1, "File") # 2 在菜单中添加一个子菜单
menu1.Append(2, "Edit") # 3 在菜单中添加一个子菜单
menu1.Append(3, "Help") # 4 在菜单中添加一个子菜单
menu2 = wx.Menu() # 5 创建另一个菜单
menu2.Append(4, "Copy") # 6 在菜单中添加一个子菜单
menu2.Append(5, "Paste") # 7 在菜单中添加一个子菜单
menu2.Append(6, "Delete") # 8 在菜单中添加一个子菜单
menuBar = wx.MenuBar() # 9 创建菜单栏
menuBar.Append(menu1, "File") # 10 在菜单栏中添加一个菜单
menuBar.Append(menu2, "Edit") # 11 在菜单栏中添加另一个菜单
self.SetMenuBar(menuBar) # 12 设置窗口的菜单栏
上面这段代码的效果如下所示:
在工具栏的上面可以看到就是我们设置的菜单栏。
关于菜单栏的创建比较的复杂一些,但是流程基本都是固定的,记住创建的流程之后就会方便很多。
二级菜单
在我们的常见菜单中,除了这种的一级菜单之外,还有一些菜单也会有多级菜单的情况出现,制作多级菜单也是非常的简单,具体的代码如下所示:
menuBar = wx.MenuBar() # 1 创建菜单栏
menuBar.Append(menu1, "File") # 2 在菜单栏中添加一个菜单
menuBar.Append(menu2, "Edit") # 3 在菜单栏中添加另一个菜单
self.SetMenuBar(menuBar) # 4 设置窗口的菜单栏
其实他的操作逻辑也是很简单的,多级菜单就是在一个菜单栏的上面再加入一个可以被展开的扩展,等于加上一个新的菜单栏,所以也需要再创建一个菜单栏,只不过不再是被添加到大的菜单栏里面了,而是被添加到小的菜单栏里面。
对话框
wxPython提供了一套丰富的预定义的对话框。这部分,我们将讨论三种用对话框得到来自用户的信息:
- 1、消息对话框
- 2、文本输入对话框
- 3、从一个列表中选择
在wxPython中有许多别的标准对话框,包括文件选择器、色彩选择器、进度对话框、打印设置和字体选择器。这些将在之后的学习中逐步的介绍。
消息对话框
与用户通信最基本的机制是wx.MessageDialog,它是一个简单的提示框。wx.MessageDialog可用作一个简单的OK框或yes/no对话框。下面的片断显示了yes/no对话框:
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "MyFrame", size=(800, 600))
self.panel = wx.Panel(self, -1)
self.Message = wx.MessageDialog(self.panel, "这里是对话框中的内容", "这里是对话框的标题", wx.YES_NO | wx.ICON_QUESTION)
self.Message.ShowModal()
self.Message.Destroy()
他的显示效果如下所示:
然后我们来看一下,对话框的参数都有那些:
MessageDialog(parent, message, caption=MessageBoxCaptionStr,style=OK|CENTRE, pos=DefaultPosition)
- parent (wx.windown) – 父窗口。
- message (string) – 要在对话框中显示的消息。
- caption (string) – 对话框标题。
- style (long) – 在OK或者YES_NO中选择一个,要么显示一个关闭,要么选择是或者否。
- POS(WX.点) – 对话框位置(在 MSW 下忽略)。
ShowModal()方法将对话框以模式框架的方式显示,这意味着在对话框关闭之前,应用程序中的别的窗口不能响应用户事件。ShowModal()方法的返回值是一个整数,对于wx.MessageDialog,返回值是下面常量之一: wx.ID_YES, wx.ID_NO, wx.ID_CANCEL, wx.ID_OK。对话框的返回值可以判断用户点击了什么操作,从而根据操作来调用对应的事件回调函数。
还有一点需要注意的是,在wxpython中,对话框需要手动调用self.Message.Destroy()方法销毁,否则会造成资源泄露,会导致资源的浪费。当你使用了对话框的时候,一定要检查一点是否手动调用销毁方法销毁对话框。
文本输入对话框
如果我们想从用户那里得到单独一行文本,我们可以使用类wx.TextEntryDialog。下面的片断创建了一个文本输入域,当用户单击OK按钮退出时,获得用户输入的值:
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "MyFrame", size=(800, 600))
self.panel = wx.Panel(self, -1)
Text = wx.TextEntryDialog(None, "这里是输入框的标题", "请输入内容:", "这里是默认内容")
if Text.ShowModal() == wx.ID_OK:
print(Text.GetValue())
Text.Destroy()
上面这段代码的效果如下所示:
上面的wx.TextEntryDialog的参数按顺序说明是,父窗口,显示在窗口中的文本标签,窗口的标题(默认是“Please enter text”),输入域中的默认值。同样它也有一个样式参数,默认是wx.OK | wx.CANCEL。与wx.MessageDialog一样,ShowModal()方法返回所按下的按钮的ID。GetValue()方法得到用户输入在文本域中的值(这有一个相应的SetValue()方法让你可以改变文本域中的值)。
从一个列表中选择
你可以让用户只能从你所提供的列表中选择,你可以使用类wx.SingleChoiceDialog。下面是一个简单的用法:
class MyFrame(wx.Frame): # 定义一个继承自wx.Frame的类,MyFrame表示窗口框架
def __init__(self): # 定义MyFrame类的构造函数,初始化窗口
wx.Frame.__init__(self, None, -1, "MyFrame", size=(800, 600)) # 初始化窗口的具体属性,包括标题、位置和大小
self.panel = wx.Panel(self, -1) # 在窗口中创建一个面板,面板是用于放置控件的容器
chios = wx.SingleChoiceDialog(None, "请选择您的心动嘉宾?", "列表选择框", ["张三", "李四", "王五", "赵六"], wx.CHOICEDLG_STYLE) # 创建一个单选对话框,包含选项列表
if chios.ShowModal() == wx.ID_OK: # 显示对话框并检查用户是否点击了“确定”按钮
print(chios.GetStringSelection()) # 获取用户选择的内容并打印出来
chios.Destroy() # 销毁对话框对象,释放相关资源
这段代码的显示效果如下所示:
wx.SingleChoiceDialog的参数类似于文本输入对话框,只是以字符串的列表代替了默认的字符串文本。要得到所选择的结果有两种方法,GetSelection()方法返回用户选项的索引,而GetStringSelection()返回实际所选的字符串。chios.ShowModal() 是 wx.SingleChoiceDialog 类中的一个方法,用于显示对话框并等待用户与其交互。具体来说,ShowModal() 方法会显示对话框,并使程序进入一个模态循环,这意味着用户必须与对话框进行交互(例如点击“确定”或“取消”按钮)之后,程序才会继续执行后续的代码。