wxPython学习笔记(二) 创建基本的wxPython程序

 

创建基本的wxPython程序

  • 主题:

    • 创建一个基本的wxPython程序
    • 将这个程序打造成一个简单的文本编辑器

本节将介绍如何使用wxPython构建一个小型的文本编辑器。通过这个看似复杂的任务你将会体验到wxPython有多方便和简单。

概述

  • 每当大家提前GUI编程的时候,总是会牵扯到窗体,菜单,鼠标,图标等等。或许你的第一感觉wx.Windows就对应一个显示在屏幕上的窗口,但你错了,在wxPython中,wx.Window表示任意可以显示在屏幕上的东西的对象,wx.Window这个类是所有屏幕上可见的对象的基类,诸如输入框,下拉列表都是由它派生而来。屏幕上的可见对象都有一些共同的属性和行为,比如位置,尺寸,是否可见,是否处于输入焦点等等,这些在wx.Window里面都有定义。 所以如果你要找一个类来表示窗口,就应该用继承自wx.Window的wx.Frame而不是wx.Window. wx.Frame实现了所有与屏幕相关的行为和属性(当然如果wx.Frame位于MDI中则另当别论) .要创建一个窗体,可以用wx.Frame,也可以用其子类如wx.Dialog,但不能再按照思维定势去想wx.Window了。

一个简单的例子

添加编辑控件

要编写一个文本编辑器,首先当然需要一个编辑控件,如下:
import wx
class MainWindow(wx.Frame):
""" We simply derive a new class of Frame. """
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(200,100))
self.control = wx.TextCtrl(self, 1, style=wx.TE_MULTILINE)
self.Show(True)
app = wx.PySimpleApp()
frame=MainWindow(None, wx.ID_ANY, 'Small editor')
app.MainLoop()
  • (需要注意的是这里我们定义了一个继承自wx.Frame的类,在类的初始化方法最后调用了父类的show方法,这也就不需要在额外调用show方法。) 如你所见,这段代码还是非常简洁, 我们所做的只是继承了一个wxFrame然后覆写了它的构造函数,在构造函数中新建一个简单的文本编辑框控件,就这样,就有了如下的效果图:

添加菜单栏

多数你所见到的GUI程序都有一个菜单栏和一个状态栏,下面就开始添加这两个组件:
import wx
ID_ABOUT=101
ID_EXIT=110
class MainWindow(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self,parent,wx.ID_ANY, title, size = (300,200))
self.control = wx.TextCtrl(self, 1, style=wx.TE_MULTILINE)
self.CreateStatusBar() # A Statusbar in the bottom of the window
# Setting up the menu.
filemenu= wx.Menu()
filemenu.Append(ID_ABOUT, "&About"," Information about this program")
filemenu.AppendSeparator()
filemenu.Append(ID_EXIT,"E&xit"," Terminate the program")
# Creating the menubar.
menuBar = wx.MenuBar()
menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.
self.Show(True)
app = wx.PySimpleApp()
frame = MainWindow(None, -1, "Sample editor")
app.MainLoop()

  • 菜单有了,但是点击菜单却没有任何反应,下面添加事件处理:

实战事件处理

  • 对事件做处理就是人们常说的事件处理,wxPython的一大特色就是在事件处理上有极高的灵活性。接下来我们将添加一下实战的代码,这些代码或许已经超越了基于前面一章的理解能力,所以对他们的讨论将放到后续章节。 简单的说,一个事件就是一条发送到wxPython得消息告知有什么事情发生了,需要处理了 [6].通常来说,你所要做的就是把这个事件连接到一个特定的方法,让这个方法去处理,仅仅需要调用

    EVT_*. (Also see Avoiding EVT_MENU.) 方法,如下:

    EVT_MENU(self, ID_ABOUT, self.OnAbout)
    这个函数的作用在将对菜单ID 为ID_ABOUT的事件都扔给self.OnAbout去处理。

    self.OnAbout函数可能就像下面这个样子:

    def OnAbout(self, event)

    OnAbout的参数是event对象,它所做的就是在事件发生时:

  • 跳过这个事件, 让事件在事件处理周期里转到另外的处理程序。
  • 或者处理这个事件,事件消息在被程序处理后就不会在事件处理周期继续传播。

让我们看看现在的程序:

import os
import wx
ID_ABOUT=101
ID_EXIT=110
class MainWindow(wx.Frame):
def __init__(self,parent,id,title):
 wx.Frame.__init__(self,parent,wx.ID_ANY, title, size = (200,100))
 self.control = wx.TextCtrl(self, 1, style=wx.TE_MULTILINE)
 self.CreateStatusBar() # A StatusBar in the bottom of the window
 # Setting up the menu.
 filemenu= wx.Menu()
 filemenu.Append(ID_ABOUT, "&About"," Information about this program")
 filemenu.AppendSeparator()
 filemenu.Append(ID_EXIT,"E&xit"," Terminate the program")
 # Creating the menubar.
 menuBar = wx.MenuBar()
 menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
 self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.
 wx.EVT_MENU(self, ID_ABOUT, self.OnAbout) # attach the menu-event ID_ABOUT to the
                                                    # method self.OnAbout
 wx.EVT_MENU(self, ID_EXIT, self.OnExit)   # attach the menu-event ID_EXIT to the
                                                    # method self.OnExit
 self.Show(True)
def OnAbout(self,e):
 d= wx.MessageDialog( self, " A sample editor \n"
                     " in wxPython","About Sample Editor", wx.OK)
                     # Create a message dialog box
 d.ShowModal() # Shows it
 d.Destroy() # finally destroy it when finished.
def OnExit(self,e):
 self.Close(True)  # Close the frame.
app = wx.PySimpleApp()
frame = MainWindow(None, -1, "Sample editor")
app.MainLoop()

更多有趣的东西

  • 如果一个文本编辑器不能保存用户的输入,不能打开一个已有的文档,那这个编辑器可以算一个废品。下面我们加上打开已有文档的代码,通过一个系统的文件浏览对话框打开文件:
        def OnOpen(self,e):
       """ Open a file"""
       self.dirname = ''
       dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", wx.OPEN)
       if dlg.ShowModal() == wx.ID_OK:
           self.filename=dlg.GetFilename()
           self.dirname=dlg.GetDirectory()
           f=open(os.path.join(self.dirname,self.filename),'r')
           self.control.SetValue(f.read())
           f.close()
       dlg.Destroy()
    
    • 上面的代码其实只有简单的三个步骤:
      • 首先,创建一个系统的文件浏览对话框
      • 然后,调用ShowModal方法,弹出一个模态对话框,等待用户按下OK按钮或者Cancel按钮。

      • 最后,得到用户所选择的文件夹和文件名,调用destroy方法然后销毁这个窗口
      这里没有给出怎么添加一个打开菜单并将它的事件连接到onOpen方法的代码,相信你看过上面的例子应该已经可以自己完成了。

    可能的扩展

    我们的编辑器还远远不能算是一个专业的编辑器,还有更多的技术可以用到这个编辑器上让它更专业,诸如:
    • 拖拽操作.
    • MDI (多窗口窗体)
    • Tab view/multiple files (通过标签视图显示更多文件)
    • Find/Replace dialog (查找,替换功能)
    • Print dialog (打印功能)

    • Macro-commands in python ( 在编辑器里面编写Python代码并运行)
    • etc ...

0 评论: