wxPython的基础知识

我正在尝试理解wx
Python,但是大多数文档只是以猴子看猴子的方式呈现程序,而没有解释库的基础知识.

考虑这段代码:

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, (-1, -1), wx.Size(250, 50))
        panel = wx.Panel(self, -1)
        box = wx.BoxSizer(wx.HORIZONTAL)
        box.Add(wx.Button(panel, -1, 'Button1'), 1 )
        box.Add(wx.Button(panel, -1, 'Button2'), 1 )
        box.Add(wx.Button(panel, -1, 'Button3'), 1 )
        panel.SetSizer(box)
        self.Centre()

class MyApp(wx.App):
     def OnInit(self):
         frame = MyFrame(None, -1, 'wxboxsizer.py')
         frame.Show(True)
         return True

app = MyApp(0)
app.MainLoop()

我在这里看到三个容器 –
框架,面板和盒子.

然后有三个按钮.

>有人可以解释哪个容器进入哪个容器?
>面板是否进入框架?如果是这样,它在哪里被添加到框架中?
>盒子怎么样?它会进入面板,还是面板进入面板?
>按钮去了吗?它进入了盒子吗?
>为什么panel.SetSizer()在一个地方使用而box.Add()在另一个地方使用?

最佳答案 让我们慢慢开发一个wxPython应用程序,看它是如何工作的.

这是制作wxPython应用程序所需的最少代码量.它包含一个wx.Frame(您可以将其理解为一个窗口).窗户里什么都没有. app.MainLoop()是捕获任何事件的循环,例如鼠标点击,关闭或最小化窗口.

import wx

app = wx.App()

frame = wx.Frame(None, -1, 'A Frame')
frame.Show()

app.MainLoop()

一个窗口本身不是很有趣,但仍然相当强大.我们可以添加菜单项和标题等内容,甚至可以选择无最大化按钮等样式.让我们做所有这些.

import wx

class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(Frame, self).__init__(*args, **kwargs)

        menubar = wx.MenuBar() # Create a menubar
        fileMenu = wx.Menu() # Create the file menu
        fitem = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quits application') # Add a quit line
        menubar.Append(fileMenu, '&File') # Add the File menu to the Menubar
        self.SetMenuBar(menubar) # Set the menubar as THE menu bar

        self.Bind(wx.EVT_MENU, self.OnQuit, fitem) # Bind the quit line

        self.Show() # Show the frame

    def OnQuit(self, e):
        self.Close()

app = wx.App()
Frame(None, -1, 'A Frame', style=wx.RESIZE_BORDER 
    | wx.SYSTEM_MENU | wx.CAPTION |  wx.CLOSE_BOX) # Some styles
app.MainLoop()

你会发现事情变得更加复杂一点.这实际上是为了帮助我们保持井井有条.我们将框架移动到自己的类中,并定义了一些特征.我们要求一个菜单,将菜单项绑定到关闭应用程序的OnQuit()方法.这都是最基本的层次.

我们来添加一个面板.面板就像一块黑板.它位于wx.Frame的顶部(就像黑板靠在墙上).一旦我们有了一个面板,我们就可以开始添加sizer和小部件了.

import wx

class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(Frame, self).__init__(*args, **kwargs)

        menubar = wx.MenuBar()
        fileMenu = wx.Menu()
        fitem = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quits application')
        menubar.Append(fileMenu, '&File')
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.OnQuit, fitem)

        panel = wx.Panel(self, -1) # Added a panel!

        self.Show()

    def OnQuit(self, e):
        self.Close()

app = wx.App()
Frame(None, -1, 'A Frame', style=wx.RESIZE_BORDER 
    | wx.SYSTEM_MENU | wx.CAPTION |  wx.CLOSE_BOX)
app.MainLoop()

您会发现根据您的平台略有不同.窗口现在填充,颜色较浅.那是我们的小组.现在让我们添加一些按钮.

import wx

class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(Frame, self).__init__(*args, **kwargs)

        menubar = wx.MenuBar()
        fileMenu = wx.Menu()
        fitem = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quits application')
        menubar.Append(fileMenu, '&File')
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.OnQuit, fitem)

        panel = wx.Panel(self, -1)
        btn = wx.Button(panel, label='I am a closing button.') # Add a button
        btn.Bind(wx.EVT_BUTTON, self.OnQuit) # Bind the first button to quit
        btn2 = wx.Button(panel, label='I am a do nothing button.') # Add a second

        self.Show()

    def OnQuit(self, e):
        self.Close()

app = wx.App()
Frame(None, -1, 'A Frame', style=wx.RESIZE_BORDER 
    | wx.SYSTEM_MENU | wx.CAPTION |  wx.CLOSE_BOX)
app.MainLoop()

现在我们有按钮位于面板上.但他们看起来很糟糕.他们被困在另一个之上.我们可以使用pos =(x,y)属性手动定位它们,但这非常繁琐.让我们的朋友打电话给boxsizer吧.

