wxpython学习笔记(推荐查看)

一、简介


wxPython是Python编程语言的一个GUI工具箱。他使得Python程序员能够轻松的创建具有健壮、功能强大的图形用户界面的程序。它是Python语言对流行的wxWidgets跨平台GUI工具库的绑定。而wxWidgets是用C++语言写成的。和Python语言与wxWidgets GUI工具库一样,wxPython是开源软件。这意味着任何人都可以免费地使用它并且可以查看和修改它的源代码,或者贡献补丁,增加功能。wxPython是跨平台的。这意味着同一个程序可以不经修改地在多种平台上运行。现今支持的平台有:32位微软Windows操作系统、大多数Unix或类Unix系统、苹果Mac OS X。由于使用Python作为编程语言,wxPython编写简单、易于理解。

二、基本使用

基本使用的话到这个地址看已经很详细了,我没有必要重复一遍啦:

http://wiki.wxpython.org/Getting%20Started

三、常用控件


1. 菜单(menu)

http://wiki.wxpython.org/Getting%20Started#head-33e6dc36df2a89db146142e9a97b6e36b956875f

2. 页面布局(Sizer)

这个东东使用起来比较麻烦,参考以下页面吧:

http://wiki.wxpython.org/Getting%20Started#head-7455553d71be4fad208480dffd53b7c68da1a982

wxPython frame的布局详细解释(一)

wxPython frame的布局详细解释(二)

3. Tab页面(notebook)

http://wiki.wxpython.org/Getting%20Started#head-b20d2fc488722cdb3f6193150293d1e118734db8

4. 列表控件(ListCtrl)

这个控件比较强大,是我比较喜欢使用的控件之一。在《wxPythonInAction》一书中第13章有介绍(想要该书电子版及附带源码的朋友可以问我要)

下面是list_report.py中提供的简单用法:

代码如下:

import wx
import sys, glob, random
import data

class DemoFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1,
                          "wx.ListCtrl in wx.LC_REPORT mode",
                          size=(600,400))

il = wx.ImageList(16,16, True)
        for name in glob.glob("smicon??.png"):
            bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)
            il_max = il.Add(bmp)
        self.list = wx.ListCtrl(self, -1, style=wx.LC_REPORT)
        self.list.AssignImageList(il, wx.IMAGE_LIST_SMALL)

# Add some columns
        for col, text in enumerate(data.columns):
            self.list.InsertColumn(col, text)

# add the rows
        for item in data.rows:
            index = self.list.InsertStringItem(sys.maxint, item[0])
            for col, text in enumerate(item[1:]):
                self.list.SetStringItem(index, col+1, text)

# give each item a random image
            img = random.randint(0, il_max)
            self.list.SetItemImage(index, img, img)

# set the width of the columns in various ways
        self.list.SetColumnWidth(0, 120)
        self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
        self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
        self.list.SetColumnWidth(3, wx.LIST_AUTOSIZE_USEHEADER)

app = wx.PySimpleApp()
frame = DemoFrame()
frame.Show()
app.MainLoop()

对于ListCtrl控件,我要补充的几个地方是:

1. 如何获取选中的项目?

最常用的方法就是获取选中的第一项:GetFirstSelected(),这个函数返回一个int,即ListCtrl中的项(Item)的ID。

还有一个方法是:GetNextSelected(itemid),获取指定的itemid之后的第一个被选中的项,同样也是返回itemid。

通过这两个方法,我们就可以遍历所有选中的项了:

代码如下:

GetNextSelecteditemid = self.list.GetFirstSelected()
while itemid <> -1:
        #Do something
        itemid = self.list.GetNextSelected(itemid)

如果要获取某一行,某一列的值,则通过下面的方法:

代码如下:

#获取第0行,第1列的值
itemtext = self.list.GetItem(0, 1).Text

2. 如何在选定项后添加右键菜单?

在__init__函数中,添加如下的事件绑定:
self.list.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)然后,添加OnContextMenu方法:

代码如下:

def OnContextMenu(self, event):
        if not hasattr(self, "popupStop"):
            self.popupStop = wx.NewId()
            self.popupPropery = wx.NewId()
            self.Bind(wx.EVT_MENU, self.OnPopupStop, id = self.popupStop)
            self.Bind(wx.EVT_MENU, self.OnPopupProperty, id = self.popupPropery)

# 创建菜单
        menu = wx.Menu()
        itemStop = wx.MenuItem(menu, self.popupStop, "Stop")
        itemProperty = wx.MenuItem(menu, self.popupPropery, 'Property')

menu.AppendItem(itemStop)
        menu.AppendItem(itemProperty)

itemProperty.Enable(False)#默认让属性按钮变成无效状态

if itemid == -1:#如果没有选中任何项
            itemStop.Enable(False)
        else:
            itemStop.Enable(False)
            itemProperty.Enable(True)
        #到这里才弹出菜单
        self.PopupMenu(menu)
        #最后注意销毁前面创建的菜单
        menu.Destroy()

5. 选择文件对话框(FileDialog)

使用起来非常简单:

代码如下:

dlg = wx.FileDialog(self,
                            message="Yes, select a place ",
                            wildcard="PNG(*.png)|*.png" ,
                            style=wx.SAVE
                            )
        savefile = ''
        if dlg.ShowModal() == wx.ID_OK:
            savefile = dlg.GetPath()
            try:
                os.remove(self.filename)
            except:
                pass
            self.img.SaveFile(savefile, wx.BITMAP_TYPE_PNG)
            self.filename = savefile
        dlg.Destroy()

6. 选择文件夹对话框(DirDialog)

代码如下:

dialog = wx.DirDialog(None, 'Choose a directory: ',
                              style = wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
if dialog.ShowModal() == wx.ID_OK:
        for itemid in range(self.list.GetItemCount()):
                self.savechart(itemid, graphpath)
dialog.Destroy()

四、一些技巧

1. 设置快捷键

比如,希望按F5执行某个操作,可以在__init__函数中使用如下方法:

代码如下:

acceltbl = wx.AcceleratorTable([(wx.ACCEL_NORMAL, wx.WXK_F5, self.btnrun.GetId())])
self.SetAcceleratorTable(acceltbl)

还有一种很常用的情况,就是按ESC键关闭窗口。我们知道,有一种非常简单的办法就是使用SetId(wx.ID_CANCEL)方法,如:

代码如下:

self.btncancel = wx.Button(self.panel1, -1, 'Cancel', wx.Point(380, 280))
self.btncancel.SetId(wx.ID_CANCEL)

这样,按ESC键时,将会关闭当前Dialog,注意!这里是说Dialog,即继承自wx.Dialog的窗口对象,对于wx.Frame使用SetId似乎没有效果。

2. 使用定时器timer
在《wxPythonInAction》18章有个例子,如下:

代码如下:

import wx
import time

class ClockWindow(wx.Window):
    def __init__(self, parent):
        wx.Window.__init__(self, parent)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.timer.Start(1000)

def Draw(self, dc):
        t = time.localtime(time.time())
        st = time.strftime("%I:%M:%S", t)
        w, h = self.GetClientSize()
        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
        dc.Clear()
        dc.SetFont(wx.Font(30, wx.SWISS, wx.NORMAL, wx.NORMAL))
        tw, th = dc.GetTextExtent(st)
        dc.DrawText(st, (w-tw)/2, (h)/2 - th/2)

def OnTimer(self, evt):
        dc = wx.BufferedDC(wx.ClientDC(self))
        self.Draw(dc)

def OnPaint(self, evt):
        dc = wx.BufferedPaintDC(self)
        self.Draw(dc)

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="wx.Timer")
        ClockWindow(self)

app = wx.PySimpleApp()
frm = MyFrame()
frm.Show()
app.MainLoop()

3. 使用多线程时你必须知道的:wx.CallAfter

在wxpython中编写多线程案例时特别需要注意,线程中通知窗口对象更新状态时,必须使用wx.CallAfter。同样是18章的例子:

代码如下:

import wx
import threading
import random

class WorkerThread(threading.Thread):
    """
    This just simulates some long-running task that periodically sends
    a message to the GUI thread.
    """
    def __init__(self, threadNum, window):
        threading.Thread.__init__(self)
        self.threadNum = threadNum
        self.window = window
        self.timeToQuit = threading.Event()
        self.timeToQuit.clear()
        self.messageCount = random.randint(10,20)
        self.messageDelay = 0.1 + 2.0 * random.random()

