python窗口应用:wxpython超快速入门教程

创建窗口程序

初步

截至目前为止,我们写的所有应用皆在终端运行。但一般来说,我们在接触编程之前所使用的软件大多具备友好的交互界面。此外,我们虽然已经写出了光线和光学元件相互作用的代码,但并不知道这个代码是否正确。

所以,需要一个用户图形界面(Graphical User Interface,GUI)来验证并展示我们的代码,效果大致如图所示。
在这里插入图片描述
为python语言提供支持的GUI框架总计数十种,对于一些简单的应用来说,python自带的tkinter完全可以胜任,无需pip可以直接使用,问题是组件太少。目前来说,python最为著名的GUI库分别是pyQT和wxPython,相对来说前者应用广泛,内容复杂;后者内容适中,结构清晰,故选取后者。

首先,安装wxPython,在命令行中输入

pip install -U wxPython

然后可以写一个小例子

import wx

class testFrame(wx.Frame):
    def __init__(self, parent=None, title="test",size=(250,200)):
        wx.Frame.__init__(self,parent=parent, title=title,size=size)

if __name__ == '__main__':
    app = wx.App()
    frame = testFrame(title="test")
    frame.Show()
    app.MainLoop()

在上面的例子中,看到了亲切的class关键字,说明我们所定义的testFrame是一个类。但是类中所传入的参数wx.Frame就不得而知了。

但是看到wx这个前缀,多半能猜到这是在wxpython中所定义的一个框架,而且极有可能也是一个类。我们的猜测是对的,wx.Frame是GUI编程中最不可少的一个类——窗口框架。在python语言中,testFrame(wx.Frame)表示对类的继承,或者建立wx.Frame的一个子类。这样,对于wx.Frame中所定义好的内容,我们可以拿来就用;对于我们自己的内容,则可以另行定义。

接下来,__init__我们已经说过了,但是wx.Frame.__init__却是个新鲜物事。然而从写法来看,似乎是父类wx.Frame的初始化函数,我们的直觉是正确的。子类testFrame调用了父类的初始化函数,实现了一个Frame对象。

Frame的初始化参数包括:

  • parent 父窗口,由于我们所建立的这个窗口是顶级窗口,所以这个值是None。
  • id 控件的id,其值一般为正整数,当输入-1时,由系统自动生成。
  • title 窗口标题,用于显示。
  • pos 窗口位置,如果输入的值为-1,则表示让系统自动产生一个位置。
  • size 窗口尺寸,如果输入的值为-1,则由系统自己决定这个尺寸。
  • style 窗口的类型与风格。
  • name 窗口的名字,用于索引。

接下来是入口函数,第一行app=wx.App(),App()也是wxpython的一个类,在此相当于定义了一个应用程序,在此之后的所有语句,都在这个应用程序中进行。

然后,建立testFrame的一个实例。

再然后,调用wx.Frame类的方法Show,使得窗口在屏幕中显示。

最后,调用wx.App类的方法MainLoop,使程序无限循环。

由于我们什么也没定义,所以只有一个光秃秃的窗口,如图所示:

在这里插入图片描述

常用控件

我们再来回顾一下本节开始所展示的窗口程序,来观察一下我们都需要掌握哪些基本的技能:最上方是菜单栏,菜单栏下面被分成两个部分:左侧为绘图区,右侧为参数控制区。

绘图区域内,较大的红色圆圈表示光源,绿色的两个圆弧表示透镜,红色小圆圈表示交点。蓝线表示透镜的主光轴,红线表示光线。

参数区首先有一个选项卡,左右两侧分别控制光学元件和光源的位置。光学元件控制区内,最上方是一个选择栏,可以选择光学元件的类型或模式,选择栏右侧为选择按钮。

下方是六组滚动条,每个滚动条下面有一个文字说明,表示其控制的参数类型。最下面是一个多行文本输出的文本框,用于说明当前的光学元件以及光线的参数。当我们拖动滚动条的时候,左侧的透镜或者光源就会跟着发生变化,从而完成单束光传播的演示。

从UI生成的角度来说,绘图区的图形是变化的,而参数区的图形则是固定的,所以我们直觉上认为右侧的图标更好画,所以就先绘制右侧的这些控件吧。

静态文本StaticText

这是一个特别简单的控件,顾名思义即为静态文本,但所谓静态不意味着不能更改,而是意味着这个文本只是提供给我们看的,我们无法与之进行交互,既不能直接输入值,也不能复制粘贴。现在我们就创建一个静态文本控件。

class testFrame(wx.Frame):
    def __init__(self, parent=None, title="test",size=(250,200)):
        wx.Frame.__init__(self,parent=parent, title=title,size=size)
        self.SetBackgroundColour(wx.Colour(255,255,255))
        self.txtSelfText = wx.StaticText(self,-1,
            "一动不动是王八",(100,100),(100,20),wx.ALIGN_LEFT)

