小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

GUI programming with wxPython 之 XRC

 dinghj 2014-04-16

一、概念

XRC(XML Resource)的設(shè)計(jì)來源于wxWidgets,它的想法很簡單,就是將界面設(shè)計(jì)的工作從程序中獨(dú)立出來。具體的做法是,創(chuàng)建單獨(dú)的XML文件,負(fù)責(zé)界面設(shè)計(jì),程序運(yùn)行的時候載入,生成界面。這樣做的好處是顯而易見的。首先,將繁瑣的外觀設(shè)計(jì)代碼從程序中去掉,程序更清晰易讀。其次,XRC文件獨(dú)立于程序,程序運(yùn)行時才調(diào)用,因此可以隨意更換外觀。這種思想并不是wxWidgets的原創(chuàng),MFC中的RC已經(jīng)有了,類似的還有HTML和CSS的關(guān)系。wxPython從wxWidgets繼承而來,當(dāng)然也保留了XRC。

這里有幾點(diǎn)要補(bǔ)充的。一是wxPython的XRC文件中用到的類名稱仍然是wxWidgets中的類名稱,換句話說,wxPython和wxWidgets可以共用XRC文件,第二點(diǎn)要補(bǔ)充的是XRC文件可以編譯成二進(jìn)制文件XRS,或者編譯成C++代碼。

二、例子

先來看一個例子。

import wx

class MyFrame(wx.Frame):

    def __init__(self):

        wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title='My Frame')

        panel = wx.Panel(self)

        label1 = wx.StaticText(panel, wx.ID_ANY, 'First name:')

        label2 = wx.StaticText(panel, wx.ID_ANY, 'Last name:')

        self.text1 = wx.TextCtrl(panel, wx.ID_ANY)

        self.text2 = wx.TextCtrl(panel, wx.ID_ANY)

        button = wx.Button(panel, wx.ID_ANY, 'Submit')

        sizer = wx.FlexGridSizer(rows=2, cols=2, vgap=5, hgap=5)

        self.Bind(wx.EVT_BUTTON, self.OnSubmit, button)

        sizer.Add(label1)

        sizer.Add(self.text1)

        sizer.Add(label2)

        sizer.Add(self.text2)

        sizer.Add((0,0)) #filler for the grid cell

        sizer.Add(button)

        panel.SetSizer(sizer)

        sizer.Fit(self)

    def OnSubmit(self, evt):

        wx.MessageBox('Your name is %s %s!' %

(self.text1.GetValue(), self.text2.GetValue()), 'Feedback')

class MyApp(wx.App):

    def OnInit(self):

        frame = MyFrame()

        self.SetTopWindow(frame)

        frame.Show()

        return True

if __name__ == '__main__':

    app = MyApp(False)

    app.MainLoop()

這是一個簡單的wxPython程序??梢钥吹缴厦娴拇a中,除了BindOnSubmit,其他的代碼都是和界面設(shè)計(jì)有關(guān)的,這些代碼或者類似的代碼出現(xiàn)于幾乎所有的GUI程序中。下面是用XRC重新實(shí)現(xiàn)的代碼。

import wx

from wx import xrc

class MyApp(wx.App):

    def OnInit(self):

        self.res = xrc.XmlResource('gui.xrc')

        self.init_frame()

        return True

    def init_frame(self):

        self.frame = self.res.LoadFrame(None, 'mainFrame')

        self.panel = xrc.XRCCTRL(self.frame, 'panel')

        self.text1 = xrc.XRCCTRL(self.panel, 'text1')

        self.text2 = xrc.XRCCTRL(self.panel, 'text2')

        self.frame.Bind(wx.EVT_BUTTON, self.OnSubmit, id=xrc.XRCID('button'))

        self.frame.Show()

    def OnSubmit(self, evt):

        wx.MessageBox('Your name is %s %s!' %

(self.text1.GetValue(), self.text2.GetValue()), 'Feedback')

if __name__ == '__main__':

    app = MyApp(False)

    app.MainLoop()

看起來是不是比上面的清晰多了,當(dāng)然,程序要跑起來,還需要下面的部分。下面的代碼屬于XRC文件。

下面的代碼屬于XRC文件。


<?xml version="1.0" encoding="utf-8"?>

<resource>

    <object name="mainFrame">

        <title>My Frame</title>

        <object name="panel">

            <object

                <cols>2</cols>

                <rows>3</rows>

                <vgap>5</vgap>

                <hgap>5</hgap>

                <object

                    <object name="label1">

                        <label>First name:</label>

                    </object>

                </object>

                <object

                    <object name="text1"/>

                </object>

                <object

                    <object name="label2">

                        <label>Last name:</label>

                    </object>

                </object>

                <object

                    <object name="text2"/>

                </object>

                <object

                    <size>0,0</size>

                </object>

                <object

                    <object name="button">

                        <label>Submit</label>

                    </object>

                </object>

            </object>

        </object>

    </object>

</resource>

這段代碼看起來很復(fù)雜,但是如果熟悉XML的話,應(yīng)該很容易看明白它的結(jié)構(gòu)。最關(guān)鍵的是,我們不用親手寫這些代碼,很多工具,像XRCed,wxGlade都可以自動生成這些代碼,你所要做的只是點(diǎn)幾下鼠標(biāo)。

三、創(chuàng)建XRC文件

雖然我們不用親自寫XRC文件,弄清楚它的原理還是必要的。在wxPython中,Button的構(gòu)造函數(shù)是這樣的。

wx.Button( parent, id, label='', pos=wx.DefaultPosition, size=wx.DefaultSize,

size=wx.DefaultSize, style=0, validator=wx.DefaultValidator, name='button')

實(shí)際使用的時候,通常沒有這么多參數(shù),

button = wx.Button(panel, wx.ID_ANY, 'Submit')

但是在XRC文件中,要創(chuàng)建一個Button,通常用下面的方式,

<object name="button">

<label>Submit</label>

</object>

從上面這幾行代碼中,我們可以得到如下信息:

1. XRC用<object> </object>表示要創(chuàng)建的對象。

2. XRC用所用的是C++的類名wxButton,而不是wxPython的類名wx.Button。

3. XRC用name表示對象的名稱,對應(yīng)于python代碼中的id。

4. XRC用層次關(guān)系表示對象之間的父子關(guān)系。

下面這段代碼顯示了XRC文件的層次關(guān)系。

<?xml version="1.0" encoding="utf-8"?>

<resource>

    <object name="mainFrame">

        <title>Test Frame</title>

        <object name="panel">

            <object name="button">

                <label>Submit</label>

            </object>

        </object>

    </object>

</resource>

注意,所有的結(jié)構(gòu)都包含在<resource> </resource>中,表示這個文件是XML Resource文件。

到目前為止,我們對XRC文件的結(jié)構(gòu)已經(jīng)有了初步的認(rèn)識,接下來要了解的是在Python程序中如何用到它們。

四、使用XRC文件

如何使用XRC文件是wxPython+XRC框架的關(guān)鍵一步。在前面的代碼中,我們注意到這樣兩行,

import wx

from wx import xrc

這里要強(qiáng)調(diào)的是xrc模塊必須單獨(dú)被導(dǎo)入,所以,第二行是必須的。

class MyApp(wx.App):

def OnInit(self):

self.res = xrc.XmlResource('gui.xrc')

self.init_frame()

return True

在上面這幾行代碼中,在上面的代碼中,Self.res存儲xrc文件的內(nèi)容。xrc.XmlResource是導(dǎo)入XRC文件,創(chuàng)建xrc對象的關(guān)鍵。

self.init_frame()是用戶自己定義的函數(shù)。你不一定要定義self.init_frame()函數(shù),這樣做的好處只是把初始化框架的工作單獨(dú)放在一起,看起來清晰。你也可以在OnInit函數(shù)中完成所有Frame的初始化工作。下面我們來看init_frame()函數(shù)中做了什么,

self.frame = self.res.LoadFrame(None, 'mainFrame')

LoadFrame()函數(shù)返回mainFrame的引用,將頂層Frame對象載入到python程序中,第一個參數(shù)是parent,第二個參數(shù)是ID,即XRC文件中為Frame取的名字。這個函數(shù)還初始化所有的children Frame,這些工作并沒有顯示的表現(xiàn)出來,由XRC自動完成。

當(dāng)你想從XRC文件中提取信息時,有兩種方式可以選擇,一種是XRCID(XRC_name),這個函數(shù)可以獲得對象的ID;另一種是XRCCTRL(XRC_name),可以獲得對象的引用。

self.panel = xrc.XRCCTRL(self.frame, 'panel')

self.text1 = xrc.XRCCTRL(self.panel, 'text1')

self.text2 = xrc.XRCCTRL(self.panel, 'text2')

對XRCCTRL需要多說兩句,XRCCTRL函數(shù)返回對象的引用。但是并沒有create新對象,僅僅是獲取他們的引用,創(chuàng)建對象的工作已經(jīng)在上面的LoadFrame()過程中完成了。另一個需要強(qiáng)調(diào)的是,調(diào)用XRCCTRL時,不一定提供直接的parent,可以使用更上一層的parent,XRCCTRL會用FindWindowById遞歸的往下找。也就是說,如果你迷路了,報上爺爺?shù)拿?,警察叔叔也能把你送到家?

到目前為止,構(gòu)造界面的工作算是完成了。如果你熟悉GUI編程的話,馬上會想到,接下來的工作應(yīng)該是將Gui對象,事件和事件處理函數(shù)聯(lián)系起來。這就是接下來要講的事件綁定。

五、事件綁定

先看一段代碼,

self.frame.Bind( wx.EVT_BUTTON, self.OnSubmit, id=xrc.XRCID('button') )

這是一個簡單的綁定的例子,將按鈕事件,事件函數(shù)和按鈕ID綁定起來。前兩個參數(shù)不用多解釋,注意第三個參數(shù)中的XRCID函數(shù),這個函數(shù)通過對象的名稱ID返回對象的數(shù)字ID。這個數(shù)字ID是你在創(chuàng)建對象的時候wxPython用wx.NewID()生成的。

講到這里有必要了解一下Bind()函數(shù),下面是Bind()函數(shù)的定義,

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

最后一個參數(shù)我們忽略不計(jì)。第四個參數(shù)就是我們剛才的例子中的第三個參數(shù),你也許會奇怪,為什么跳過了默認(rèn)的第三個參數(shù)直接讀取第四個參數(shù),程序還能正常?在這種情形下,它的確就是正常??戳薆ind()函數(shù)的定義之后,你也許還能想出另一種調(diào)用方法,像下面這樣,

self.button = xrc.XRCCTRL(self.panel, 'button')

self.frame.Bind(wx.EVT_BUTTON, self.OnSubmit, self.button)

這當(dāng)然也是正確的。但我們通常都用前一種方法。為什么呢?后一種不是更直觀嗎?真正的原因是,XRCCTRL只能返回wxWindow的繼承類的引用,也就是有GetID方法的類。但很多情況下,我們要綁定的對象并不是wxWindow的繼承類,像我們經(jīng)常用到的Bind是將event handler和menu綁定起來,wxMenuItem類不是由wxWindow繼承而來,因此,用XRCCTRL得不到它的引用,這種情況下,必須用XRCID來獲得對象的ID,并將ID傳給Bind作為參數(shù)。所以,為了簡單,為了統(tǒng)一,我們就選擇ID來作為Bind的參數(shù)。

關(guān)于利用wxPython+XRC的框架進(jìn)行GUI編程,到這里就講完了,這些東西是我從網(wǎng)上收集來的,半翻譯半筆記最后寫成現(xiàn)在這樣。主要參考了下面這篇文章

http://wiki./XRCTutorial

希望能對也為這個內(nèi)容困惑的朋友有幫助。 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多