def stop(self):
        self.timeToQuit.set()

def run(self):
        msg = "Thread %d iterating %d times with a delay of %1.4f\n" \
              % (self.threadNum, self.messageCount, self.messageDelay)
        wx.CallAfter(self.window.LogMessage, msg)

for i in range(1, self.messageCount+1):
            self.timeToQuit.wait(self.messageDelay)
            if self.timeToQuit.isSet():
                break
            msg = "Message %d from thread %d\n" % (i, self.threadNum)
            wx.CallAfter(self.window.LogMessage, msg)
        else:
            wx.CallAfter(self.window.ThreadFinished, self)

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Multi-threaded GUI")
        self.threads = []
        self.count = 0

panel = wx.Panel(self)
        startBtn = wx.Button(panel, -1, "Start a thread")
        stopBtn  = wx.Button(panel, -1, "Stop all threads")
        self.tc = wx.StaticText(panel, -1, "Worker Threads: 00")
        self.log = wx.TextCtrl(panel, -1, "",
                               style=wx.TE_RICH|wx.TE_MULTILINE)

inner = wx.BoxSizer(wx.HORIZONTAL)
        inner.Add(startBtn, 0, wx.RIGHT, 15)
        inner.Add(stopBtn, 0, wx.RIGHT, 15)
        inner.Add(self.tc, 0, wx.ALIGN_CENTER_VERTICAL)
        main = wx.BoxSizer(wx.VERTICAL)
        main.Add(inner, 0, wx.ALL, 5)
        main.Add(self.log, 1, wx.EXPAND|wx.ALL, 5)
        panel.SetSizer(main)

self.Bind(wx.EVT_BUTTON, self.OnStartButton, startBtn)
        self.Bind(wx.EVT_BUTTON, self.OnStopButton, stopBtn)
        self.Bind(wx.EVT_CLOSE,  self.OnCloseWindow)

self.UpdateCount()

def OnStartButton(self, evt):
        self.count += 1
        thread = WorkerThread(self.count, self)
        self.threads.append(thread)
        self.UpdateCount()
        thread.start()

def OnStopButton(self, evt):
        self.StopThreads()
        self.UpdateCount()

def OnCloseWindow(self, evt):
        self.StopThreads()
        self.Destroy()

def StopThreads(self):
        while self.threads:
            thread = self.threads[0]
            thread.stop()
            self.threads.remove(thread)

def UpdateCount(self):
        self.tc.SetLabel("Worker Threads: %d" % len(self.threads))

def LogMessage(self, msg):
        self.log.AppendText(msg)

def ThreadFinished(self, thread):
        self.threads.remove(thread)
        self.UpdateCount()

app = wx.PySimpleApp()
frm = MyFrame()
frm.Show()
app.MainLoop()

4. 需要在程序中启动另外一个GUI程序,而有不失去主窗口的焦点?
通常,我们调用os.popen运行其他外部程序是没有问题的。但是在wxpython中,将会让wx失去当前的焦点,即使得打开的程序成为了一个模式对话框。要解决这个问题可以使用wx自带的方法,wx.Execute。

代码如下:

wx.Execute('notepad')

五、学习资源


1. 官方:http://wiki.wxpython.org/FrontPage

2. 啄木鸟WIKI:http://wiki.woodpecker.org.cn/moin/WxPythonInAction

作者:CoderZh(CoderZh)
出处:http://coderzh.cnblogs.com

(0)

