(九)Python GUI的基本框架

目录

基本框架

组件

事件处理机制

 GUI常用组件

按钮

菜单

菜单常用事件

静态文本和文本框

列表

单选与复选框 

 布局管理

 sizer

使用sizer的步骤

其他GUI库

PyQt

Tkinter

PyGTK


基本框架

创建一个简单的wxPython程序

import wx
app = wx.App()  # 创建应用程序对象
frame = wx.Frame(None, title = "Hello, World!") #创建一个框架
frame.Show(True)    # 显示窗口
app.MainLoop()  # 进入事件循化

运行结果如下所示:

利用我们之前讲的面向对象的方法,可以对这个代码进行修改,修改之后的代码如下所示:

import wx


class MyApp(wx.App):    # 从App类里生子类
    def OnInit(self):   # 定义初始化方法
        frame = wx.Frame(None, title="Hello, World!")   # 创建一个框架
        frame.Show()    # 显示窗口
        return True


if __name__ == '__main__':
    app = MyApp()   # 执行初始化方法
    app.MainLoop()

组件

  • 组件容器(Containers)——用于容纳其他组件 – 例:wx.Panel等 
  • 动态组件(Dynamic Widgets)——可以被用户编辑 – 例:wx.Button、wx.TextCtrl、wx.ListBox等
  • 静态组件(Static Widgets)——显示信息用,不能被用户编辑 – 例:wx.StaticBitmap、wx.StaticText、wxStaticLine等 
  • 其他组件 – 例:wx.ToolBar、wx.MenuBar、wx.StatusBar

 具体的使用方法,如下所示:

import wx


class Frame1(wx.Frame):
    def __init__(self, superior):   # 修改了原来Frame子类的__init__()方法
        wx.Frame.__init__(self, parent=superior, title="一个可以输入的文本框", pos=(100, 200), size=(350, 200))
        # 进行窗口标题、位置、大小的设置
        panel = wx.Panel(self)  # 通过Panel、TextCtrl增加一个文本输入框的位置
        text1 = wx.TextCtrl(panel, value="Hello, World!", size=(350, 200))
        # 把初始的文本内容设置为Hello, World!

if __name__ == '__main__':
    app = wx.App()
    frame = Frame1(None)
    frame.Show(True)
    app.MainLoop()

运行结果如下所示:

事件处理机制

  • GUI程序工作的基本机制之一——事件处理
  • 事件
    • – 移动鼠标,按下鼠标左键、单击按钮等
    • – 可以由用户操作触发产生,也可以在程序中创建对象产生
  •  wxPython程序将特定类型的事件关联到特定的一块代码(方法),当 该类型的事件产生时,相关代码将响应事件被自动执行 
    • – 例:当产生鼠标移动事件时,OnMove()方法将被自动调

具体代码如下所示:

import wx


class Frame1(wx.Frame):
    def __init__(self, superior):  # 修改了原来Frame子类的__init__()方法
        wx.Frame.__init__(self, parent=superior, title="一个可以输入的文本框", pos=(100, 200), size=(350, 200))
        # 进行窗口标题、位置、大小的设置
        self.panel = wx.Panel(self)  # 通过Panel、TextCtrl增加一个文本输入框的位置
        # text1 = wx.TextCtrl(self.panel, value="Hello, World!", size=(350, 200))
        # 把初始的文本内容设置为Hello, World!
        self.panel.Bind(wx.EVT_LEFT_UP, self.OnClick)
        # 将鼠标左键抬起事件(EVT_LEFT_UP)绑定到派生出的子类onClick()方法上

    def OnClick(self, event):
        posm = event.GetPosition()  # 获得鼠标单击的位置
        wx.StaticText(parent=self.panel, label="Hello, World!", pos=(posm.x, posm.y))
        # 放置一个静态的文本文件


if __name__ == '__main__':
    app = wx.App()
    frame = Frame1(None)
    frame.Show(True)
    app.MainLoop()

运行结果如下所示:

 GUI常用组件

按钮

  • 功能:接受用户的点击事件,触发相应的操作。
  • 常用按钮:
    • – wx.Button:文本按钮
    • – wx.BitmapButton:位图按钮
    • – wx.ToggleButton:开关按钮
  • 绑定处理按钮点击的事件

菜单

  • 菜单
    • – 菜单栏
    • – 菜单
    • – 菜单项命令
  •  wxPython用于创建菜单的类
    • – wx.MenuBar
    • – wx.Menu
    • – wx.MenuItem 

菜单常用事件

菜单事件 – wx.EVT_MENU

…
#绑定事件处理器
    self.Bind(wx.EVT_MENU,self.OnClickBigger,biggerItem)
    self.Bind(wx.EVT_MENU,self.OnClickQuit,id=wx.ID_EXIT)
…
#事件处理器
def OnClickBigger(self,e):
    pass
def OnClickQuit(self,e):
    self.Close()
…

静态文本和文本框

  • 文本框用于接收用户在框内输入的信息,或显示由程序提供的信息
  •  静态文本框(标签):
    • – 类:wx.StaticText
  •  文本框:
    • – 类:wx.TextCtrl
    • – 常用形式:单行,多行,富文本框

列表

  • 列表用于显示多个条目并且可供用户选择
  •  列表能够以下面四种不同模式建造:
    • – wx.LC_ICON(图标)
    • – wx.LC_SMALL_ICON(小图标)
    • – wx.LC_LIST(列表)
    • – wx.LC_REPORT (报告)

单选与复选框 

  •  复选框用于从一组可选项中, 同时选中多个选项
  •  对应的,单选框用于从一组互 斥的选项中,选取其一

具体实现如下代码所示,因为后续还会详细分析这段代码,就不展示运行结果。 

import wx


class Frame1(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, title="Hello World in wxPython")
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.text1 = wx.TextCtrl(panel, value="Hello, World!", size=(200, 180), style=wx.TE_MULTILINE)
        # 创建了一个TextCtrl实例,也就是在panel中添加了一个文本框
        sizer.Add(self.text1, 0, wx.ALIGN_TOP | wx.EXPAND)
        button = wx.Button(panel, label="Click Me")
        # 创建了一个Button实例,也就是在panel中添加了一个按钮
        sizer.Add(button)
        panel.SetSizerAndFit(sizer)
        panel.Layout()
        self.Bind(wx.EVT_BUTTON, self.OnClick, button)
        # 把Button事件绑定在frame的OnClick()方法上
        self.Show(True)

    def OnClick(self, text):
        self.text1.AppendText("\nHello, World!")  # 添加字符串


if __name__ == '__main__':
    app = wx.App()
    frame = Frame1(None)
    app.MainLoop()

 布局管理

  • 绝对定位
    •  每个窗口组件被创建时可以显式地指定它的位置和大小
    •  缺点:定位不灵活
      •      调整大小困难
      •      受设备、操作系统甚至字体影响
  •  灵活布局的解决方案
    •  sizer – 每个sizer有自己的定位策略
    •  开发者只需要选择合适策略的sizer将窗口组件放入,并且指定好需求即可

 sizer

  •  sizer本身不是一个容器或一个窗口组件。它只是一个屏幕布局的算法
  •  sizer允许嵌套
  •  wxPython常用的sizer
    • – wx.BoxSizer(在一条线上布局子窗口部件)
    • – wx.FlexGridSizer(行高和列宽由最大的组件决定)
    • – wx.GridSizer(所有组件大小一致, 固定一个方向,在 另外一个方向生长)
    • – wx.GridBagSizer

使用sizer的步骤

  1. 创建自动调用尺寸的容器,例如panel
  2. 创建sizer
  3. 创建子窗口(窗体组件)
  4. 使用sizer的Add()方法将每个子窗口添加给sizer 
  5. 调用容器的SetSizer(sizer)方法

具体代码如下所示:

import wx


