- wxPython 教程
- wxPython - 首页
- wxPython - 简介
- wxPython - 环境配置
- wxPython - Hello World
- wxPython - GUI构建工具
- wxPython - 主要类
- wxPython - 事件处理
- wxPython - 布局管理
- wxPython - 按钮
- wxPython - 可停靠窗口
- 多文档界面
- wxPython - 绘图API
- wxPython - 拖放操作
- wxPython 资源
- wxPython 快速指南
- wxPython - 有用资源
- wxPython - 讨论
wxPython 快速指南
wxPython - 简介
wxPython 是一个 Python 包装器,用于流行的跨平台 GUI 工具包 wxWidgets(用 C++编写)。由 Robin Dunn 和 Harri Pasanen 开发,wxPython 实现为一个 Python 扩展模块。
就像 wxWidgets 一样,wxPython 也是一个自由软件。它可以从官方网站 http://wxpython.org 下载。许多操作系统的二进制文件和源代码都可以在此网站下载。
wxPython API 中的主要模块包括一个核心模块。它包含wxObject 类,它是 API 中所有类的基类。控件模块包含 GUI 应用程序开发中使用的所有窗口部件。例如,wx.Button、wx.StaticText(类似于标签)、wx.TextCtrl(可编辑文本控件)等。
wxPython API 有 GDI(图形设备接口)模块。它是一组用于在窗口部件上绘图的类。字体、颜色、画笔等类都是它的一部分。所有容器窗口类都在 Windows 模块中定义。
wxPython 的官方网站还托管 Project Phoenix——一个针对 Python 3.* 的 wxPython 新实现。它专注于提高速度、可维护性和可扩展性。该项目始于 2012 年,目前仍处于测试阶段。
wxPython - 环境配置
Windows
Windows 操作系统(32 位和 64 位)的预构建二进制文件可在 http://www.wxpython.org/download.php 页面上找到。最新的安装程序版本如下:wxPython3.0-win32-3.0.2.0-py27.exe(适用于 32 位 Python 2.7) wxPython3.0-win64-3.0.2.0-py27.exe(适用于 64 位 Python 2.7)
wxPython 演示、示例和 wxWidgets 文档也可在同一页面下载。
wxPython3.0-win32-docs-demos.exe
Linux
许多 Linux 发行版的 wxPython 二进制文件可以在其各自的存储库中找到。将需要使用相应的包管理器来下载和安装。例如,在 Debian Linux 上,以下命令应该能够安装 wxPython。
sudo apt-get install python-wxgtk3.0
MacOS
MacOS 的预构建二进制文件(磁盘映像形式)可在官方网站的下载页面上找到。
wxPython - Hello World
一个简单的 GUI 应用程序,显示 Hello World 消息,使用以下步骤构建:
导入 wx 模块。
定义 Application 类的对象。
创建一个顶级窗口作为 wx.Frame 类的对象。标题和大小参数在构造函数中给出。
虽然可以在 Frame 对象中添加其他控件,但无法管理它们的布局。因此,将一个 Panel 对象放入 Frame 中。
添加一个 StaticText 对象,以在窗口内的所需位置显示“Hello World”。
通过 show() 方法激活框架窗口。
进入 Application 对象的主事件循环。
import wx app = wx.App() window = wx.Frame(None, title = "wxPython Frame", size = (300,200)) panel = wx.Panel(window) label = wx.StaticText(panel, label = "Hello World", pos = (100,50)) window.Show(True) app.MainLoop()
上述代码产生以下输出:
wxFrame 对象是最常用的顶级窗口。它派生自wxWindow 类。框架是一个窗口,其大小和位置可以由用户更改。它有一个标题栏和控制按钮。如果需要,可以启用菜单栏、工具栏和状态栏等其他组件。wxFrame 窗口可以包含任何不是对话框或另一个框架的框架。
wxPython - GUI构建工具
通过手动编码创建美观的 GUI 可能很繁琐。一个可视化 GUI 设计器工具始终很方便。许多针对 wxPython 的 GUI 开发 IDE 都可用。以下是一些:
- wxFormBuilder
- wxDesigner
- wxGlade
- BoaConstructor
- gui2py
wxFormBuilder 是一个开源的、跨平台的所见即所得 GUI 构建器,可以将 wxWidget GUI 设计转换为 C++、Python、PHP 或 XML 格式。这里简要介绍了 wxFormBuilder 的使用方法。
首先,需要从 http://sourceforge.net/projects/wxformbuilder/ 下载并安装最新版本的 wxFormBuilder。打开应用程序后,中间会出现一个带有空白灰色区域的新项目。
为项目命名,并选择 Python 作为代码生成语言。这在对象属性窗口中完成,如下图所示:
然后从组件调色板的“窗体”选项卡中选择 Frame。
从“布局”选项卡中添加一个垂直 wxBoxSizer。
在 Box 中添加必要的控件,并使用合适的标题。这里添加了一个 StaticText(标签)、两个 TextCtrl 对象(文本框)和一个 wxButton 对象。框架如下图所示:
在这三个控件上启用 Expand 和 Stretch。在 wxButton 对象的对象属性中,将函数 findsquare() 分配给 OnButtonClick 事件。
保存项目并按 F8 生成已开发 GUI 的 Python 代码。将生成的代码文件命名为 Demo.py
在可执行的 Python 脚本中,导入 demo.py 并定义 FindSquare() 函数。声明 Application 对象并启动主事件循环。以下是可执行代码:
import wx #import the newly created GUI file import demo class CalcFrame(demo.MyFrame1): def __init__(self,parent): demo.MyFrame1.__init__(self,parent) def FindSquare(self,event): num = int(self.m_textCtrl1.GetValue()) self.m_textCtrl2.SetValue (str(num*num)) app = wx.App(False) frame = CalcFrame(None) frame.Show(True) #start the applications app.MainLoop()
上述代码产生以下输出:
wxPython - 主要类
原始 wxWidgets(用 C++编写)是一个庞大的类库。该库中的 GUI 类使用 wxPython 模块移植到 Python,该模块试图尽可能准确地镜像原始 wxWidgets 库。因此,wxPython 中的 wx.Frame 类与 C++ 版本中的 wxFrame 类的工作方式非常相似。
wxObject 是大多数类的基类。wxApp(在 wxPython 中为 wx.App)的对象表示应用程序本身。生成 GUI 后,应用程序通过 MainLoop() 方法进入事件循环。下图描述了 wxPython 中最常用的 GUI 类的类层次结构。
序号 | 类和描述 |
---|---|
1 | wx.Frame
wx.Frame 类有一个没有参数的默认构造函数。 |
2 | wx.Panel
wx.Panel 类通常放在 wxFrame 对象内。此类也继承自 wxWindow 类。 |
3 | wx.StaticText
wx.StaticText 类对象呈现一个包含只读文本的控件。因为它不会产生任何事件,所以它可以被称为被动控件。 |
4 | TextCtrl
在 wxPython 中,wx.TextCtrl 类的对象用于此目的。它是一个可以显示和编辑文本的控件。 |
5 | RadioButton & RadioBox
每个按钮(wx.RadioButton 类的对象)在圆形按钮旁边都有一个文本标签。wxPython API 还包含 wx.RadioBox 类。它的对象为该组提供边框和标签。 |
6 | wx.CheckBox
复选框显示一个小的带标签的矩形框。单击时,矩形内会出现一个复选标记,以指示已做出选择。 |
7 | ComboBox & Choice 类
wx.ComboBox 对象提供一个项目列表供选择。可以将其配置为下拉列表或永久显示。wxPython API 包含 wx.Choice 类,其对象也是一个永久只读的下拉列表。 |
8 | Wx.Gauge
Wx.Gauge 类对象显示一个垂直或水平条,以图形方式显示递增的数量。 |
9 | wx.Slider
wxPython API 包含 wx.Slider 类。它提供与滚动条相同的功能。滑块提供了一种方便的方法来处理通过滑块特定的 wx.EVT_SLIDER 事件绑定器拖动滑块。 |
10 | wx.MenuBar
顶级窗口标题栏下方的水平条用于显示一系列菜单。它是 wxPython API 中 wx.MenuBar 类的对象。 |
11 | wx.Toolbar
如果 wx.Toolbar 对象的 style 参数设置为 wx.TB_DOCKABLE,则它将变为可停靠的。也可以使用 wxPython 的 AUIToolBar 类构造浮动工具栏。 |
12 | Wx.Dialog
虽然 Dialog 类对象看起来像 Frame,但它通常用作父框架顶部的弹出窗口。Dialog 的目的是从用户那里收集一些数据并将其发送到父框架。 |
13 | wx.Notebook
wx.Notebook 窗口部件提供一个选项卡式控件。框架中的一个 Notebook 对象具有一个或多个选项卡(称为页面),每个页面都有一个显示控件布局的面板。 |
14 | wx.SplitterWindow
此类的对象是一个布局管理器,它包含两个子窗口,其大小可以通过拖动它们之间的边界来动态更改。Splitter 控件提供一个可以拖动以调整控件大小的句柄。 |
15 | HTMLWindow
wxHTML 库包含用于解析和显示 HTML 内容的类。虽然这并非旨在成为一个功能齐全的浏览器,但 wx.HtmlWindow 对象是一个通用的 HTML 查看器。 |
16 | ListBox & ListCtrl
wx.ListBox 窗口部件显示一个垂直可滚动的字符串列表。默认情况下,列表中可以选择单个项目。ListCtrl 窗口部件是一个高度增强的列表显示和选择工具。可以在报表视图、列表视图或图标视图中显示多列列表。 |
wxPython - 事件处理
与以顺序方式执行的控制台模式应用程序不同,基于 GUI 的应用程序是事件驱动的。函数或方法是响应用户操作(例如单击按钮、从集合中选择项目或鼠标单击等,称为事件)而执行的。
应用程序运行期间发生的事件相关数据存储为从wx.Event派生的子类的对象。显示控件(例如按钮)是特定类型事件的源,并产生与其关联的Event类对象。例如,单击按钮会发出wx.CommandEvent。此事件数据将分派到程序中的事件处理程序方法。wxPython 具有许多预定义的事件绑定器。事件绑定器封装了特定窗口小部件(控件)、其关联的事件类型和事件处理程序方法之间的关系。
例如,要在按钮单击事件上调用程序的OnClick() 方法,需要以下语句:
self.b1.Bind(EVT_BUTTON, OnClick)
Bind() 方法由所有显示对象从wx.EvtHandler 类继承。这里的EVT_.BUTTON 是绑定器,它将按钮单击事件与OnClick() 方法关联。
示例
在以下示例中,由拖动顶级窗口(在本例中为wx.Frame 对象)引起的MoveEvent 与使用wx.EVT_MOVE 绑定器的OnMove() 方法连接。代码显示一个窗口。如果使用鼠标移动它,则其瞬时坐标将显示在控制台上。
import wx class Example(wx.Frame): def __init__(self, *args, **kw): super(Example, self).__init__(*args, **kw) self.InitUI() def InitUI(self): self.Bind(wx.EVT_MOVE, self.OnMove) self.SetSize((250, 180)) self.SetTitle('Move event') self.Centre() self.Show(True) def OnMove(self, e): x, y = e.GetPosition() print "current window position x = ",x," y= ",y ex = wx.App() Example(None) ex.MainLoop()
上述代码产生以下输出:
当前窗口位置 x = 562 y = 309
当前窗口位置 x = 562 y = 309
当前窗口位置 x = 326 y = 304
当前窗口位置 x = 384 y = 240
当前窗口位置 x = 173 y = 408
当前窗口位置 x = 226 y = 30
当前窗口位置 x = 481 y = 80
下表列出了一些从wx.Event 继承的子类:
序号 | 事件和描述 |
---|---|
1 | wxKeyEvent 按下或释放按键时发生 |
2 | wxPaintEvent 每当需要重绘窗口内容时生成 |
3 | wxMouseEvent 包含有关任何由于鼠标活动(例如鼠标按钮按下或拖动)而发生的事件的数据 |
4 | wxScrollEvent 与可滚动控件(如wxScrollbar 和wxSlider)相关联 |
5 | wxCommandEvent 包含源自许多窗口小部件(如按钮、对话框、剪贴板等)的事件数据。 |
6 | wxMenuEvent 不同的菜单相关事件,不包括菜单命令按钮单击 |
7 | wxColourPickerEvent wxColourPickerCtrl 生成的事件 |
8 | wxDirFilePickerEvent FileDialog 和 DirDialog 生成的事件 |
wxPython 中的事件分为两种类型:基本事件和命令事件。基本事件停留在其起源的窗口中。大多数 wxWidgets 生成命令事件。命令事件可以传播到窗口或窗口,这些窗口在类层次结构中位于源窗口之上。
示例
以下是事件传播的一个简单示例。完整的代码是:
import wx class MyPanel(wx.Panel): def __init__(self, parent): super(MyPanel, self).__init__(parent) b = wx.Button(self, label = 'Btn', pos = (100,100)) b.Bind(wx.EVT_BUTTON, self.btnclk) self.Bind(wx.EVT_BUTTON, self.OnButtonClicked) def OnButtonClicked(self, e): print 'Panel received click event. propagated to Frame class' e.Skip() def btnclk(self,e): print "Button received click event. propagated to Panel class" e.Skip() class Example(wx.Frame): def __init__(self,parent): super(Example, self).__init__(parent) self.InitUI() def InitUI(self): mpnl = MyPanel(self) self.Bind(wx.EVT_BUTTON, self.OnButtonClicked) self.SetTitle('Event propagation demo') self.Centre() self.Show(True) def OnButtonClicked(self, e): print 'click event received by frame class' e.Skip() ex = wx.App() Example(None) ex.MainLoop()
在上面的代码中,有两个类。MyPanel,一个wx.Panel 子类和Example,一个wx.Frame 子类,它是程序的顶级窗口。一个按钮放在面板中。
此Button 对象绑定到一个事件处理程序btnclk(),该处理程序将其传播到父类(在本例中为MyPanel)。按钮单击生成一个CommandEvent,可以通过Skip() 方法将其传播到其父级。
MyPanel 类对象还将接收到的事件绑定到另一个处理程序OnButtonClicked()。此函数又将其传递给其父级Example 类。上述代码产生以下输出:
Button received click event. Propagated to Panel class. Panel received click event. Propagated to Frame class. Click event received by frame class.
wxPython - 布局管理
可以通过指定以像素为单位测量的绝对坐标,将GUI 窗口小部件放置在容器窗口内。坐标相对于其构造函数的size 参数定义的窗口尺寸。窗口小部件在窗口内的位置由其构造函数的pos 参数定义。
import wx app = wx.App() window = wx.Frame(None, title = "wxPython Frame", size = (300,200)) panel = wx.Panel(window) label = wx.StaticText(panel, label = "Hello World", pos = (100,50)) window.Show(True) app.MainLoop()
但是,这种绝对定位由于以下原因并不合适:
即使调整窗口大小,窗口小部件的位置也不会改变。
在具有不同分辨率的不同显示设备上的外观可能不一致。
布局修改很困难,因为它可能需要重新设计整个表单。
wxPython API 提供布局类,用于更优雅地管理容器内窗口小部件的位置。布局管理器相对于绝对定位的优点是:
- 窗口内的窗口小部件会自动调整大小。
- 确保在具有不同分辨率的显示设备上外观一致。
- 可以动态添加或删除窗口小部件,而无需重新设计。
在wxPython 中,布局管理器称为Sizer。Wx.Sizer 是所有sizer 子类的基类。让我们讨论一些重要的sizer,例如wx.BoxSizer、wx.StaticBoxSizer、wx.GridSizer、wx.FlexGridSizer 和wx.GridBagSizer。
序号 | Sizer 和描述 |
---|---|
1 | BoxSizer
此sizer 允许以行方式或列方式排列控件。BoxSizer 的布局由其orientation 参数(wxVERTICAL 或wxHORIZONTAL)确定。 |
2 | GridSizer
顾名思义,GridSizer 对象呈现一个二维网格。控件按从左到右、从上到下的顺序添加到网格槽中。 |
3 | FlexiGridSizer
此sizer 也具有二维网格。但是,它在单元格中布置控件方面提供了更多灵活性。 |
4 | GridBagSizer
GridBagSizer 是一个多功能的sizer。它提供了比FlexiGridSizer 更多的增强功能。子窗口小部件可以添加到网格内的特定单元格。 |
5 | StaticBoxSizer
StaticBoxSizer 将box sizer 放入静态框中。它在框周围提供一个边框,以及顶部的标签。 |
wxPython - 按钮
按钮窗口小部件在任何GUI 界面中使用最广泛。它捕获用户生成的单击事件。它最明显的用途是触发与其绑定的处理程序函数。
wxPython 类库提供了不同类型的按钮。有一个简单传统的按钮,wx.Button 类对象,它带有文本作为其标题。还提供了一个双状态按钮,名为wx.ToggleButton。其按下或弹起状态可以通过事件处理程序函数识别。
另一种类型的按钮,wx.BitmapButton 显示位图(图像)作为其表面的图标。
wx.Button 类和wx.ToggleButton 类的构造函数采用以下参数:
Wx.Button(parent, id, label, pos, size, style)
这些是wx.Button 类的一些重要方法:
序号 | 方法和描述 |
---|---|
1 | SetLabel() 以编程方式设置按钮的标题 |
2 | GetLabel() 返回按钮的标题 |
3 | SetDefault() 将按钮设置为顶级窗口的默认按钮。模拟按下Enter 键时的单击事件 |
wx.ToggleButton 类的两个重要方法是:
序号 | 方法和描述 |
---|---|
1 | GetValue() 返回切换按钮的状态(开/关) |
2 | SetValue() 以编程方式设置按钮的状态 |
为了创建位图按钮,首先需要根据图像文件构造位图对象。
最常用的wx.Bitmap 类构造函数的变体如下:
Wx.Bitmap(fiiename, wx.BITMAP_TYPE)
一些预定义的位图类型常量是:
wx.BITMAP_TYPE_BMP |
wx.BITMAP_TYPE_ICO |
wx.BITMAP_TYPE_CUR |
wx.BITMAP_TYPE_TIFF |
wx.BITMAP_TYPE_TIF |
wx.BITMAP_TYPE_GIF |
wx.BITMAP_TYPE_PNG |
wx.BITMAP_TYPE_JPEG |
wx.BITMAP_TYPE_PCX |
wx.BITMAP_TYPE_ICON |
wx.BITMAP_TYPE_ANY |
此位图对象用作wx.BitmapButton 类构造函数的参数之一。
Wx.BitmapButton(parent, id, bitmap, pos, size, style)
在某些操作系统平台上,位图按钮可以同时显示位图和标签。SetLabel() 方法分配标题。在其他平台上,它用作内部标签。
普通按钮和位图按钮都会发出wx.CommandEvent。EVT_BUTTON 绑定器将处理程序函数与其关联。
另一方面,切换按钮使用wx.TOGGLEBUTTON 绑定器进行事件处理。
在以下示例中,所有三种类型的按钮都放置在面板的垂直box sizer 中。
使用以下语句创建简单的按钮对象:
self.btn = wx.Button(panel, -1, "click Me")
切换按钮由以下语句构造:
self.tbtn = wx.ToggleButton(panel , -1, "click to on")
这些按钮使用以下语句添加到垂直sizer 中:
vbox.Add(self.btn,0,wx.ALIGN_CENTER) vbox.Add(self.tbtn,0,wx.EXPAND|wx.ALIGN_CENTER)
注意:由于wx.EXPAND 标志,切换按钮占据了框架的整个宽度。
使用EVT_BUTTON 和EVT_TOGGLEBUTTON 绑定器,它们与各自的处理程序关联。
self.btn.Bind(wx.EVT_BUTTON,self.OnClicked) self.tbtn.Bind(wx.EVT_TOGGLEBUTTON,self.OnToggle)
三个位图按钮添加到水平box sizer 中。这些按钮显示图像作为其标题的图标。
bmp = wx.Bitmap("NEW.BMP", wx.BITMAP_TYPE_BMP) self.bmpbtn = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp, size = (bmp.GetWidth()+10, bmp.GetHeight()+10)) bmp1 = wx.Bitmap("OPEN.BMP", wx.BITMAP_TYPE_BMP) self.bmpbtn1 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp1, size = (bmp.GetWidth()+10, bmp.GetHeight()+10)) bmp2 = wx.Bitmap("SAVE.BMP", wx.BITMAP_TYPE_BMP) self.bmpbtn2 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp2, size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
这三个按钮的单击事件定向到OnClicked() 方法。
self.bmpbtn.Bind(wx.EVT_BUTTON, self.OnClicked) self.bmpbtn1.Bind(wx.EVT_BUTTON, self.OnClicked) self.bmpbtn2.Bind(wx.EVT_BUTTON, self.OnClicked)
这些按钮的内部标签分别设置为NEW、OPEN 和SAVE。
OnClicked() 事件处理程序函数检索导致单击事件的源按钮的标签。该标签将打印在控制台上。
def OnClicked(self, event): btn = event.GetEventObject().GetLabel() print "Label of pressed button = ",btn
单击切换按钮时,将触发OnToggle() 事件处理程序。其状态由GetValue() 方法读取,并据此设置按钮的标题。
def OnToggle(self,event): state = event.GetEventObject().GetValue() if state == True: print "off" event.GetEventObject().SetLabel("click to off") else: print "on" event.GetEventObject().SetLabel("click to on")
完整的代码清单如下:
import wx class Mywin(wx.Frame): def __init__(self, parent, title): super(Mywin, self).__init__(parent, title = title,size = (200,150)) panel = wx.Panel(self) vbox = wx.BoxSizer(wx.VERTICAL) self.btn = wx.Button(panel,-1,"click Me") vbox.Add(self.btn,0,wx.ALIGN_CENTER) self.btn.Bind(wx.EVT_BUTTON,self.OnClicked) self.tbtn = wx.ToggleButton(panel , -1, "click to on") vbox.Add(self.tbtn,0,wx.EXPAND|wx.ALIGN_CENTER) self.tbtn.Bind(wx.EVT_TOGGLEBUTTON,self.OnToggle) hbox = wx.BoxSizer(wx.HORIZONTAL) bmp = wx.Bitmap("NEW.BMP", wx.BITMAP_TYPE_BMP) self.bmpbtn = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp, size = (bmp.GetWidth()+10, bmp.GetHeight()+10)) hbox.Add(self.bmpbtn,0,wx.ALIGN_CENTER) self.bmpbtn.Bind(wx.EVT_BUTTON,self.OnClicked) self.bmpbtn.SetLabel("NEW") bmp1 = wx.Bitmap("OPEN.BMP", wx.BITMAP_TYPE_BMP) self.bmpbtn1 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp1, size = (bmp.GetWidth()+10, bmp.GetHeight()+10)) hbox.Add(self.bmpbtn1,0,wx.ALIGN_CENTER) self.bmpbtn1.Bind(wx.EVT_BUTTON,self.OnClicked) self.bmpbtn1.SetLabel("OPEN") bmp2 = wx.Bitmap("SAVE.BMP", wx.BITMAP_TYPE_BMP) self.bmpbtn2 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp2, size = (bmp.GetWidth()+10, bmp.GetHeight()+10)) hbox.Add(self.bmpbtn2,0,wx.ALIGN_CENTER) self.bmpbtn2.Bind(wx.EVT_BUTTON,self.OnClicked) self.bmpbtn2.SetLabel("SAVE") vbox.Add(hbox,1,wx.ALIGN_CENTER) panel.SetSizer(vbox) self.Centre() self.Show() self.Fit() def OnClicked(self, event): btn = event.GetEventObject().GetLabel() print "Label of pressed button = ",btn def OnToggle(self,event): state = event.GetEventObject().GetValue() if state == True: print "Toggle button state off" event.GetEventObject().SetLabel("click to off") else: print " Toggle button state on" event.GetEventObject().SetLabel("click to on") app = wx.App() Mywin(None, 'Button demo') app.MainLoop()
上述代码产生以下输出:
按下按钮的标签 = click Me
切换按钮状态关闭
切换按钮状态打开
按下按钮的标签 = NEW
按下按钮的标签 = OPEN
按下按钮的标签 = SAVE
wxPython - 可停靠窗口
wxAui 是wxWidgets API 中集成的先进用户界面库。Wx.aui.AuiManager 是AUI 框架中的核心类。
AuiManager 使用每个面板在wx.aui.AuiPanelInfo 对象中的信息来管理与特定框架关联的面板。让我们了解PanelInfo 对象控制对接和浮动行为的各种属性。
将可停靠窗口放在顶级框架中涉及以下步骤:
首先,创建一个AuiManager 对象。
self.mgr = wx.aui.AuiManager(self)
然后,设计一个具有所需控件的面板。
pnl = wx.Panel(self) pbox = wx.BoxSizer(wx.HORIZONTAL) text1 = wx.TextCtrl(pnl, -1, "Dockable", style = wx.NO_BORDER | wx.TE_MULTILINE) pbox.Add(text1, 1, flag = wx.EXPAND) pnl.SetSizer(pbox)
设置AuiPanelInfo 的以下参数。
方向:顶部、底部、左侧、右侧或中心
位置:多个面板可以放置在一个可停靠区域内。每个都给出一个位置编号。
行:多个面板显示在一行中。就像多条工具栏出现在同一行中一样。
层:面板可以分层放置。
使用此PanelInfo,将设计的面板添加到管理器对象中。
info1 = wx.aui.AuiPaneInfo().Bottom() self.mgr.AddPane(pnl,info1)
其余的顶级窗口可以像往常一样拥有其他控件。
完整的代码如下:
import wx import wx.aui class Mywin(wx.Frame): def __init__(self, parent, title): super(Mywin, self).__init__(parent, title = title, size = (300,300)) self.mgr = wx.aui.AuiManager(self) pnl = wx.Panel(self) pbox = wx.BoxSizer(wx.HORIZONTAL) text1 = wx.TextCtrl(pnl, -1, "Dockable", style = wx.NO_BORDER | wx.TE_MULTILINE) pbox.Add(text1, 1, flag = wx.EXPAND) pnl.SetSizer(pbox) info1 = wx.aui.AuiPaneInfo().Bottom() self.mgr.AddPane(pnl, info1) panel = wx.Panel(self) text2 = wx.TextCtrl(panel, size = (300,200), style = wx.NO_BORDER | wx.TE_MULTILINE) box = wx.BoxSizer(wx.HORIZONTAL) box.Add(text2, 1, flag = wx.EXPAND) panel.SetSizerAndFit(box) self.mgr.Update() self.Bind(wx.EVT_CLOSE, self.OnClose) self.Centre() self.Show(True) def OnClose(self, event): self.mgr.UnInit() self.Destroy() app = wx.App() Mywin(None,"Dock Demo") app.MainLoop()
上述代码产生以下输出:
wxPython - 多文档界面
典型的GUI 应用程序可能有多个窗口。选项卡式和堆叠式窗口小部件允许一次激活一个这样的窗口。但是,很多时候这种方法可能不起作用,因为其他窗口的视图被隐藏了。
同时显示多个窗口的一种方法是将它们创建为独立窗口。这称为SDI(单文档界面)。这需要更多内存资源,因为每个窗口可能都有自己的菜单系统、工具栏等。
wxPython 中的MDI 框架提供了一个wx.MDIParentFrame 类。其对象充当多个子窗口的容器,每个子窗口都是wx.MDIChildFrame 类的对象。
子窗口位于父框架的MDIClientWindow 区域中。添加子框架后,父框架的菜单栏会显示一个“窗口”菜单,其中包含以级联或平铺方式排列子窗口的按钮。
示例
以下示例说明了使用MDIParentFrame 作为顶级窗口。名为NewWindow 的菜单按钮在客户端区域中添加一个子窗口。可以添加多个窗口,然后以级联或平铺顺序排列。
完整的代码如下:
import wx class MDIFrame(wx.MDIParentFrame): def __init__(self): wx.MDIParentFrame.__init__(self, None, -1, "MDI Parent", size = (600,400)) menu = wx.Menu() menu.Append(5000, "&New Window") menu.Append(5001, "&Exit") menubar = wx.MenuBar() menubar.Append(menu, "&File") self.SetMenuBar(menubar) self.Bind(wx.EVT_MENU, self.OnNewWindow, id = 5000) self.Bind(wx.EVT_MENU, self.OnExit, id = 5001) def OnExit(self, evt): self.Close(True) def OnNewWindow(self, evt): win = wx.MDIChildFrame(self, -1, "Child Window") win.Show(True) app = wx.App() frame = MDIFrame() frame.Show() app.MainLoop()
上述代码产生以下输出:
wxPython - 绘图API
GDI+(图形绘制接口)、CoreGraphics 和Cairo 库构成了wxPython 中绘图API 的框架。wx.GraphicsContext 是主要的绘图对象,使用它可以创建各种设备上下文对象。
wx.DC 是一个抽象类。它的派生类用于在不同设备上呈现图形和文本。设备上下文类是:
wx.ScreenDC:使用它在屏幕上绘图,而不是单个窗口。
wx.ClientDC:使用它在窗口的客户端区域(没有边框和其他装饰的部分)上绘图,但在wxPaintEvent 中不要使用它。
wx.PaintDC:使用它在窗口的客户端区域上绘图,但仅在wxPaintEvent 中使用。
wx.WindowDC:使用它在窗口的整个区域(包括装饰)上绘图。这在非Windows 平台上可能不可用。
wxPython 的绘图 API 提供了绘制形状、文本和图像的不同函数。绘图所需的 Colour、Pen、Brush 和 Font 等对象也可以使用 GDI 类构造。
wx.Colour 类
Colour 对象表示 RGB(红、绿、蓝)强度值的组合,每个值的范围都是 0-255。有一些预定义的颜色对象,例如:
- wxBLACK
- wxBLUE
- wxCYAN
- wxGREEN
- wxYELLOW
- wxLIGHT_GREY
- wxRED
- wxWHITE
可以使用自定义的 RGB 值组合来创建wx.Colour 对象。
wx.Colour(r,g,b)
wx.Pen 类
Pen 对象确定图形(如线、矩形、圆形等)的形状的颜色、宽度和样式。
预定义的 Pen 对象有:
wxBLACK_DASHED_PEN |
wxBLACK_PEN |
wxBLUE_PEN |
wxCYAN_PEN |
wxGREEN_PEN |
wxYELLOW_PEN |
wxGREY_PEN |
wxLIGHT_GREY_PEN |
wxMEDIUM_GREY_PEN |
wxRED_PEN |
wxTRANSPARENT_PEN |
wxWHITE_PEN |
预定义的 Pen 样式有:
wx.SOLID |
wx.DOT |
wx.LONG_DASH |
wx.SHORT_DASH |
wx.DOT_DASH |
wx.TRANSPARENT |
wx.Brush 类
Brush 是另一个基本的图形对象,用于填充矩形、椭圆形、圆形等形状的背景。
自定义 Brush 对象需要 wx.Colour 和 Brush 样式参数。以下是预定义的笔刷样式列表:
wx.SOLID |
wx.STIPPLE |
wx.BDIAGONAL_HATCH |
wx.CROSSDIAG_HATCH |
wx.FDIAGONAL_HATCH |
wx.CROSS_HATCH |
wx.HORIZONTAL_HATCH |
wx.VERTICAL_HATCH |
wx.TRANSPARENT |
wxPython 有许多函数可以方便地绘制不同的形状、文本和图像。
序号 | 函数和描述 |
---|---|
1 | DrawRectangle() 绘制给定尺寸的矩形 |
2 | DrawCircle() 在给定中心点和半径处绘制一个圆形 |
3 | DrawEllipse() 绘制给定 x 和 y 半径的椭圆形 |
4 | DrawLine() 绘制两个 wx.Point 对象之间的直线 |
5 | DrawBitmap() 在给定位置绘制图像 |
6 | DrawText() 在指定位置显示给定的文本 |
示例
以下示例中实现了上述函数,并使用了 Pen、Brush、Colour 和 Font 对象。
完整的代码如下:
import wx class Mywin(wx.Frame): def __init__(self, parent, title): super(Mywin, self).__init__(parent, title = title,size = (500,300)) self.InitUI() def InitUI(self): self.Bind(wx.EVT_PAINT, self.OnPaint) self.Centre() self.Show(True) def OnPaint(self, e): dc = wx.PaintDC(self) brush = wx.Brush("white") dc.SetBackground(brush) dc.Clear() dc.DrawBitmap(wx.Bitmap("python.jpg"),10,10,True) color = wx.Colour(255,0,0) b = wx.Brush(color) dc.SetBrush(b) dc.DrawCircle(300,125,50) dc.SetBrush(wx.Brush(wx.Colour(255,255,255))) dc.DrawCircle(300,125,30) font = wx.Font(18, wx.ROMAN, wx.ITALIC, wx.NORMAL) dc.SetFont(font) dc.DrawText("Hello wxPython",200,10) pen = wx.Pen(wx.Colour(0,0,255)) dc.SetPen(pen) dc.DrawLine(200,50,350,50) dc.SetBrush(wx.Brush(wx.Colour(0,255,0), wx.CROSS_HATCH)) dc.DrawRectangle(380, 15, 90, 60) ex = wx.App() Mywin(None,'Drawing demo') ex.MainLoop()
上述代码产生以下输出:
wxPython - 拖放
拖放功能对于用户来说非常直观。在许多桌面应用程序中都可以找到它,用户只需用鼠标拖动对象并将其放在另一个窗口上,即可将对象从一个窗口复制或移动到另一个窗口。
拖放操作包括以下步骤:
- 声明一个放置目标
- 创建数据对象
- 创建 wx.DropSource
- 执行拖动操作
- 取消或接受放置
在 wxPython 中,有两个预定义的放置目标:
- wx.TextDropTarget
- wx.FileDropTarget
许多 wxPython 小部件支持拖放活动。源控件必须启用拖动,而目标控件必须能够接受(或拒绝)拖动。
用户正在拖动的源数据被放置在目标对象上。目标对象的 OnDropText() 消耗数据。如果需要,可以删除源对象中的数据。
示例
在以下示例中,两个 ListCtrl 对象水平放置在一个 Box Sizer 中。左侧列表填充了 languages[] 数据。它被指定为拖动的源。右侧列表是目标。
languages = ['C', 'C++', 'Java', 'Python', 'Perl', 'JavaScript', 'PHP', 'VB.NET','C#'] self.lst1 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) self.lst2 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) for lang in languages: self.lst1.InsertStringItem(0,lang)
第二个列表控件为空,是 TextDropTarget 类对象的参数。
class MyTextDropTarget(wx.TextDropTarget): def __init__(self, object): wx.TextDropTarget.__init__(self) self.object = object def OnDropText(self, x, y, data): self.object.InsertStringItem(0, data)
OnDropText() 方法将源数据添加到目标列表控件中。
拖动操作由事件绑定器初始化。
wx.EVT_LIST_BEGIN_DRAG(self, self.lst1.GetId(), self.OnDragInit)
OnDragInit() 函数将拖动数据放在目标上并从源中删除。
def OnDragInit(self, event): text = self.lst1.GetItemText(event.GetIndex()) tobj = wx.PyTextDataObject(text) src = wx.DropSource(self.lst1) src.SetData(tobj) src.DoDragDrop(True) self.lst1.DeleteItem(event.GetIndex())
完整的代码如下:
import wx class MyTarget(wx.TextDropTarget): def __init__(self, object): wx.TextDropTarget.__init__(self) self.object = object def OnDropText(self, x, y, data): self.object.InsertStringItem(0, data) class Mywin(wx.Frame): def __init__(self, parent, title): super(Mywin, self).__init__(parent, title = title,size = (-1,300)) panel = wx.Panel(self) box = wx.BoxSizer(wx.HORIZONTAL) languages = ['C', 'C++', 'Java', 'Python', 'Perl', 'JavaScript', 'PHP', 'VB.NET','C#'] self.lst1 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) self.lst2 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) for lang in languages: self.lst1.InsertStringItem(0,lang) dt = MyTarget(self.lst2) self.lst2.SetDropTarget(dt) wx.EVT_LIST_BEGIN_DRAG(self, self.lst1.GetId(), self.OnDragInit) box.Add(self.lst1,0,wx.EXPAND) box.Add(self.lst2, 1, wx.EXPAND) panel.SetSizer(box) panel.Fit() self.Centre() self.Show(True) def OnDragInit(self, event): text = self.lst1.GetItemText(event.GetIndex()) tobj = wx.PyTextDataObject(text) src = wx.DropSource(self.lst1) src.SetData(tobj) src.DoDragDrop(True) self.lst1.DeleteItem(event.GetIndex()) ex = wx.App() Mywin(None,'Drag&Drop Demo') ex.MainLoop()
上述代码产生以下输出: