# wxPython 中的应用框架

> 原文： [http://zetcode.com/wxpython/skeletons/](http://zetcode.com/wxpython/skeletons/)

在本节中，我们将创建一些应用框架。 我们的脚本将制定出接口，但不会实现该功能。 目的是展示如何在 wxPython 中完成几个众所周知的 GUI 界面。

## 文件管理器

文件监视器是文件管理器的骨架。 它复制了 Krusader 的监视，Krusader 是 Unix 系统上可用的文件管理器。 如果我们双击拆分器小部件，它将把文件监视器分成宽度相同的两个部分。 如果我们调整主窗口的大小，也会发生同样的情况。

`file_hunter.py`

```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
ZetCode wxPython tutorial

This program creates a skeleton
of a file manager UI.

author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""

import wx
import os
import time

ID_BUTTON=100
ID_EXIT=200
ID_SPLITTER=300

class MyListCtrl(wx.ListCtrl):

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

        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.InsertItem(0, '..')
        self.SetItemImage(0, 5)

        files = os.listdir('.')

        for i in files:

            (name, ext) = os.path.splitext(i)
            ex = ext[1:]
            size = os.path.getsize(i)
            sec = os.path.getmtime(i)

            self.InsertItem(j, name)
            self.SetItem(j, 1, ex)
            self.SetItem(j, 2, str(size) + ' B')
            self.SetItem(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 Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

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

        p1 = MyListCtrl(self.splitter)
        p2 = MyListCtrl(self.splitter)
        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)

        tb.AddTool(10, 'Previous', wx.Bitmap('images/previous.png'), shortHelp='Previous')
        tb.AddTool(20, 'Up', wx.Bitmap('images/up.png'), shortHelp='Up one directory')
        tb.AddTool(30, 'Home', wx.Bitmap('images/home.png'), shortHelp='Home')
        tb.AddTool(40, 'Refresh', wx.Bitmap('images/refresh.png'), shortHelp='Refresh')
        tb.AddSeparator()
        tb.AddTool(50, 'Edit text', wx.Bitmap('images/textedit.png'), shortHelp='Edit text')
        tb.AddTool(60, 'Terminal', wx.Bitmap('images/terminal.png'), shortHelp='Terminal')
        tb.AddSeparator()
        tb.AddTool(70, 'Help', wx.Bitmap('images/help.png'), shortHelp='Show 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)

        sb = self.CreateStatusBar()
        sb.SetStatusText(os.getcwd())

        self.SetTitle("File Hunter")
        self.Center()

    def OnExit(self, e):

        self.Close(True)

    def OnSize(self, e):

        size = self.GetSize()
        self.splitter.SetSashPosition(size.x / 2)

        e.Skip()

    def OnDoubleClick(self, e):

        size =  self.GetSize()
        self.splitter.SetSashPosition(size.x / 2)

def main():

    app = wx.App()
    ex = Example(None)
    ex.Show()
    app.MainLoop()

if __name__ == '__main__':
    main()

```

该示例创建一个两面板文件管理器的 UI。

```py
class MyListCtrl(wx.ListCtrl):

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

```

应用的主要区域被`wx.ListCtrl`小部件占据。

```py
self.il = wx.ImageList(16, 16)

for i in images:

    self.il.Add(wx.Bitmap(i))

self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)

```

列表控件包含一个列表图像，用于指示文件类型。

```py
files = os.listdir('.')

for i in files:

    (name, ext) = os.path.splitext(i)
    ex = ext[1:]
    size = os.path.getsize(i)
    sec = os.path.getmtime(i)
    ...

```

我们获取当前工作目录的内容，并确定文件扩展名，大小和最后修改时间。

```py
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)

```

根据文件扩展名选择文件的图像。

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

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

```

我们有两个列表控件，这些控件由拆分器小部件垂直拆分。

```py
menuBar = wx.MenuBar()
menuBar.Append(filemenu, "&File")
menuBar.Append(editmenu, "&Edit")
...

```

我们有一个菜单栏。

```py
tb = self.CreateToolBar( wx.TB_HORIZONTAL | wx.NO_BORDER |
      wx.TB_FLAT)

tb.AddTool(10, 'Previous', wx.Bitmap('images/previous.png'), shortHelp='Previous')
tb.AddTool(20, 'Up', wx.Bitmap('images/up.png'), shortHelp='Up one directory')
...

```

我们有一个工具栏。

```py
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")
...

```

八个按钮放置在水平大小调整器中，该大小调整器添加到窗口底部。

![File manager](img/02f5baffb280f24ec575ee05da01ab6c.jpg)

Figure: File manager

## 电子表格

下面的示例创建电子表格应用的 UI。

`spreadsheet.py`

```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
ZetCode wxPython tutorial

This program creates a SpreadSheet UI.

author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""

from wx.lib import sheet
import wx

class MySheet(wx.grid.Grid):

    def __init__(self, *args, **kw):
        super(MySheet, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        nOfRows = 55
        nOfCols = 25

        self.row = self.col = 0
        self.CreateGrid(nOfRows, nOfCols)

        self.SetColLabelSize(20)
        self.SetRowLabelSize(50)

        self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnGridSelectCell)

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

        for i in range(nOfCols):
            self.SetColSize(i, 75)

    def OnGridSelectCell(self, e):

        self.row, self.col = e.GetRow(), e.GetCol()

        control = self.GetParent().GetParent().position
        value =  self.GetColLabelValue(self.col) + self.GetRowLabelValue(self.row)
        control.SetValue(value)

        e.Skip()

class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        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, style= wx.TB_HORIZONTAL)

        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/new.png'))
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/open.png'))
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/save.png'))

        toolbar1.AddSeparator()

        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/cut.png'))
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/copy.png'))
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/paste.png'))
        toolbar1.AddTool(wx.ID_ANY, '',  wx.Bitmap('images/delete.png'))

        toolbar1.AddSeparator()

        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/undo.png'))
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/redo.png'))

        toolbar1.AddSeparator()

        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/asc.png'))
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/desc.png'))

        toolbar1.AddSeparator()
        toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/chart.png'))

        toolbar1.AddSeparator()
        toolbar1.AddTool(wx.ID_ANY, '',  wx.Bitmap('images/exit.png'))

        toolbar1.Realize()

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

        self.position = wx.TextCtrl(toolbar2)

        font = wx.ComboBox(toolbar2, value='Times', choices=fonts, size=(100, -1),
                style=wx.CB_DROPDOWN)

        font_height = wx.ComboBox(toolbar2, 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()

        toolbar2.AddCheckTool(wx.ID_ANY, '', wx.Bitmap('images/text-bold.png'))
        toolbar2.AddCheckTool(wx.ID_ANY, '', wx.Bitmap('images/text-italic.png'))
        toolbar2.AddCheckTool(wx.ID_ANY, '', wx.Bitmap('images/text-underline.png'))

        toolbar2.AddSeparator()

        toolbar2.AddTool(wx.ID_ANY, '', wx.Bitmap('images/align-left.png'))
        toolbar2.AddTool(wx.ID_ANY, '', wx.Bitmap('images/align-center.png'))
        toolbar2.AddTool(wx.ID_ANY, '', wx.Bitmap('images/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, 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.SetSize((550, 550))
        self.SetTitle("SpreadSheet")
        self.Centre()

def main():

    app = wx.App()
    ex = Example(None)
    ex.Show()
    app.MainLoop()

if __name__ == '__main__':
    main()

```

该代码示例创建电子表格应用的 UI。 我有一个菜单栏，工具栏和一个中央网格小部件。

```py
class MySheet(wx.grid.Grid):

    def __init__(self, *args, **kw):
        super(MySheet, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        nOfRows = 55
        nOfCols = 25

        self.row = self.col = 0
        self.CreateGrid(nOfRows, nOfCols)
        ...

```

我们创建一个自定义的`wx.grid.Grid`小部件。 我们的每个工作表将有 55 行和 25 列。 用`CreateGrid()`方法创建一个单元格网格。

```py
control = self.GetParent().GetParent().position

```

位置文本控件显示了网格小部件的选定单元格。 它是第二个工具栏的第一个小部件。 在`Example`类内部，我们需要获取对文本控件的引用，该引用在`Example`类中定义。 `MySheet`是笔记本的子项。 笔记本是`Example`的子项。 因此，通过两次调用`GetParent()`方法，我们设法到达了位置文本控件。

```py
notebook = wx.Notebook(self, 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')

```

将创建三张纸并将其放置在笔记本小部件中。

![Spreadsheet](img/f02dc5b88179403054b76eb0e9772ac6.jpg)

Figure: Spreadsheet

## 播放器

以下示例是典型视频播放器的框架。

`player.py`

```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
ZetCode wxPython tutorial

This program creates a Player UI.

author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""

import wx

class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        self.CreateMenuBar()

        panel = wx.Panel(self)

        pnl1 = wx.Panel(self)
        pnl1.SetBackgroundColour(wx.BLACK)
        pnl2 = wx.Panel(self)

        slider1 = wx.Slider(pnl2, value=18, minValue=0, maxValue=1000)
        pause = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/pause.png'))
        play  = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/play.png'))
        forw  = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/forw.png'))
        back  = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/back.png'))
        vol = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/volume.png'))
        slider2 = wx.Slider(pnl2, value=1, minValue=0, maxValue=100,
            size=(120, -1))

        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)

        hbox1.Add(slider1, proportion=1)
        hbox2.Add(pause)
        hbox2.Add(play, flag=wx.RIGHT, border=5)
        hbox2.Add(forw, flag=wx.LEFT, border=5)
        hbox2.Add(back)
        hbox2.Add((-1, -1), proportion=1)
        hbox2.Add(vol)
        hbox2.Add(slider2, flag=wx.TOP|wx.LEFT, border=5)

        vbox.Add(hbox1, flag=wx.EXPAND|wx.BOTTOM, border=10)
        vbox.Add(hbox2, proportion=1, flag=wx.EXPAND)
        pnl2.SetSizer(vbox)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(pnl1, proportion=1, flag=wx.EXPAND)
        sizer.Add(pnl2, flag=wx.EXPAND|wx.BOTTOM|wx.TOP, border=10)

        self.SetMinSize((350, 300))
        self.CreateStatusBar()
        self.SetSizer(sizer)

        self.SetSize((350, 200))
        self.SetTitle('Player')
        self.Centre()

    def CreateMenuBar(self):

        menubar = wx.MenuBar()
        filem = wx.Menu()
        play = wx.Menu()
        view = wx.Menu()
        tools = wx.Menu()
        favorites = wx.Menu()
        help = wx.Menu()

        filem.Append(wx.ID_ANY, '&Quit', 'Quit application')

        menubar.Append(filem, '&File')
        menubar.Append(play, '&Play')
        menubar.Append(view, '&View')
        menubar.Append(tools, '&Tools')
        menubar.Append(favorites, 'F&avorites')
        menubar.Append(help, '&Help')

        self.SetMenuBar(menubar)

def main():

    app = wx.App()
    ex = Example(None)
    ex.Show()
    app.MainLoop()

if __name__ == '__main__':
    main()  

```

为了构建界面，我们使用了位图按钮，滑块，面板和菜单栏。

```py
pnl1 = wx.Panel(self)
pnl1.SetBackgroundColour(wx.BLACK)

```

应用的主要区域由黑色背景的面板占据。

```py
slider1 = wx.Slider(pnl2, value=18, minValue=0, maxValue=1000)

```

`wx.Slider`用于显示胶片的进度。

```py
pause = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/pause.png'))
play  = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/play.png'))

```

位图按钮用于控制按钮。

```py
self.SetMinSize((350, 300))

```

在这里，我们设置播放器的最小大小。 将窗口缩小到某个值以下没有太大意义。

![Player](img/6abc7333235b3a495d465af00d14475a.jpg)

Figure: Player

## 浏览器

在下面的示例中，我们模仿经典浏览器 UI 的外观。

`browser.py`

```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
ZetCode wxPython tutorial

This program creates a browser UI.

author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""

import wx
from wx.lib.buttons import GenBitmapTextButton

class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):

        self.CreateMenuBar()

        panel = wx.Panel(self)
        # panel.SetBackgroundColour('white')

        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)

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

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

        back = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/back.png'),
                style=wx.NO_BORDER)
        forward = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/forw.png'),
                style=wx.NO_BORDER)
        refresh = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/refresh.png'),
                style=wx.NO_BORDER)
        stop = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/stop.png'),
                style=wx.NO_BORDER)
        home = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/home.png'),
                style=wx.NO_BORDER)
        address = wx.ComboBox(toolbar1, size=(50, -1))
        go = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/play.png'),
                style=wx.NO_BORDER)
        text = wx.TextCtrl(toolbar1, size=(150, -1))

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

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

        toolbar2 = wx.Panel(panel, size=(-1, 30))
        bookmark1 = wx.BitmapButton(toolbar2, bitmap=wx.Bitmap('images/love.png'),
                style=wx.NO_BORDER)
        bookmark2 = wx.BitmapButton(toolbar2, bitmap=wx.Bitmap('images/book.png'),
                style=wx.NO_BORDER)
        bookmark3 = wx.BitmapButton(toolbar2, bitmap=wx.Bitmap('images/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)

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

        panel.SetSizer(vbox)

        self.CreateStatusBar()

        self.SetTitle("Browser")
        self.Centre()

    def CreateMenuBar(self):

        menubar = wx.MenuBar()
        file = wx.Menu()
        file.Append(wx.ID_ANY, '&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)

def main():

    app = wx.App()
    ex = Example(None)
    ex.Show()
    app.MainLoop()

if __name__ == '__main__':
    main()

```

为了创建一个较大的组合框，我们不能使用`wx.Toolbar`。 我们基于`wx.Panel`创建自定义工具栏。

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

```

我们创建一个普通的`wx.Panel`。

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

```

我们创建一个水平大小调整器，并添加所有必要的按钮。

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

```

然后，将组合框添加到大小调整器。 这种组合框通常称为地址栏。 请注意，这是唯一将比例设置为 1 的小部件。这是使其可调整大小的必要条件。

```py
line2 = wx.StaticLine(panel)
vbox.Add(line2, 0, wx.EXPAND)

```

工具栏由一行分隔。

![Browser UI](img/48142a1ee2caa247df00f6ff4674489e.jpg)

Figure: Browser UI

在 wxPython 教程的这一部分中，我们创建了一些应用框架。