相关推荐

  • wxpython 学习笔记 第一天

    它是Python语言对流行的wxWidgets跨平台GUI工具库的绑定.而wxWidgets是用C++语言写成的. 和Python语言与wxWidgets GUI工具库一样,wxPython是开源软件.这意味着任何人都可以免费地使用它并且可以查看和修改它的源代码,或者贡献补丁,增加功能. wxPython是跨平台的.这意味着同一个程序可以不经修改地在多种平台上运行.现今支持的平台有:32位微软Windows操作系统.大多数Unix或类Unix系统.苹果Mac OS X. 由于使用Python作为

  • python简单线程和协程学习心得(分享)

    python中对线程的支持的确不够,不过据说python有足够完备的异步网络框架模块,希望日后能学习到,这里就简单的对python中的线程做个总结 threading库可用来在单独的线程中执行任意的python可调用对象.尽管此模块对线程相关操作的支持不够,但是我们还是能够用简单的线程来处理I/O操作,以减低程序响应时间. from threading import Thread import time def countdown(n): while n > 0: print('T-minus:

  • Python学习资料

    官方网站 : www.python.org Python is an interpreted, interactive, object-oriented programming language. It is often compared to Tcl, Perl, Scheme or Java. Python combines remarkable power with very clear syntax. It has modules, classes, exceptions, very h

  • python笔记(1) 关于我们应不应该继续学习python

    以前面试的时候会被问到,linux熟不熟呀?对于这种问题:我总会尴尬地回答,"额..了解一点". 然而,我大学毕业的时候,连linux的虚拟机都没装过,更别提系统熟不熟悉了.虽然我了解一点这个系统可以完全通过命令来操作.后来工作了,有时候写点代码,svn提交上去,服务器是Linux的,自己也是在windows上跑跑客户端.记得有个项目,要求用shell来启动java程序,你知道那时候我是怎么做的吗?把他们的shell拿来,问哪几个地方要改的,然后改下要启动java类的路径.ok了,完全

  • 最近Python有点火? 给你7个学习它的理由!

    Python 是一门更注重可读性和效率的语言,尤其是相较于 Java,PHP 以及 C++ 这样的语言,它的这两个优势让其在开发者中大受欢迎. 诚然,它有点老了,但仍是80后啊 -- 至少没有 Cobol 或者 Fortran 那么老.而且,如果还能派上用场的话,为啥要折腾着改变它呢 (尤其在这个还有那么多方法可以提升它性能的时候)? 实际上这要看你怎么看待它,生命线长本身就是件好事 -- 说明它稳定且可靠. 如果你是像其他许多人一样都是从 Java,C 或者 Perl 开始进入职业生涯的,那么

  • 学习python (1)

    先推荐一个学习python的好网址 简明 Python 教程 Swaroop, C. H. 著 沈洁元  译在线教程的网址: http://www.woodpecker.org.cn:9081/doc/abyteofpython_cn/chinese/index.html 学习编程快20年了,很少见到如此好的教程.简单,清晰.大部分的软件书籍翻译的是呕呀啁咂难为听,名声显赫的译者如候某人,也是50步笑百步而已. 网上有一种说法,一个有经验的程序员可以在半天内,学会python. 我试了一下,感觉

  • Python学习思维导图(必看篇)

    无意间碰到的一个大神整理的Python学习思维导图,感觉对初学者理清学习思路大有裨益,非常感谢他的分享. 14 张思维导图 基础知识 数据类型 序列 字符串 列表 & 元组 字典 & 集合 条件 & 循环 文件对象 错误 & 异常 函数 模块 面向对象编程 以上这篇Python学习思维导图(必看篇)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • python学习之面向对象【入门初级篇】

    前言 最近在学习Python的面向对象编程,以前是没有接触过其它的面向对象编程的语言,因此学习这一部分是相当带劲的,这里也总结一下. 概述 python支持多种编程范式:面向过程.面向对象.面向切面(装饰器部分)等. 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强..." OOP思想 面向对象的基本哲学:世界由具有各自运动规律和内部状态的对象组成,对象之间相互作用和通讯构

  • 学习python的几条建议分享

    熟悉python语言,以及学会python的编码方式.熟悉python库,遇到开发任务的时候知道如何去找对应的模块.知道如何查找和获取第三方的python库,以应付开发任务. 安装开发环境 如果你在window下, 去下载pythonxy安装起来, 然后运行python, 进入python解释环境.如果你在ubuntu下, 执行: sudo apt-get install python, 然后在命令行下运行python, 进入python解释环境. 学习方法 作为一名成熟的开发人员, 我学习新东

  • 简明 Python 基础学习教程

    版本:1.20 A Byte of Python Copyright © 2003-2005 Swaroop C H 简明 Python 教程 <简明 Python 教程>为 "A Byte of Python" 的唯一指定简体中文译本,版权 © 2005 沈洁元 本书依照 创作公用约定(署名-非派生作品-非商业用途) 发布. 概要 无论您刚接触电脑还是一个有经验的程序员,本书都将有助您学习使用Python语言. 前言 本书的读者 本书的由来 本书目前的状况 官方网站 约定

随机推荐