wxPython操作图形用户界面

1、wxPython 安装

1.1、Windows 和 macOS 平台安装:

pip install -U wxPython

其中 install 是按照软件包,-U 是将指定软件包升级到最新版本。

1.2、Linux 平台下使用 pip 安装有点麻烦,例如在 Ubuntu 16.04 安装,打开终端输入 如下指令:

pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-16.04 wxPython

1.3、下载 wxPython 帮助文档和案例。 

https://extras.wxpython.org/wxPython4/extras

1.4.官方文档

https://www.wxpython.org/

 2、wxPython 基础.

作为图形用户界面开发工具包 wxPython,主要提供了如下 GUI 内容:

1. 窗口。

2. 控件。

3. 事件处理。

4. 布局管理。

2.1、wxPython 类层次结构

2.2、第一个 wxPython 程序

第一个程序

#!/usr/bin/env python
# encoding: utf-8
"""
@author: Irving Shi
"""

import wx

app = wx.App()  # 创建应用程序对象

# 创建窗口对象           title:标题        size: 窗口大小    pos:  窗口的位置
frm = wx.Frame(None, title='第一个gui程序', size=(400, 300), pos=(100, 100))
frm.Show()  # 显示窗口
app.MainLoop()  # 进入主事件循环

2.3、窗口类 MyFrame

import wx


# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title="第一个GUI程序!", size=(400, 300), pos=(100, 100))


class App(wx.App):
    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True

    def OnExit(self):
        print('应用程序退出')
        return 0

2.4、使用面板

import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title="第一个GUI程序!", size=(400, 300))
        self.Centre() # 设置窗口居中 ①
        panel = wx.Panel(parent=self)
        statictext = wx.StaticText(parent=panel, label='Hello World!', pos=(10, 10))
class App(wx.App):
    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True
if __name__ == '__main__':
    app = App()
    app.MainLoop() # 进入主事件循环

3、事件处理

在事件处理的过程中涉及 4 个要素:

1. 事件。

2. 事件类型。

3. 事件源。

4. 事件处理者。

绑定是通过事件处理类的 Bind()方法实现,Bind()方法语法如下:

Bind(self, event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY)

3.1 一对一事件处理

#!/usr/bin/env python
# encoding: utf-8
"""
@author: Irving Shi
"""

import wx


# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title="一对一事件处理", size=(300, 180))
        self.Centre()  # 设置窗口居中 ①
        panel = wx.Panel(parent=self)
        self.statictext = wx.StaticText(parent=panel, pos=(110, 20))
        b = wx.Button(parent=panel, label='OK', pos=(100, 50))
        self.Bind(wx.EVT_BUTTON, self.on_click, b)

    def on_click(self, event):
        # print(event)
        self.statictext.SetLabelText('hello world')


class App(wx.App):
    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()  # 进入主事件循环

3.2、一对多事件处理

#!/usr/bin/env python
# encoding: utf-8
"""
@author: Irving Shi
"""

import wx


# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title="一对多事件处理", size=(300, 180))
        self.Centre()  # 设置窗口居中 ①
        panel = wx.Panel(parent=self)
        self.statictext = wx.StaticText(parent=panel, pos=(110, 15))
        b1 = wx.Button(parent=panel, id=10, label='button1', pos=(100, 45))
        b2 = wx.Button(parent=panel, id=11, label='button2', pos=(100, 85))
        # self.Bind(wx.EVT_BUTTON, self.on_click, b1) # 一对一事件
        # self.Bind(wx.EVT_BUTTON, self.on_click, b2) # 一对一事件

        self.Bind(wx.EVT_BUTTON, self.on_click, id=10, id2=20, )  # 一对多事件

    def on_click(self, event):
        print(event.GetId())
        button_id = event.GetId()
        if button_id == 10:
            self.statictext.SetLabelText('hello world button 1')
        else:
            self.statictext.SetLabelText('hello world button 2')


class App(wx.App):
    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()  # 进入主事件循环

3.3、鼠标事件处理

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Author: Irving Shi


import wx


# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title="鼠标事件处理", size=(400, 300))
        self.Centre()  # 设置窗口居中 ①
        # panel = wx.Panel(parent=self)
        # self.statictext = wx.StaticText(parent=panel, pos=(110, 15))

        self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down)
        self.Bind(wx.EVT_LEFT_UP, self.on_left_up)
        self.Bind(wx.EVT_MOTION, self.on_mouse_move)

    def on_left_down(self, evt):
        print('鼠标按下')

    def on_left_up(self, evt):
        print('鼠标释放')

    def on_mouse_move(self, event):
        """鼠标移动事件"""

        # 鼠标移动              # 鼠标按下左键
        if event.Dragging() and event.LeftIsDown():
            # 获取鼠标移动的坐标
            pos = event.GetPosition()
            print(pos)


class App(wx.App):

    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()  # 进入主事件循环

4、布局管理

使用绝对布局会有如下问题:

  1. 子窗口(或控件)位置和大小不会随着父窗口的变化而变化。

  2. 在不同平台上显示效果可能差别很大。

  3. 在不同分辨率下显示效果可能差别很大。

  4. 字体的变化也会对显示效果有影响。

  5. 动态添加或删除子窗口(或控件)界面布局需要重新设计。

 4.1 box 布局器

创建 wx.BoxSizer 对象时可以指定布局方向:

hbox = wx.BoxSizer(wx.HORIZONTAL)  # 设置为水平方向布局

hbox = wx.BoxSizer()  # 也是设置为水平方向布局,wx.HORIZONTAL是默认值可以省略

vhbox = wx.BoxSizer(wx.VERTICAL)  # 设置为垂直方向布局

当需要添加子窗口(或控件)到父窗口时,需要调用 wx.BoxSizer 对象 Add()方法,

Add()方法是从父类 wx.Sizer 继承而来的,Add()方法语法说明如下:

Add(window, proportion=0, flag=0, border=0, userData=None) # 添加到父窗口

Add(sizer, proportion=0, flag=0, border=0, userData=None)# 添加到另外一个Sizer中,用于嵌套

Add(width, height, proportion=0, flag=0, border=0, userData=None)# 添加一个空白空间

其中proportion参数仅被wx.BoxSizer使用,设置当前子窗口(或控件)在父窗口所占空间比例: flag 参数标志,用来控制对齐、边框和调整尺寸: border 参数包含边框的宽度: userData 参数可被用来传递额外的数据

4.1.1对齐 flag 标志

wx.ALIGN_TOP    # 顶对齐
wx.ALIGN_BOTTOM    # 底对齐
wx.ALIGN_LEFT    # 左对齐
wx.ALIGN_RIGHT    # 右对齐
wx.ALIGN_CENTER    # 居中对齐
wx.ALIGN_CENTER_VERTICAL    # 垂直居中对齐
wx.ALIGN_CENTER_HORIZONTAL水    # 平居中对齐
wx.ALIGN_CENTRE    # 同 wx.ALIGN_CENTER
wx.ALIGN_CENTRE_VERTICAL    # 同 wx.ALIGN_CENTER_VERTICAL
wx.ALIGN_CENTRE_HORIZONTAL    # 同 wx.ALIGN_CENTER_HORIZONTAL

4.1.2、边框 flag 标志

wx.TOP    # 设置有顶部边框,边框的宽度需要通过 Add()方法的 border 参数设置
wx.BOTTOM    # 设置有底部边框
wx.LEFT    # 设置有左边框
wx.RIGHT    # 设置有右边框
wx.ALL    # 设置 4 面全有边框

4.1.3、调整尺寸 flag 标志

wx.EXPAND    # 调整子窗口(或控件)完全填满有效空间
wx.SHAPED    # 调整子窗口(或控件)填充有效空间,但保存高宽比
wx.FIXED_MINSIZE    # 调整子窗口(或控件)为最小尺寸
wx.RESERVE_SPACE_EVEN_IF_ HIDDEN    # 设置此标志后,子窗口(或控件)如果被隐藏,所占空间保留

 4.1.4、示例

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Author: Irving Shi


import wx


# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title="box布局", size=(300, 120))
        self.Centre()  # 设置窗口居中 ①
        panel = wx.Panel(parent=self)

        # 创建垂直方向box布局管理器
        vbox = wx.BoxSizer(wx.VERTICAL)

        # 创建静态文本
        self.statictext = wx.StaticText(parent=panel, label="button1单机")

        # 添加静态文本到box布局管理器
        vbox.Add(self.statictext, proportion=2, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)
        button1 = wx.Button(parent=panel, id=10, label="button1")
        button2 = wx.Button(parent=panel, id=11, label="button2")

        self.Bind(wx.EVT_BUTTON, self.on_click, id=10, id2=20)

        # 创建水平方向box布局管理器
        hbox = wx.BoxSizer(wx.HORIZONTAL)  # wx.BoxSizer()
        hbox.Add(button1, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=5)
        hbox.Add(button2, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=5)

        # 把水平box添加到垂直box
        vbox.Add(hbox, proportion=2, flag=wx.CENTER | wx.BOTTOM, border=5)

        # 把垂直box添加到面板
        panel.SetSizer(vbox)

    def on_click(self, event):
        print(event.GetId())


class App(wx.App):

    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()  # 进入主事件循环

 4.2、StaticBox 布局


4.2.1 wx.StaticBoxSizer 构造方法如下:

wx.StaticBoxSizer(box, orient=HORIZONTAL)    #box 参数是 wx.StaticBox(静态框)对象,orient 参数是布局方向。

wx.StaticBoxSizer(orient, parent, label="")    # orient 参数是布局方向,parent 参数是设置所在父窗口,label 参数设置边框的静态文本。

 4.2.2、 示例

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Author: Irving Shi


import wx


# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title="StaticBox布局", size=(300, 120))
        self.Centre()  # 设置窗口居中 ①
        panel = wx.Panel(parent=self)

        # 创建垂直方向box布局管理器
        vbox = wx.BoxSizer(wx.VERTICAL)

        # 创建静态文本
        self.statictext = wx.StaticText(parent=panel, label="button1单机")

        # 添加静态文本到box布局管理器
        vbox.Add(self.statictext, proportion=2, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=5)
        button1 = wx.Button(parent=panel, id=10, label="button1")
        button2 = wx.Button(parent=panel, id=11, label="button2")

        self.Bind(wx.EVT_BUTTON, self.on_click, id=10, id2=20)

        # 创建静态box
        s_box = wx.StaticBox(parent=panel, label="静态框")

        # 创建水平方向静态box布局管理器
        hsbox = wx.StaticBoxSizer(s_box, orient=wx.HORIZONTAL)  # wx.BoxSizer()
        hsbox.Add(button1, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=5)
        hsbox.Add(button2, proportion=0, flag=wx.BOTTOM | wx.EXPAND, border=5)

        # 把水平静态box添加到垂直box
        vbox.Add(hsbox, proportion=2, flag=wx.CENTER | wx.BOTTOM, border=5)

        # 把垂直box添加到面板
        panel.SetSizer(vbox)

    def on_click(self, event):
        print(event.GetId())


class App(wx.App):

    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()  # 进入主事件循环



















原文地址:https://www.cnblogs.com/shizhengwen/p/14144491.html