Ross Wan's World!

Python, Ajax, PHP and Linux.

wxPython:界面框架(Skeletons)

Posted by Ross Wan 于 2008/04/30

       在这个章节,我们将会创建一些程序框架,注意,这仅仅涉及到程序的界面,并没有实现程序的具体功能。当中,主要介绍一些著名的程序界面在 wxPython 中是如何实现的。

文件管理器(Fiel Manager)

       下面将创建一个名为“File Hunter”的文件管理器,它的界面仿照了 Unix 著名的文件管理器 Krusader。如果双击 spliter 控件,窗口会被拆分成等宽的两部分。

#!/usr/bin/python

import wx
import os
import time

ID_BUTTON=100
ID_EXIT=200
ID_SPLITTER=300

class MyListCtrl(wx.ListCtrl):
    def __init__(self, parent, id):
        wx.ListCtrl.__init__(self, parent, id, style=wx.LC_REPORT)

        files = os.listdir(‘.’)
        images = [‘images/empty.png’, ‘images/folder.png’, ‘images/source_py.png’,
        ‘images/image.png’, ‘images/pdf.png’, ‘images/up16.png’]

        self.InsertColumn(0, ‘Name’)
        self.InsertColumn(1, ‘Ext’)
        self.InsertColumn(2, ‘Size’, wx.LIST_FORMAT_RIGHT)
        self.InsertColumn(3, ‘Modified’)

        self.SetColumnWidth(0, 220)
        self.SetColumnWidth(1, 70)
        self.SetColumnWidth(2, 100)
        self.SetColumnWidth(3, 420)

        self.il = wx.ImageList(16, 16)
        for i in images:
            self.il.Add(wx.Bitmap(i))
        self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)

        j = 1
        self.InsertStringItem(0, ‘..’)
        self.SetItemImage(0, 5)

        for i in files:
            (name, ext) = os.path.splitext(i)
            ex = ext[1:]
            size = os.path.getsize(i)
            sec = os.path.getmtime(i)
            self.InsertStringItem(j, name)
            self.SetStringItem(j, 1, ex)
            self.SetStringItem(j, 2, str(size) + ‘ B’)
            self.SetStringItem(j, 3, time.strftime(‘%Y-%m-%d %H:%M’,
        time.localtime(sec)))

            if os.path.isdir(i):
                self.SetItemImage(j, 1)
            elif ex == ‘py’:
                self.SetItemImage(j, 2)
            elif ex == ‘jpg’:
                self.SetItemImage(j, 3)
            elif ex == ‘pdf’:
                self.SetItemImage(j, 4)
            else:
                self.SetItemImage(j, 0)

            if (j % 2) == 0:
                self.SetItemBackgroundColour(j, ‘#e6f1f5’)
            j = j + 1

class FileHunter(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, -1, title)

        self.splitter = wx.SplitterWindow(self, ID_SPLITTER, style=wx.SP_BORDER)
        self.splitter.SetMinimumPaneSize(50)

        p1 = MyListCtrl(self.splitter, -1)
        p2 = MyListCtrl(self.splitter, -1)
        self.splitter.SplitVertically(p1, p2)

        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_SPLITTER_DCLICK, self.OnDoubleClick, id=ID_SPLITTER)

        filemenu= wx.Menu()
        filemenu.Append(ID_EXIT,”E&xit”,” Terminate the program”)
        editmenu = wx.Menu()
        netmenu = wx.Menu()
        showmenu = wx.Menu()
        configmenu = wx.Menu()
        helpmenu = wx.Menu()

        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,”&File”)
        menuBar.Append(editmenu, “&Edit”)
        menuBar.Append(netmenu, “&Net”)
        menuBar.Append(showmenu, “&Show”)
        menuBar.Append(configmenu, “&Config”)
        menuBar.Append(helpmenu, “&Help”)
        self.SetMenuBar(menuBar)
        self.Bind(wx.EVT_MENU, self.OnExit, id=ID_EXIT)

        tb = self.CreateToolBar( wx.TB_HORIZONTAL | wx.NO_BORDER |
        wx.TB_FLAT | wx.TB_TEXT)
        tb.AddSimpleTool(10, wx.Bitmap(‘images/previous.png’), ‘Previous’)
        tb.AddSimpleTool(20, wx.Bitmap(‘images/up.png’), ‘Up one directory’)
        tb.AddSimpleTool(30, wx.Bitmap(‘images/home.png’), ‘Home’)
        tb.AddSimpleTool(40, wx.Bitmap(‘images/refresh.png’), ‘Refresh’)
        tb.AddSeparator()
        tb.AddSimpleTool(50, wx.Bitmap(‘images/write.png’), ‘Editor’)
        tb.AddSimpleTool(60, wx.Bitmap(‘images/terminal.png’), ‘Terminal’)
        tb.AddSeparator()
        tb.AddSimpleTool(70, wx.Bitmap(‘images/help.png’), ‘Help’)
        tb.Realize()

        self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)

        button1 = wx.Button(self, ID_BUTTON + 1, “F3 View”)
        button2 = wx.Button(self, ID_BUTTON + 2, “F4 Edit”)
        button3 = wx.Button(self, ID_BUTTON + 3, “F5 Copy”)
        button4 = wx.Button(self, ID_BUTTON + 4, “F6 Move”)
        button5 = wx.Button(self, ID_BUTTON + 5, “F7 Mkdir”)
        button6 = wx.Button(self, ID_BUTTON + 6, “F8 Delete”)
        button7 = wx.Button(self, ID_BUTTON + 7, “F9 Rename”)
        button8 = wx.Button(self, ID_EXIT, “F10 Quit”)

        self.sizer2.Add(button1, 1, wx.EXPAND)
        self.sizer2.Add(button2, 1, wx.EXPAND)
        self.sizer2.Add(button3, 1, wx.EXPAND)
        self.sizer2.Add(button4, 1, wx.EXPAND)
        self.sizer2.Add(button5, 1, wx.EXPAND)
        self.sizer2.Add(button6, 1, wx.EXPAND)
        self.sizer2.Add(button7, 1, wx.EXPAND)
        self.sizer2.Add(button8, 1, wx.EXPAND)

        self.Bind(wx.EVT_BUTTON, self.OnExit, id=ID_EXIT)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.splitter,1,wx.EXPAND)
        self.sizer.Add(self.sizer2,0,wx.EXPAND)
        self.SetSizer(self.sizer)

        size = wx.DisplaySize()
        self.SetSize(size)

        self.sb = self.CreateStatusBar()
        self.sb.SetStatusText(os.getcwd())
        self.Center()
        self.Show(True)

    def OnExit(self,e):
        self.Close(True)

    def OnSize(self, event):
        size = self.GetSize()
        self.splitter.SetSashPosition(size.x / 2)
        self.sb.SetStatusText(os.getcwd())
        event.Skip()

    def OnDoubleClick(self, event):
        size =  self.GetSize()
        self.splitter.SetSashPosition(size.x / 2)

app = wx.App(0)
FileHunter(None, -1, ‘File Hunter’)
app.MainLoop()

电子数据表(SpreadSheet)

       Gnumeric,KSpread 和 OpenOffice.org Cale 都是 Unix 下的著名电子数据表程序。在下面的例子中的,我们将会利用 wxPython 来创建一个电子数据表的界面框架。

#!/usr/bin/python
# spreadsheet.py

from wx.lib import sheet
import wx

class MySheet(sheet.CSheet):
    def __init__(self, parent):
        sheet.CSheet.__init__(self, parent)
        self.row = self.col = 0
        self.SetNumberRows(55)
        self.SetNumberCols(25)

        for i in range(55):
            self.SetRowSize(i, 20)

    def OnGridSelectCell(self, event):
        self.row, self.col = event.GetRow(), event.GetCol()
        control = self.GetParent().GetParent().position
        value =  self.GetColLabelValue(self.col) + self.GetRowLabelValue(self.row)
        control.SetValue(value)
        event.Skip()

class Newt(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, -1, title, size = (550, 500))

        fonts = [‘Times New Roman’, ‘Times’, ‘Courier’, ‘Courier New’, ‘Helvetica’,
                ‘Sans’, ‘verdana’, ‘utkal’, ‘aakar’, ‘Arial’]
        font_sizes = [’10’, ’11’, ’12’, ’14’, ’16’]

        box = wx.BoxSizer(wx.VERTICAL)
        menuBar = wx.MenuBar()

        menu1 = wx.Menu()
        menuBar.Append(menu1, ‘&File’)
        menu2 = wx.Menu()
        menuBar.Append(menu2, ‘&Edit’)
        menu3 = wx.Menu()
        menuBar.Append(menu3, ‘&Edit’)
        menu4 = wx.Menu()
        menuBar.Append(menu4, ‘&Insert’)
        menu5 = wx.Menu()
        menuBar.Append(menu5, ‘F&ormat’)
        menu6 = wx.Menu()
        menuBar.Append(menu6, ‘&Tools’)
        menu7 = wx.Menu()
        menuBar.Append(menu7, ‘&Data’)
        menu8 = wx.Menu()
        menuBar.Append(menu8, ‘&Help’)

        self.SetMenuBar(menuBar)

        toolbar1 = wx.ToolBar(self, -1, style= wx.TB_HORIZONTAL)
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/stock_new.png’))
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/stock_open.png’))
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/stock_save.png’))
        toolbar1.AddSeparator()
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/stock_cut.png’))
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/stock_copy.png’))
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/stock_paste.png’))
        toolbar1.AddLabelTool(-1, ”,  wx.Bitmap(‘icons/stock_delete.png’))
        toolbar1.AddSeparator()
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/stock_undo.png’))
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/stock_redo.png’))
        toolbar1.AddSeparator()
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/incr22.png’))
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/decr22.png’))
        toolbar1.AddSeparator()
        toolbar1.AddLabelTool(-1, ”, wx.Bitmap(‘icons/chart.xpm’))
        toolbar1.AddSeparator()
        toolbar1.AddLabelTool(-1, ”,  wx.Bitmap(‘icons/stock_exit.png’))

        toolbar1.Realize()

        toolbar2 = wx.ToolBar(self, wx.TB_HORIZONTAL | wx.TB_TEXT)

        self.position = wx.TextCtrl(toolbar2)
        font = wx.ComboBox(toolbar2, -1, value = ‘Times’, choices=fonts, size=(100, -1),
                style=wx.CB_DROPDOWN)
        font_height = wx.ComboBox(toolbar2, -1, value = ’10’,  choices=font_sizes,
                size=(50, -1), style=wx.CB_DROPDOWN)

        toolbar2.AddControl(self.position)
        toolbar2.AddControl(font)
        toolbar2.AddControl(font_height)
        toolbar2.AddSeparator()
        bold = wx.Bitmap(‘icons/stock_text_bold.png’)
        toolbar2.AddCheckTool(-1, bold)
        italic = wx.Bitmap(‘icons/stock_text_italic.png’)
        toolbar2.AddCheckTool(-1, italic)
        under = wx.Bitmap(‘icons/stock_text_underline.png’)
        toolbar2.AddCheckTool(-1, under)
        toolbar2.AddSeparator()
        toolbar2.AddLabelTool(-1, ”, wx.Bitmap(‘icons/text_align_left.png’))
        toolbar2.AddLabelTool(-1, ”, wx.Bitmap(‘icons/text_align_center.png’))
        toolbar2.AddLabelTool(-1, ”, wx.Bitmap(‘icons/text_align_right.png’))

        box.Add(toolbar1, border=5)
        box.Add((5,5) , 0)
        box.Add(toolbar2)
        box.Add((5,10) , 0)

        toolbar2.Realize()
        self.SetSizer(box)
        notebook = wx.Notebook(self, -1, style=wx.RIGHT)

        sheet1 = MySheet(notebook)
        sheet2 = MySheet(notebook)
        sheet3 = MySheet(notebook)
        sheet1.SetFocus()

        notebook.AddPage(sheet1, ‘Sheet1’)
        notebook.AddPage(sheet2, ‘Sheet2’)
        notebook.AddPage(sheet3, ‘Sheet3’)

        box.Add(notebook, 1, wx.EXPAND)

        self.CreateStatusBar()
        self.Centre()
        self.Show(True)

app = wx.App()
Newt(None, -1, ‘SpreadSheet’)
app.MainLoop()

       上面大部分代码都是为了创建菜单和工具栏的,而用于创建电子表格的仅用了很少的代码。

class MySheet(sheet.CSheet):
    def __init__(self, parent):
        sheet.CSheet.__init__(self, parent)
        self.row = self.col = 0
        self.SetNumberRows(55)
        self.SetNumberCols(25)

        for i in range(55):
            self.SetRowSize(i, 20)

       MySheet 类继承了 wx.lib 模块的 CSheet 类 ──── 这是一个基本的 wx.Grid 类,仅附加了一些功能。
 

 notebook = wx.Notebook(self, -1, style=wx.RIGHT)

       这是一人目前 wxPython( on GTK+)的一个 Bug,right 实质上是 bottom,bottom 实质上是 right。

浏览器(Browser)

       在下面的例子中,我们将模仿 Firefox 创建一个网页浏览器界面框架。

#!/usr/bin/python

import wx
from wx.lib.buttons import GenBitmapTextButton

class Browser(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(450, 400))
        panel = wx.Panel(self, -1)
        panel.SetBackgroundColour(‘WHITE’)

        menubar = wx.MenuBar()
        file = wx.Menu()
        file.Append(1, ‘&Quit’, ”)
        edit = wx.Menu()
        view = wx.Menu()
        go = wx.Menu()
        bookmarks = wx.Menu()
        tools = wx.Menu()
        help = wx.Menu()

        menubar.Append(file, ‘&File’)
        menubar.Append(edit, ‘&Edit’)
        menubar.Append(view, ‘&View’)
        menubar.Append(go, ‘&Go’)
        menubar.Append(bookmarks, ‘&Bookmarks’)
        menubar.Append(tools, ‘&Tools’)
        menubar.Append(help, ‘&Help’)

        self.SetMenuBar(menubar)

        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        toolbar1 = wx.Panel(panel, -1, size=(-1, 40))
        back = wx.BitmapButton(toolbar1, -1, wx.Bitmap(‘icons/back.png’),
        style=wx.NO_BORDER)
        forward = wx.BitmapButton(toolbar1, -1, wx.Bitmap(‘icons/forward.png’),
        style=wx.NO_BORDER)
        refresh = wx.BitmapButton(toolbar1, -1, wx.Bitmap(‘icons/refresh.png’),
        style=wx.NO_BORDER)
        stop = wx.BitmapButton(toolbar1, -1, wx.Bitmap(‘icons/stop.png’),
        style=wx.NO_BORDER)
        home = wx.BitmapButton(toolbar1, -1, wx.Bitmap(‘icons/home.png’),
        style=wx.NO_BORDER)
        address = wx.ComboBox(toolbar1, -1, size=(50, -1))
        go = wx.BitmapButton(toolbar1, -1, wx.Bitmap(‘icons/go.png’),
        style=wx.NO_BORDER)
        text = wx.TextCtrl(toolbar1, -1, size=(150, -1))

        hbox1.Add(back)
        hbox1.Add(forward)
        hbox1.Add(refresh)
        hbox1.Add(stop)
        hbox1.Add(home)
        hbox1.Add(address, 1, wx.TOP, 4)
        hbox1.Add(go, 0, wx.TOP | wx.LEFT, 4)
        hbox1.Add(text, 0, wx.TOP | wx.RIGHT, 4)

        vbox.Add(toolbar1, 0, wx.EXPAND)
        line = wx.StaticLine(panel)
        vbox.Add(line, 0, wx.EXPAND)

        toolbar2 = wx.Panel(panel, -1, size=(-1, 30))
        bookmark1 = wx.BitmapButton(toolbar2, -1, wx.Bitmap(‘icons/love.png’),
        style=wx.NO_BORDER)
        bookmark2 = wx.BitmapButton(toolbar2, -1, wx.Bitmap(‘icons/books.png’),
        style=wx.NO_BORDER)
        bookmark3 = wx.BitmapButton(toolbar2, -1, wx.Bitmap(‘icons/sound.png’),
        style=wx.NO_BORDER)
        hbox2.Add(bookmark1, flag=wx.RIGHT, border=5)
        hbox2.Add(bookmark2, flag=wx.RIGHT, border=5)
        hbox2.Add(bookmark3)
        toolbar2.SetSizer(hbox2)
        vbox.Add(toolbar2, 0, wx.EXPAND)
        line = wx.StaticLine(panel)
        vbox.Add(line, 0, wx.EXPAND)

        panel.SetSizer(vbox)

        self.CreateStatusBar()
        self.Centre()
        self.Show(True)

