dialog, TextCtrl subclassing by using xrc

Hi, all
I have been trying to use xrc and subclassing.
Surely, I read TwoStageCreation, SubclassingListCtrlWithXrc.

code is here:

···

####################################################
# -*- coding: utf-8 -*-

import sys
import os
import wx
from wx import xrc

#global
_firstEventType = wx.EVT_SHOW

menculator_xrc = '''\
<?xml version="1.0" ?><resource>
  <object class="wxDialog" name="mainframe"
subclass="menculator.MCDialog">
    <object class="wxBoxSizer">
      <orient>wxVERTICAL</orient>
      <object class="sizeritem">
        <object class="wxBoxSizer">
          <orient>wxVERTICAL</orient>
          <object class="sizeritem">
            <object class="wxStaticText" name="qSText"/>
            <option>1</option>
            <flag>wxALL|wxEXPAND</flag>
          </object>
          <object class="sizeritem">
            <object class="wxTextCtrl" name="aTCtrl"
subclass="menculator.MyTextCtrl"/>
            <option>1</option>
            <flag>wxALL|wxEXPAND</flag>
          </object>
        </object>
        <option>1</option>
        <flag>wxALL|wxEXPAND</flag>
        <border>5</border>
      </object>
    </object>
    <object class="wxMenuBar"/>
    <title>mainframe</title>
    <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
  </object>
</resource>'''

class MyTextCtrl( wx.TextCtrl ):
    def __init__( self , parent ):
        pre = wx.PreTextCtrl()
        self.PostCreate( pre )
        self.Bind( _firstEventType , self.OnCreate )

    def OnCreate():
        self.Unbind(self._firstEventType)
        self.Refresh()

        self.Bind( wx.EVT_KEY_UP , self.OnKeyUp )

    def OnKeyUp( self , event ):
        if self.aTCtrl == self.dlg.FindFocus():
            if wx.WXK_RETURN == event.GetKeyCode():
                event

class MCDialog( wx.Dialog ):
    def __init__( self ):
        pre = wx.PreDialog()
        global xmlRes
        xmlRes.LoadOnDialog( pre , None , "mainframe" )
        self.PostCreate( pre )
        self.Bind( _firstEventType , self.OnCreate )

    def OnCreate( self , event ):
        self.Unbind( _firstEventType )
        self.Refresh()

        self.qSText = self.FindWindowById( xrc.XRCID( 'qSText' ) )
        self.aTCtrl = self.FindWindowById( xrc.XRCID( 'aTCtrl' ) )

class Mencualtor( wx.App ):
    def __init__( self ):
        wx.App.__init__( self , False )

    def OnInit( self ):
        global xmlRes
        menculator_xrc
        xmlRes = xrc.EmptyXmlResource()
        xmlRes.LoadFromString( menculator_xrc )
        return True

def main():
    app = Mencualtor()
    dlg = MCDialog()
    dlg.Show()
    app.MainLoop()

main()
####################################################

wx.Dialog, wx.TextCtrl are subclassed, problem is don't created
'aTCtrl'.
after run, error message box shows "Subclass 'menculator.MyTextCtrl'
not found for resource 'aTCtrl', not subclassing!"
I tested LoadDialog function that create child widgets against
LoadOnDialog.
how do i solve it?

============================================
sorry about my poor english

####################################################

wx.Dialog, wx.TextCtrl are subclassed, problem is don't created
'aTCtrl'.
after run, error message box shows "Subclass 'menculator.MyTextCtrl'
not found for resource 'aTCtrl', not subclassing!"
I tested LoadDialog function that create child widgets against
LoadOnDialog.
how do i solve it?

============================================
sorry about my poor english

You made in your code a bunch of careless mistakes. Try use pylint to
check the code and you will find out many clues. Primary problem is:

class MyTextCtrl( wx.TextCtrl ):
    def __init__( self , parent ):

There should not be the parent argument since XRC mechanism is not
supplying it.

Also:

    def OnCreate():
        self.Unbind(self._firstEventType)

self._firstEventType is not defined.

And I think you'd better bind to EVT_WINDOW_CREATE instead of EVT_SHOW
for widget creation, since the EVT_SHOW will be invoked only when the
control is displayed, not when it is created.

Attached is a slightly modified version that is working:

# -*- coding: utf-8 -*-

import sys
import os
import wx
from wx import xrc

menculator_xrc = '''\
<?xml version="1.0" ?><resource>
  <object class="wxDialog" name="mainframe"
subclass="menculator.MCDialog">
    <object class="wxBoxSizer">
      <orient>wxVERTICAL</orient>
      <object class="sizeritem">
        <object class="wxBoxSizer">
          <orient>wxVERTICAL</orient>
          <object class="sizeritem">
            <object class="wxStaticText" name="qSText"/>
            <option>1</option>
            <flag>wxALL|wxEXPAND</flag>
          </object>
          <object class="sizeritem">
            <object class="wxTextCtrl" name="aTCtrl"
subclass="menculator.MyTextCtrl"/>
            <option>1</option>
            <flag>wxALL|wxEXPAND</flag>
          </object>
        </object>
        <option>1</option>
        <flag>wxALL|wxEXPAND</flag>
        <border>5</border>
      </object>
    </object>
    <object class="wxMenuBar"/>
    <title>mainframe</title>
    <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
  </object>
</resource>'''

class MyTextCtrl( wx.TextCtrl ):
    def __init__( self ):
        pre = wx.PreTextCtrl()
        self.PostCreate( pre )
        self.Bind(wx.EVT_WINDOW_CREATE, self.OnCreate)

    def OnCreate( self, event):
        if self is event.GetEventObject():
            self.Bind( wx.EVT_KEY_UP , self.OnKeyUp )
        event.Skip()

    def OnKeyUp( self , event ):
        if self.aTCtrl == self.dlg.FindFocus():
            if wx.WXK_RETURN == event.GetKeyCode():
                event

class MCDialog( wx.Dialog ):
    def __init__( self ):
        pre = wx.PreDialog()
        self.PostCreate( pre )
        self.Bind(wx.EVT_WINDOW_CREATE, self.OnCreate)

    def OnCreate( self , event ):
        if self is event.GetEventObject():
            self.qSText = self.FindWindowById( xrc.XRCID( 'qSText' ) )
            self.aTCtrl = self.FindWindowById( xrc.XRCID( 'aTCtrl' ) )
        event.Skip()

class Mencualtor( wx.App ):
    def __init__( self ):
        wx.App.__init__( self , False )

    def OnInit( self ):
        global xmlRes
        menculator_xrc
        xmlRes = xrc.EmptyXmlResource()
        xmlRes.LoadFromString( menculator_xrc )

        dlg = xmlRes.LoadDialog(None, 'mainframe')
        dlg.Show()

        return True

def main():
    app = Mencualtor()
    app.MainLoop()

if __name__ == '__main__':
    main()

Cookie wrote:

Hi, all
I have been trying to use xrc and subclassing.
Surely, I read TwoStageCreation, SubclassingListCtrlWithXrc.

wx.Dialog, wx.TextCtrl are subclassed, problem is don't created
'aTCtrl'.
after run, error message box shows "Subclass 'menculator.MyTextCtrl'
not found for resource 'aTCtrl', not subclassing!"
I tested LoadDialog function that create child widgets against
LoadOnDialog.
how do i solve it?

You have some problems:

1. The subclassing factory works by importing the module where the class resides. Since this is the same as your main script in this case you need to be sure to protect the call to main() so it is not executed again when XRC imports the module:

     if __name__ == '__main__':
         main()

2. When XRC creates an instance of the class specified in the subclass attribute it calls it with no parameters. Your sample has MyTextCtrl.__init__ expecting a parent parameter.

3. self._firstEventType does not exist.

4. Not really a problem per se, but not really a good approach to take: You've got MCDialog loading itself from the XRC, but it is also using the subclass attribute in the XRC. IMO you should choose one or the other approach, not both.

···