class Frame1(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, title="Hello World in wxPython")
        panel = wx.Panel(self)  # 首先创建自动调用尺寸的容器
        sizer = wx.BoxSizer(wx.VERTICAL)    # 第二是创建一个sizer,这是一个BoxSizer的实例,方向是垂直方向
        self.text1 = wx.TextCtrl(panel, value="Hello, World!", size=(200, 180), style=wx.TE_MULTILINE)
        # 第三是创建窗口组件,创建了一个TextCtrl实例,也就是在panel中添加了一个文本框
        sizer.Add(self.text1, 0, wx.ALIGN_TOP | wx.EXPAND)
        # 第四是使用add方法加到sizer
        button = wx.Button(panel, label="Click Me")
        # 第三是创建窗口组件,创建了一个Button实例,也就是在panel中添加了一个按钮
        sizer.Add(button)
        panel.SetSizerAndFit(sizer)
        # 最后调用容器的SetSizer()方法
        panel.Layout()
        self.Bind(wx.EVT_BUTTON, self.OnClick, button)
        # 把Button事件绑定在frame的OnClick()方法上
        self.Show(True)

    def OnClick(self, text):
        self.text1.AppendText("\nHello, World!")  # 添加字符串


if __name__ == '__main__':
    app = wx.App()
    frame = Frame1(None)
    app.MainLoop()

 运行结果如下所示:

其他GUI库

PyQt

  • 是Python语言的GUI编程解决方案之一
  • 提供了GPL与商业协议两种授权方式,可以免费地用于自由软 件的开发
  • 跨平台:可以运行于Microsoft Windows、Mac OS X、Linux 以及其它类Unix平台上 

具体代码如下所示:

import sys
from PyQt5 import QtWidgets


class TestWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Hello World!")
        self.outputArea = QtWidgets.QTextBrowser()
        self.helloButton = QtWidgets.QPushButton("Click Me")
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.outputArea)
        self.layout.addWidget(self.helloButton)
        self.setLayout(self.layout)
        self.helloButton.clicked.connect(self.sayHello)

    def sayHello(self):
        self.outputArea.append("Hello, World!")


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    testWidget = TestWidget()
    testWidget.show()
    sys.exit(app.exec_())

 运行结果如下所示:

优点:

  • 文档比其他GUI库丰富
  • 与Qt、C++开发经验互通
  • 可使用大多数为Qt开发的组件
  • 有方便的周边工具支持PyQt, 如QtDesigner,Eric4

缺点:

  • 要注意避免内存泄露
  • 运行时庞大
  • 需要学习一些C++知识

Tkinter

  • Tkinter绑定了 Python 的 Tk GUI 工具集 ,通过内嵌在 Python 解释器内部的 Tcl 解释器实现  Tkinter 的调用转换成 Tcl 命令,然后交给 Tcl 解释器进行解释, 实现 Python 的 GUI 界面

具体代码如下所示:

import tkinter as tk


class Tkdemo(object):
    def __init__(self):
        self.root = tk.Tk()
        self.txt = tk.Text(self.root, width=30, height=10)
        self.txt.pack()
        self.button = tk.Button(self.root, text='Click me', command=self.sayhello)
        self.button.pack()

    def sayhello(self):
        self.txt.insert(tk.INSERT, "Hello, World!\n")


d = Tkdemo()
d.root.mainloop()

 运行结果如下所示:

 优点:

  • 历史最悠久, 是Python 事实上的标准GUI
    • Python 中使用TkGUI工具集的标准接口,已包括在标准的Python Windows 安装中
    • 著名的 IDLE 用 Tkinter 实现 GUI
  • 创建的 GUI 简单,学起来和用起来也简单

缺点:

  • 性能不太好, 执行速度慢

PyGTK

  • PyGTK是一套GTK+ GUI库的Python封装
  • pyGTK为创建桌面程序提供了一套综合的图形元素和其它使用的编程工具
  • PyGTK是基于LGPL协议的免费软件
  • 许多 Gnome 下的著名应用程序的 GUI 都是使用 PyGTK 实现的,比如 BitTorrent , GIMP 和 Gedit 都有可选的实现

在此就不展示PyGTK的代码,感兴趣的同学可以自己去学习。

优点:

  • 底层的GTK+提供了各式的可视元素和功能
  • 能开发在GNOME桌面系统运行的功能完整的软件

缺点:

  • 在Windows平台表现不太好 
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值