运行之后,显示结果为
在这里插入图片描述

回过头来,我们可以到wxpythonAPI查询一下wx.StaticText这个控件中的参数都是什么意思。得到的结果如下:

parent (wx.Window) – Parent window. Should not be None.
id (wx.WindowID) – Control identifier. A value of -1 denotes a default value.
label (string) – Text label.
pos (wx.Point) – Window position.
size (wx.Size) – Window size.
style (long) – Window style. See wx.StaticText.
name (string) – Window name.

  • parent为其父控件,填写self即代表其父控件为我们定义的testFrame,即这个静态文本画在testFrame上面。
  • id就是id,其值为整型,如果填写-1的话,代表系统自动分配id。
  • label即静态文本控件所显示的内容,其格式为字符串。
  • pos为控件位置,在窗口坐标中,其横轴为从左到右,纵轴为从上到下。size为控件尺寸,分别表示宽度和高度。这两个参数几乎在所有控件中都会用到,如果值为-1的话,表示默认尺寸。
  • style顾名思义,即风格,wx.ALIGN_LEFT表示文本左对齐。
按钮与事件

刚刚说了,静态文本并不是真的不会改变,只是不能直接被我们改变,为了让其有所变化,我们可以定义一个按钮,按下按钮之后,结果如图所示。

在这里插入图片描述

代码为:

class testFrame(wx.Frame):
    def __init__(self, parent=None, title="test",size=(250,200)):
        wx.Frame.__init__(self,parent=parent, title=title,size=size)
        self.SetBackgroundColour(wx.Colour(222,222,222))
        self.txtSelfText = wx.StaticText(self,-1,
            "一动不动是王八",(10,10),(100,20),wx.ALIGN_LEFT)
        btnTest = wx.Button(self,-1,"改变吧",(10,30),(100,20))
        btnTest.Bind(wx.EVT_BUTTON,self.onChange)

    def onChange(self,evt):
        self.txtSelfText.SetLabel("啊我变了")

首先,wx.Button即定义一个按钮,里面的参数与静态文本是大同小异的。

然后先跳过bind,直接看后面定义的函数onChange,这里有两个参数,分别是self和evt,前者没的说,类方法必备的自身参数。后者则代表传入到这个函数的某个动作,这个动作是与我们交互的,所以在函数内部似乎并没有显示出对这个参数的调用。

这是我们还注意到了一个区别,即静态文本控件前面有self,而按钮则没有。这是因为我们在后续的操作中需要对静态文本变量进行操作,所以将其定义为了类成员,而按钮则不必。所谓的操作,即SetLabel,设置self.txtSelfText中的Label参数。

然后再回过头来看btnTest.Bind,这个操作表示将某个事件绑定在按钮btnTest上,即按钮btnTest是一个事件源。第二个参数self.onChange即我们定义的事件函数,需要注意的是,调用类方法时需要加上标识符self表明是调用这个类下面的方法。

第一个参数wx.EVT_BUTTON则表示传入这个函数的动作,即事件类型,实质上是一个整数ID。差不多可以认为,wx.EVT_BUTTON即为我们传入onChange中的参数evt,表示当我们点击按钮时,执行一个按钮事件。

文本输入控件TextCtrl

在初始化初始化方法中插入两行代码:

self.setText = wx.TextCtrl(self,-1,"input",(10,50),(100,20))
        self.setText.Bind(wx.EVT_TEXT_ENTER,self.onText)

然后添再添加一个方法

def onText(self,evt):
        self.txtSelfText.SetLabel(self.setText.GetValue())

得到如图所示的效果

在这里插入图片描述

与静态文本控件的区别是,TextCtrl控件可以手动输入数值。在上例中,我们还为其绑定了一个事件,即输入字符之后,如果敲下回车键,就会执行self.onText方法。GetValue顾名思义,即获取这个控件的值。所以这个方法实现了将文本框中的值赋给静态文本控件。

事件wx.EVT_TEXT_ENTER需要按下回车才会响应,相比之下,wx.EVT_TEXT表示当文字内容发生变化时即可执行,我们可以根据需求自行选择事件。

作为文本输入控件,TextCtrl支持多种不同的风格类型,比较常用的有:

  • wx.TE_MULTILINE:多行文本
  • wx.HSCROLL:现实纵向的滚动条
  • wx.PASSWORD:密码模式,此时将不会显示输入的明文。
  • wx.CENTER:输入文本居中显示,相应地RIGHT、LEFT为靠右靠左。

写到这里,其实就已经可以做一个美观的Windows计算器了,很多GUI教程,似乎都喜欢编写这个案例,喜欢的朋友可以尝试一下。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微小冷

请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值