import wx

class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(Frame, self).__init__(*args, **kwargs)

        menubar = wx.MenuBar()
        fileMenu = wx.Menu()
        fitem = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quits application')
        menubar.Append(fileMenu, '&File')
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.OnQuit, fitem)

        panel = wx.Panel(self, -1)
        btn = wx.Button(panel, label='I am a closing button.')
        btn.Bind(wx.EVT_BUTTON, self.OnQuit)
        btn2 = wx.Button(panel, label='I am a do nothing button.')

        vbox = wx.BoxSizer(wx.VERTICAL) # Create a vertical boxsizer
        vbox.Add(btn) # Add button 1 to the sizer
        vbox.Add(btn2) # Add button 2 to the sizer

        panel.SetSizer(vbox) # Tell the panel to use this sizer as its sizer. 

        self.Show()

    def OnQuit(self, e):
        self.Close()

app = wx.App()
Frame(None, -1, 'A Frame', style=wx.RESIZE_BORDER 
    | wx.SYSTEM_MENU | wx.CAPTION |  wx.CLOSE_BOX)
app.MainLoop()

那已经好多了!让我们看一下水平sizer的样子.

import wx

class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(Frame, self).__init__(*args, **kwargs)

        menubar = wx.MenuBar()
        fileMenu = wx.Menu()
        fitem = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quits application')
        menubar.Append(fileMenu, '&File')
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.OnQuit, fitem)

        panel = wx.Panel(self, -1)
        btn = wx.Button(panel, label='I am a closing button.')
        btn.Bind(wx.EVT_BUTTON, self.OnQuit)
        btn2 = wx.Button(panel, label='I am a do nothing button.')

        vbox = wx.BoxSizer(wx.VERTICAL) # A vertical sizer
        hbox = wx.BoxSizer(wx.HORIZONTAL) # And a horizontal one?? but why?
        hbox.Add(btn) # Let's add the buttons first
        hbox.Add(btn2)

        panel.SetSizer(hbox) # see why we need to tell the panel which sizer to use? We might have two!

        self.Show()

    def OnQuit(self, e):
        self.Close()

app = wx.App()
Frame(None, -1, 'A Frame', style=wx.RESIZE_BORDER 
    | wx.SYSTEM_MENU | wx.CAPTION |  wx.CLOSE_BOX)
app.MainLoop()

有趣!请注意我如何保留我们的vbox?让我们尝试将两者结合起来.我们还需要更多按钮,也许还需要一些TextCtrls.

import wx

class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(Frame, self).__init__(*args, **kwargs)

        menubar = wx.MenuBar()
        fileMenu = wx.Menu()
        fitem = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quits application')
        menubar.Append(fileMenu, '&File')
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.OnQuit, fitem)

        panel = wx.Panel(self, -1)
        btn = wx.Button(panel, label='I am a closing button.')
        btn.Bind(wx.EVT_BUTTON, self.OnQuit)
        btn2 = wx.Button(panel, label='I am a do nothing button.')
        txt1 = wx.TextCtrl(panel, size=(140,-1))
        txt2 = wx.TextCtrl(panel, size=(140,-1))
        txt3 = wx.TextCtrl(panel, size=(140,-1))
        btn3 = wx.Button(panel, label='I am a happy button.')
        btn4 = wx.Button(panel, label='I am a bacon button.')
        btn5 = wx.Button(panel, label='I am a python button.')


        # So many sizers! 
        vbox = wx.BoxSizer(wx.VERTICAL) 
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        hbox4 = wx.BoxSizer(wx.HORIZONTAL)
        hbox1.Add(btn)
        hbox1.Add(btn2)
        hbox1.Add(txt1)
        hbox2.Add(txt2)
        hbox2.Add(txt3)
        hbox2.Add(btn3)
        hbox3.Add(btn4)
        hbox4.Add(btn5)
        vbox.Add(hbox1)
        vbox.Add(hbox2)
        vbox.Add(hbox3)
        vbox.Add(hbox4)

        panel.SetSizer(vbox)

        self.Show()

    def OnQuit(self, e):
        self.Close()

app = wx.App()
Frame(None, -1, 'A Frame', style=wx.RESIZE_BORDER 
    | wx.SYSTEM_MENU | wx.CAPTION |  wx.CLOSE_BOX)
app.MainLoop()

我们首先将按钮和文本小部件添加到水平测量器,然后再添加到垂直测量器.我们在sizer中有sizer,这是在wxPython中执行操作的一种非常常见的方式.

__________________________
|__hbox1_|_______________|  \
|_hbox2____|______|____|_|   \___VBOX
|___hbox3______|_________|   /
|_______|__hbox4_|_______|  /

有点像那样.在每个hbox中,我们都有许多小部件.由你决定你想要多少.希望这可以帮助.

点赞