wxpython學習筆記(推薦查看)

來源:互聯網
上載者:User

一、簡介

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

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.