--
Robin Dunn
Software Craftsman

Thanks, all
I solve the problem on the strength of you.

4. Not really a problem per se, but not really a good approach to take:
You've got MCDialog loading itself from the XRC, but it is also using
the subclass attribute in the XRC. IMO you should choose one or the
other approach, not both.

You mean that

...
class Mencualtor( wx.App ):
...
    def OnInit( self ):
...
        self.frame = xmlRes.LoadDialog( None , 'mainframe' )
...

def main():
    app = Mencualtor()
    app.MainLoop()

right?

Hi Cookie,
I know this is kind of old, but could you please post your fixed code?
I’m trying to find an example for subclassing masked.NumCtrl with XRCed but didn’t find it by now.

Thanks,
Joel

···

On Saturday, July 18, 2009 10:16:50 AM UTC+2, Cookie wrote:

Hi, all

I have been trying to use xrc and subclassing.

Surely, I read TwoStageCreation, SubclassingListCtrlWithXrc.

code is here:

####################################################

-- coding: utf-8 --

import sys

import os

import wx

from wx import xrc

#global

_firstEventType = wx.EVT_SHOW

menculator_xrc = ‘’'\

<?xml version="1.0" ?>

<object class=“wxDialog” name=“mainframe”

subclass=“menculator.MCDialog”>

<object class="wxBoxSizer">

  <orient>wxVERTICAL</orient>

  <object class="sizeritem">

    <object class="wxBoxSizer">

      <orient>wxVERTICAL</orient>

      <object class="sizeritem">

        <object class="wxStaticText" name="qSText"/>

        <option>1</option>

        <flag>wxALL|wxEXPAND</flag>

      </object>

      <object class="sizeritem">

        <object class="wxTextCtrl" name="aTCtrl"

subclass=“menculator.MyTextCtrl”/>

        <option>1</option>

        <flag>wxALL|wxEXPAND</flag>

      </object>

    </object>

    <option>1</option>

    <flag>wxALL|wxEXPAND</flag>

    <border>5</border>

  </object>

</object>

<object class="wxMenuBar"/>

<title>mainframe</title>

<style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>

‘’’

class MyTextCtrl( wx.TextCtrl ):

def __init__( self , parent ):

    pre = wx.PreTextCtrl()

    self.PostCreate( pre )

    self.Bind( _firstEventType , self.OnCreate )



def OnCreate():

    self.Unbind(self._firstEventType)

    self.Refresh()



    self.Bind( wx.EVT_KEY_UP , self.OnKeyUp )



def OnKeyUp( self , event ):

    if self.aTCtrl == self.dlg.FindFocus():

        if wx.WXK_RETURN == event.GetKeyCode():

            event

class MCDialog( wx.Dialog ):

def __init__( self ):

    pre = wx.PreDialog()

    global xmlRes

    xmlRes.LoadOnDialog( pre , None , "mainframe" )

    self.PostCreate( pre )

    self.Bind( _firstEventType , self.OnCreate )



def OnCreate( self , event ):

    self.Unbind( _firstEventType )

    self.Refresh()



    self.qSText = self.FindWindowById( xrc.XRCID( 'qSText' ) )

    self.aTCtrl = self.FindWindowById( xrc.XRCID( 'aTCtrl' ) )

class Mencualtor( wx.App ):

def __init__( self ):

    wx.App.__init__( self , False )





def OnInit( self ):

    global xmlRes

    menculator_xrc

    xmlRes = xrc.EmptyXmlResource()

    xmlRes.LoadFromString( menculator_xrc )

    return True

def main():

app = Mencualtor()

dlg = MCDialog()

dlg.Show()

app.MainLoop()

main()

####################################################

wx.Dialog, wx.TextCtrl are subclassed, problem is don’t created

‘aTCtrl’.

after run, error message box shows "Subclass ‘menculator.MyTextCtrl’

not found for resource ‘aTCtrl’, not subclassing!"

I tested LoadDialog function that create child widgets against

LoadOnDialog.

how do i solve it?

============================================

sorry about my poor english