xrc sub-classing and sub folders...

Apologies if this has been dealt with before but I haven't been able to
find a specific answer.

I am developing an application in wxPython and using XRC to define the
frames, etc...

I generate the standard Python code and save it in my eclipse project
for sub-classing.

What are you using to generate the Python code? (I'm guessing XRCed or pywxrc, but if it's something else then please be specific.)

Where it goes pear-shaped is that I have carved up my project into
folder and I am trying to have all user interface code in a folder
called 'gui'.

The tools above specify the xrc file to be loaded with no path information, (like "__res.Load('test1.xrc')") so that means that it is expecting to find the xrc file in the current working directory. When you move the modules to a package structure then most likely your current working directory is located somewhere else, and so it will not find the xrc file there.

Probably the easiest way to deal with this issue is to tell the tool to embed the xrc in the py file. Both XRCed and pywxrc support doing that. Another option would be to monkey-patch in your own function in place of get_resources which knows how to find the .xrc file located in some other place.

···

On 10/26/12 11:44 PM, Rob wrote:

--
Robin Dunn
Software Craftsman

Hi Robin,

Thank you very much for your reply…

To answer your question…I am using XRCed to generate the Python and I am aware of it ‘expecting’ the xrc file to be in the current working directory, however I’m still getting problems with the menubar…

For the moment I have just dropped the menu bar from the xrc file and left it until later and I hand-mod the generated python module to add ./gui/ to the filename (understanding that this defeats the purpose of generating that module).

Having done this everything works fine (minus the menubar) and the forms all behave nicely. By the way… I am sub-classing all of the classes in the generated python module.

I have tried including the menubar as part of the main frame and also having it external to the main frame and adding it to the main frame at run-time but it does not matter what I do I always end up with some variation on the following exception:

···

Traceback (most recent call last):

File “C:\Users\Rob\Eclipse\Workspace\Quiver\src\Main.py”, line 26, in

app = QuiverApp()

File “C:\Users\Rob\Eclipse\Workspace\Quiver\src\Main.py”, line 16, in init

wx.App.init(self, redirect=False)

File “C:\Python26\lib\site-packages\wx-2.8-msw-unicode\wx_core.py”, line 7978, in init

self._BootstrapApp()

File “C:\Python26\lib\site-packages\wx-2.8-msw-unicode\wx_core.py”, line 7552, in _BootstrapApp

return core.PyApp__BootstrapApp(*args, **kwargs)

File “C:\Users\Rob\Eclipse\Workspace\Quiver\src\Main.py”, line 20, in OnInit

QuiverFrm = frmQuiver()

File “C:\Users\Rob\Eclipse\Workspace\Quiver\src\gui\Forms.py”, line 18, in init

self.SetMenuBar(mnbQuiver())

File “C:\Users\Rob\Eclipse\Workspace\Quiver\src\gui\Forms.py”, line 60, in init

xrcmnbQuiver.init(self)

File “C:\Users\Rob\Eclipse\Workspace\Quiver\src\gui\Quiver_xrc.py”, line 222, in init

self.mnuFile = self.FindItemById(xrc.XRCID(“mnuFile”)).GetSubMenu()

AttributeError: ‘NoneType’ object has no attribute ‘GetSubMenu’

20:31:57: Debug: …\include\wx/msw/private.h(697): ‘UnregisterClass’ failed with error 0x00000584 (class still has open windows.).


It does not matter whether I have the xrc, xcfg and generated module in the current working directory or my ./gui/ directory. I always seem to end up with a ‘NoneType’ object has no attribute ‘GetSubMenu’ error.

The offending line of code from the menu bar class is:

self.mnuFile = self.FindItemById(xrc.XRCID(“mnuFile”)).GetSubMenu()

from the code snippet below…

class xrcmnbQuiver(wx.MenuBar):

def init(self):

pre = get_resources().LoadMenuBar(“mnbQuiver”)

self.PostCreate(pre)

Define variables for the menu items

idx = self.FindMenu(“New”)

if idx != wx.NOT_FOUND:

self.mnuFile = self.GetMenu(idx)

else:

self.mnuFile = self.FindItemById(xrc.XRCID(“mnuFile”)).GetSubMenu()

self.mniNew = self.FindItemById(xrc.XRCID(“mniNew”))

Whilst I would prefer to have the XRCed generated module and associated files in a folder of my choosing the problem is that I can’t even make it work in the current working directory.

Curiously, it did work in one version of my code (curses for not keeping a GIT or SVN repository) but when it stopped working, all I did was and another panel to the xrc file. I actually did not touch the menu bar.

Anyway…thank you once again for taking the time to look at my problem and if there is anything else you can suggest I would be most grateful.

Regards

Rob M