app = wx.App(0)
Browser(None, -1, ‘Browser’)
app.MainLoop()

        程序最大的问题是如何在工具栏上创建一个可变大小的复合框(浏览器的地址栏),因此我们不能简单的使用 wx.Toolbar,因为 Robin Dunn 已经证实这是不可能的。

 toolbar1 = wx.Panel(panel, -1, size=(-1, 40))

     
       这是一个简单的技巧,我们创建一个面板来代替工具栏。

hbox1 = wx.BoxSizer(wx.HORIZONTAL)
 …
 hbox1.Add(back)
 hbox1.Add(forward)
 hbox1.Add(refresh)

       创建一个 horizontal sizer,并放置必需的按钮。

 hbox1.Add(address, 1, wx.TOP, 4)

       放置一个复合框到 sizer 上,作为浏览器的地址栏。注意,为了可重设大小,它的 proportion 参数设置为1。

       创建的第二个工具栏是一个常规的工具栏。我们用一水平直线来分隔上下两个工具栏(我们可能会尝试设置上面的面板的 borders 来实现这水平直线,但证实这也是不可能的)。

line = wx.StaticLine(panel)
Advertisements

一条回应 to “wxPython:界面框架(Skeletons)”

  1. Ross Wan said

    翻译自:The wxPython tutorial

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

 
%d 博主赞过: