XRC初步


XRC初步

转自:云雀XRC初步(上)XRC初步(下)

XRC初步(上)

wxPython 中定义用户界面布局可以采用两种方法。传统的方法是将界面布局代码直接写在源文件之中,这种方法不需要学习XML语法,概念上较为简单,避免了同时维护多个文件的麻烦;同时,对IDE的自动完成的支持较好。另一种方法则是采用XML资源文件,即XRC(XML Resource)。XRC的基本出发点是界面布局和程序逻辑的分离,即将界面布局代码采用XML的方式放在分离的文件之中;在程序中不涉及控件的创建和布局,只需要加载相应的资源并处理事件绑定即可。在wxPython中采用XRC分离界面布局和程序逻辑主要有以下几个方面的好处:

1. 提高了程序的可维护性
2. 界面布局可由专业人员设计
3. 更好的支持GUI布局设计工具
4. 作为wxWidgets的规范,XRC资源可通用于C++、Python等语言

示例                         

使用XRC建立用户界面必须建立两个分离的文件:XML资源文件(.xrc)和python源文件。XRC文件包含了用户界面布局信息,如下例:

#design layout in a separate XML file

<? xml version="1.0" encoding="utf-8"  ?>
< resource >
    
< object  class ="wxFrame"  name ="mainFrame" >
        
< title > My Frame </ title >
        
< object  class ="wxPanel"  name ="panel" >
            
< object  class ="wxFlexGridSizer" >
                
< cols > 2 </ cols >
                
< rows > 3 </ rows >
                
< vgap > 5 </ vgap >
                
< hgap > 5 </ hgap >
                
< object  class ="sizeritem" >
                    
< object  class ="wxStaticText"  name ="label1" >
                        
< label > First name: </ label >
                    
</ object >
                
</ object >
                
< object  class ="sizeritem" >
                    
< object  class ="wxTextCtrl"  name ="text1"   />
                
</ object >
                
< object  class ="sizeritem" >
                    
< object  class ="wxStaticText"  name ="label2" >
                        
< label > Last name: </ label >
                    
</ object >
                
</ object >
                
< object  class ="sizeritem" >
                    
< object  class ="wxTextCtrl"  name ="text2"   />
                
</ object >
                
< object  class ="spacer" >
                    
< size > 0,0 </ size >
                
</ object >
                
< object  class ="sizeritem" >
                    
< object  class ="wxButton"  name ="button" >
                        
< label > Submit </ label >
                    
</ object >
                
</ object >
            
</ object >
        
</ object >
    
</ object >
</ resource >

  Python源文件中则包括加载资源文件和事件绑定代码,同时可以使用xrc.XRCCTRL方法从名字获取控件,使用xrc.XRCID方法获取控件ID:

# logic by itself in module

import  wx
from  wx  import  xrc

class  MyApp(wx.App):

    
def  OnInit(self):
        self.res 
=  xrc.XmlResource( ' gui.xrc ' )
        
assert  self.res
        self.init_frame()
        
return  True
    
    
def  init_frame(self):
        self.frame 
=  self.res.LoadFrame(None,  ' mainFrame ' )
        
assert  self.frame
        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()

创建XRC文件         

首先我们看看XRC的组成。XRC文件由一系列预定义的标签组成,你可以注意到这些预定义的标签与控件创建时的关键字参数相似。例如,在wxPython中创建按键的代码如下:

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


  与之相应的XRC代码则是这个样子:

< object  class ="wxButton"  name ="button" >
    
< label > Submit </ label >
</ object >

  从例示中可以注意到几个XRC的关键概念:

1. 每个控件与一个XML节点相对应
2. 控件间的层次关系与XML节点间层次关系相对应,放置控件的容器与相应的XML节点的父节点相对应
3. 节点class属性值对应控件的C++类名
4. 节点name属性值为控件在XRC文件中的唯一标识,可通过该值自python源文件中获取控件
5. label等其余参数在XRC文件中作为节点的子节点出现

  有了这些基本概念,现在我们可以使用XRC文件来布局我们的用户界面了。存在大量的工具以可视化的方式来帮助我们完成这个繁琐的工作。wxPython 自带的XRCED以一种半可视化的方式(可视化的设定控件属性并预览,但不支持直接拖放控件)支持用户界面设计;开源的wxglade则支持直接的控件拖放,并可生成C++、python、perl、lisp和XRC的源文件;wxDesigner、dialogBlock,wxDesigner,BOA 等工具同样值得一试。

XRC初步(下)

python源文件中的处理       

完成了XRC界面布局文件的编写,下一步必须在python源文件中做相应的处理。与XRC处理相关的wxPython代码段主要包括三个方面:资源文件的加载,控件的获取和事件绑定代码:

  1.导入与XRC处理相关的xrc模块:

import wx.xrc as xrc


  2.加载资源文件:

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


  3.获取控件。此过程不需要显式的创建控件,通过设计XRC文件时相应的name属性值获取即可:

# 加载Frame,第一个参数为父窗口,当前为顶层窗口,故为None
#
第二个参数为设计XRC文件时Frame的name属性值
self.frame = self.res.LoadFrame(None, ' mainFrame ' )

# 获取控件,第一个参数为控件的父窗口
#
第二个参数为设计XRC文件时控件的name属性值
self.panel = xrc.XRCCTRL(self.frame, ' panel ' )
self.text1
= xrc.XRCCTRL(self.panel, ' text1 ' )

#  获取panel中的控件时不必显式获取panel本身,直接传入self.frame即可递归向下查找
self.text2 = xrc.XRCCTRL(self.frame, ' text2 ' )

#  获取控件ID,参数为设计XRC文件时控件的name属性值
self.id = xrc.XRCID( ' button ' )


  4.绑定事件处理有两种方式:

  a. 绑定按键事件:

self.button = xrc.XRCCTRL(self.panel, ' button ' )
self.frame.Bind(wx.EVT_BUTTON, self.OnSubmit, self.button)


  b. 因为xrc.XRCCTRL仅能返回wx.Window的派生类,而wxMenuItem不是派生自wx.Window,不能采用xrc.XRCCTRL 获取菜单项,因此事件必须委托给Frame绑定。派生自wx.Window的按键等控件也可以采用本方法绑定:

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


动态创建

加载Frame窗体时将自动加载其子控件和子窗体,那么,你如何控制子窗体和子控件的加载呢?为此,你必须将子窗体定义为和窗体节体平行的顶级节点 (Frames、Dialogs、Panels、Toolbars、Menus和MenuBars可以作为顶级节点),并通过程序控制加载。如下例:

dynamic.xrc文件: 

<? xml version="1.0" encoding="utf-8"  ?>
< resource >
    
< object  class ="wxFrame"  name ="mainFrame" >
        
< title > Primary Frame </ title >
        
< object  class ="wxPanel"  name ="mainPanel" >
            
< object  class ="wxButton"  name ="button" >
                
< label > New Frame </ label >
            
</ object >
        
</ object >
    
</ object >
    
< object  class ="wxFrame"  name ="nextFrame" >
        
< title > Secondary Frame </ title >
        
< object  class ="wxPanel"  name ="nextPanel" >
            
< object  class ="wxStaticText"  name ="label" >
                
< label > This is a dynamically created frame. </ label >
            
</ object >
        
</ object >
    
</ object >
</ resource >

Python源文件: 

import  wx
from  wx  import  xrc


class  MyApp(wx.App):

    
def  OnInit(self):
        self.res 
=  xrc.XmlResource( ' dynamic.xrc ' )
        self.init_frame()
        
return  True
        
    
def  init_frame(self):
        self.frame 
=  self.res.LoadFrame(None,  ' mainFrame ' )
        self.panel 
=  xrc.XRCCTRL(self.frame,  ' mainPanel ' )
        self.button 
=  xrc.XRCCTRL(self.panel,  ' button ' )
        self.frame.Bind(wx.EVT_BUTTON, self.OnNewFrame, self.button)
        self.frame.Show()
        
    
def  OnNewFrame(self, evt):
        self.frame2 
=  self.res.LoadFrame(None,  ' nextFrame ' )
        self.frame2.Show()
        

if   __name__   ==   ' __main__ ' :
    app 
=  MyApp(False)
    app.MainLoop()

  动态添加子控件时必须首先调用父窗口的GetSizer方法,创建控件后添加到Sizer,并调用Sizer的Fit方法为控件留出显示空间:

MainWindow = res.LoadFrame(None, " frame_1 " )
my_sizer
= MainWindow.GetSizer()
my_text
= wx.TextCtrl(MainWindow, - 1 , " Test " , size = ( 325 , 200 ))
my_sizer.Add(my_text,
1 , wx.EXPAND | wx.ADJUST_MINSIZE, 0)
my_sizer.Fit(MainWindow)



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值