Because FindItemById is returning None, meaning that it couldn't find the item you are searching for. If the "mnuFile" item is a menu or menubar then FindItemById is not expected to work, since they are not real window objects. Instead you should use frame.GetMenuBar() and/or methods of the menubar or menu classes to dig deeper if needed.

···

On 10/30/12 2:39 AM, Rob wrote:

     self.mnuFile = self.FindItemById(xrc.XRCID("mnuFile")).GetSubMenu()
AttributeError: 'NoneType' object has no attribute 'GetSubMenu'
20:31:57: Debug: ..\..\include\wx/msw/private.h(697): 'UnregisterClass'
failed with error 0x00000584 (class still has open windows.).
--------------------------------------------------------------------------------------------

It does not matter whether I have the xrc, xcfg and generated module in
the current working directory or my ./gui/ directory. I always seem to
end up with a 'NoneType' object has no attribute 'GetSubMenu' error.

--
Robin Dunn
Software Craftsman

Hi Robin,

Thanks again for taking the time to look at my problem…

I tried generating the py module from XCRed with the xrc resources embedded in the module (in order to take my folder structure out of the equation).

I also made the menubar a child of my mainframe in XRCed instead of its own class.

The funny thing is that I still get the same exception.

If I test the main frame in XRCed it displays perfectly, menubar and all.

As soon as I use it in my app I get the exception.

The line that causes the exception is generated by XRCed so I don’t quite understand what I have done in my code that subclasses the generated code that causes it to fail.

Does that make sense?

Thanks again

Rob M

Please make a runnable, small as possible, sample application that demonstrates the problem. MakingSampleApps - wxPyWiki

···

On 11/1/12 4:31 AM, Rob wrote:

Hi Robin,

Thanks again for taking the time to look at my problem....

I tried generating the py module from XCRed with the xrc resources
embedded in the module (in order to take my folder structure out of the
equation).

I also made the menubar a child of my mainframe in XRCed instead of its
own class.

The funny thing is that I still get the same exception.

If I test the main frame in XRCed it displays perfectly, menubar and all.

As soon as I use it in my app I get the exception.

The line that causes the exception is generated by XRCed so I don't
quite understand what I have done in my code that subclasses the
generated code that causes it to fail.

Does that make sense?

--
Robin Dunn
Software Craftsman

Hi Robin,

Please see attached…

Note: I manually modified the XRCed generated module so that it points to the xrc file in my /src/gui folder, which produces the exception in previous messages.

If I revert to the module as generated by XRCed it produces a similar but different exception presumably because it cannot find the xrc file.

What I am actually seeking to do is have the all xrc, and forms gui related content stored in the /src/gui folder.

I’m using Python version 2.6.5 and wxPython 2.8.10.1.

Thanks again for your help.

Sample.zip (7.97 KB)

self.mnuFile = self.GetMenuBar().FindItemById(xrc.XRCID("mnuFile")).GetSubMenu()

You're still having the problem of FindItemById returning None, and calling None.GetSubMenu doesn't work. FindItemById is meant to return wx.MenuItems, not wx.Menus, and for menus in a menubar there is no menu item.

However you really do not need to do that, at least with the code you've shown in the sample. You are only using the self.mnu* attributes for binding EVT_MENU handlers, however opening a menu on the menubar does not generate a EVT_MENU event. So there really is no reason to assign a variable or bind an event handler for them.

If there is some other reason that you need to get a menu that is in the menubar then you should do menuBar.FindMenu(label) or use menuBar.FindItemById with the ID of some item within the menu and then use that item's GetMenu method to get the menu that the item is in (after ensureing that FindItemById did not return None.)

···

On 11/2/12 5:10 AM, Rob wrote:

Hi Robin,

Please see attached...

Note: I manually modified the XRCed generated module so that it points
to the xrc file in my /src/gui folder, which produces the exception in
previous messages.

If I revert to the module as generated by XRCed it produces a similar
but different exception presumably because it cannot find the xrc file.

What I am actually seeking to do is have the all xrc, and forms gui
related content stored in the /src/gui folder.

I'm using Python version 2.6.5 and wxPython 2.8.10.1.

--
Robin Dunn
Software Craftsman

Doh…

Finally…I get what you’re telling me and now I understand why it was working for me before and suddenly started giving me exceptions.

Originally I did not have the EVT_MNU and ‘Assign Variable’ checked for the menu bar or menus, hence it worked.

I added those later ‘just in case’ and couldn’t make the connection with what was happening in the generated code.

Thankyou so much for getting me through that…

As an aside though…It does seem strange that XRCed would generate ‘faulty code’ and or in the case that those options are chosen.

In any case, thanks again Robin…I really appreciate your support (and patience).

Regards

Rob M