I've just added the first version of wxPropertyGrid bindings
for wxPython 2.9.0 in the SVN trunk. They seem to build just
fine, but I get strange errors when running the demo (based
on my old test_propgrid.py). It seems my global variables
class instance, derived from wxModule, is not really
initialized.
Note that this problem does not appear when running my
plain test_propgrid.py, available here:
I've just added the first version of wxPropertyGrid bindings
for wxPython 2.9.0 in the SVN trunk.
Thanks! I've been meaning to ask you about them but it kept slipping my mind.
They seem to build just
fine, but I get strange errors when running the demo (based
on my old test_propgrid.py). It seems my global variables
class instance, derived from wxModule, is not really
initialized.
Note that this problem does not appear when running my
plain test_propgrid.py, available here:
wxModules are initialized and executed when wxWidgets is first loaded and is initializing its own globals, but when your python module is imported later after that has happened there isn't anything to trigger the execution of the new wxModules in the newly loaded dynamic libraries. So you need to provide a function that will do it for you, and then call that function when the Python module is imported.
For example, look in XRC at the wxXmlInitResourceModule function. In the .i file I've got code like this that gets merged into the module's init function:
%init %{
wxXmlInitResourceModule();
%}
Also, the first wxPython 2.9 release is going to be
based on the code in WX_2_9_0_BRANCH, right? I've made
my C++ code tweaks there.
Yes. I didn't make a 2.9.0 specific branch because I thought it was only going to be active for a few days and because I figured that I would not be working on more than one 2.9.x branch at a time. At least one of my assumptions was correct.
wxModules are initialized and executed when wxWidgets is first loaded and is initializing its own globals, but when your python module is imported later after that has happened there isn't anything to trigger the execution of the new wxModules in the newly loaded dynamic libraries. So you need to provide a function that will do it for you, and then call that function when the Python module is imported.
For example, look in XRC at the wxXmlInitResourceModule function. In the .i file I've got code like this that gets merged into the module's init function:
%init %{
wxXmlInitResourceModule();
%}
All right, that's pretty much what I had to do to get it working now.
wxModules are initialized and executed when wxWidgets is first loaded and is initializing its own globals, but when your python module is imported later after that has happened there isn't anything to trigger the execution of the new wxModules in the newly loaded dynamic libraries. So you need to provide a function that will do it for you, and then call that function when the Python module is imported.
For example, look in XRC at the wxXmlInitResourceModule function. In the .i file I've got code like this that gets merged into the module's init function:
%init %{
wxXmlInitResourceModule();
%}
All right, that's pretty much what I had to do to get it working now.
It would be nice to be able to get rid of these swig warnings:
../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(362): operator= ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(383): operator++ ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(383): operator++ ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(384): operator-- ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(384): operator-- ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(362): operator= ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(383): operator++ ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(383): operator++ ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(384): operator-- ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(384): operator-- ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:303: Warning(362): operator= ignored
../wxWidgets/include/wx/propgrid/manager.h:66: Warning(402): Base class 'wxPropertyGridPageState' is incomplete.
../wxWidgets/include/wx/propgrid/propgriddefs.h:272: Warning(402): Only forward declaration 'wxPropertyGridPageState' was found.
src/propgrid_cbacks.i:481: Warning(401): Nothing known about base class 'wxSystemColourProperty'. Ignored.
src/propgrid_cbacks.i:856: Warning(401): Nothing known about base class 'wxColourProperty'. Ignored.
I'm getting some Assertion errors when starting up the demo, and also some tracebacks:
22:07:18: Debug: /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s == g_invalidStringContent" failed in InitAfterAdded(): Implement ValueToString() instead of GetValueAsString()
22:07:45: Debug: /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s == g_invalidStringContent" failed in InitAfterAdded(): Implement ValueToString() instead of GetValueAsString()
22:07:48: Debug: /projects/wx/2.9/wxWidgets/src/propgrid/propgridiface.cpp(571): assert "p" failed in GetPropertyByNameA(): no property with name 'NotARealProperty'
Traceback (most recent call last):
File "/projects/wx/2.9/wxPython/demo/PropertyGrid.py", line 512, in OnPropGridSelect
print('%s selected'%(event.GetPropertyName()))
AttributeError: 'PropertyGridEvent' object has no attribute 'GetPropertyName'
Traceback (most recent call last):
File "/projects/wx/2.9/wxPython/demo/PropertyGrid.py", line 512, in OnPropGridSelect
print('%s selected'%(event.GetPropertyName()))
AttributeError: 'PropertyGridEvent' object has no attribute 'GetPropertyName'
Also, some of the property widgets are a little too cramped on the Mac. I'll attach a couple samples.
There is also this message from the SWIG runtime: "swig/python detected a memory leak of type 'wxColourPropertyValue *', no destructor found." This means that there is a wxColourPropertyValue object that was created in Python and the runtime thinks that the proxy object still owns the C++ object, but there is no destructor for it to call. To take care of this you can simply define a destructor for SWIG to see (it will just generate the "delete obj" code and it won't matter if there is a real dtor or just the implicit one created by the compiler.) If ownership of that object is ever transfered to some other object then be sure to use the disown directive so SWIG will clear the flag indicating that the proxy owns the C++ object. For example, in the wxListCtrl class I have this for disowning the imagelist when it is passed to AssignImageList:
What is the best way to do this without adding '#ifndef SWIG' sections
in the header files? Just disable the warning?
../wxWidgets/include/wx/propgrid/manager.h:66: Warning(402): Base class 'wxPropertyGridPageState' is incomplete.
../wxWidgets/include/wx/propgrid/propgriddefs.h:272: Warning(402): Only forward declaration 'wxPropertyGridPageState' was found.
src/propgrid_cbacks.i:481: Warning(401): Nothing known about base class 'wxSystemColourProperty'. Ignored.
src/propgrid_cbacks.i:856: Warning(401): Nothing known about base class 'wxColourProperty'. Ignored.
Thing is, I'm not sure if it is a good idea to expose all the property
classes in wxPython, as that's *a lot* of SWIG code, and wxPG .pyd
file is already almost double the size of wxAUI one. That is why many
property classes and wxPropertyGridPageState have "#ifndef SWIG"
condition around them. Naturally, you can still create these properties
using factory functions provided in propgrid.i, but you can't derive
from them (I've tried to exclude property classes that are particularly
un-useful as a basis for derived user properties). I guess I could
disable the SWIG warning if I cannot think of any better overall
solution.
I'm getting some Assertion errors when starting up the demo, and also some tracebacks:
22:07:18: Debug: /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s == g_invalidStringContent" failed in InitAfterAdded(): Implement ValueToString() instead of GetValueAsString()
22:07:45: Debug: /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s == g_invalidStringContent" failed in InitAfterAdded(): Implement ValueToString() instead of GetValueAsString()
22:07:48: Debug: /projects/wx/2.9/wxWidgets/src/propgrid/propgridiface.cpp(571): assert "p" failed in GetPropertyByNameA(): no property with name 'NotARealProperty'
The above ones I don't get, at least not by just starting up the demo.
I'm testing on WinXP SP3, with Python 2.6.2 and wxPython debug builds
compiled using VC9 (debugging in VC2008 Express IDE).
Traceback (most recent call last):
File "/projects/wx/2.9/wxPython/demo/PropertyGrid.py", line 512, in OnPropGridSelect
print('%s selected'%(event.GetPropertyName()))
AttributeError: 'PropertyGridEvent' object has no attribute 'GetPropertyName'
Traceback (most recent call last):
File "/projects/wx/2.9/wxPython/demo/PropertyGrid.py", line 512, in OnPropGridSelect
print('%s selected'%(event.GetPropertyName()))
AttributeError: 'PropertyGridEvent' object has no attribute 'GetPropertyName'
These I got and they should be fixed now in SVN trunk.
Also, some of the property widgets are a little too cramped on the Mac. I'll attach a couple samples.
Right, but as of this time I don't have a Mac OS X box to develop with,
I don't think I can do much about it.
There is also this message from the SWIG runtime: "swig/python detected a memory leak of type 'wxColourPropertyValue *', no destructor found." This means that there is a wxColourPropertyValue object that was created in Python and the runtime thinks that the proxy object still owns the C++ object, but there is no destructor for it to call. To take care of this you can simply define a destructor for SWIG to see (it will just generate the "delete obj" code and it won't matter if there is a real dtor or just the implicit one created by the compiler.) If ownership of that object is ever transfered to some other object then be sure to use the disown directive so SWIG will clear the flag indicating that the proxy owns the C++ object. For example, in the wxListCtrl class I have this for disowning the imagelist when it is passed to AssignImageList:
What is the best way to do this without adding '#ifndef SWIG' sections
in the header files? Just disable the warning?
You can use the %ignore directive with the function signature before the %include's to exclude just those items.
../wxWidgets/include/wx/propgrid/manager.h:66: Warning(402): Base class 'wxPropertyGridPageState' is incomplete.
../wxWidgets/include/wx/propgrid/propgriddefs.h:272: Warning(402): Only forward declaration 'wxPropertyGridPageState' was found.
src/propgrid_cbacks.i:481: Warning(401): Nothing known about base class 'wxSystemColourProperty'. Ignored.
src/propgrid_cbacks.i:856: Warning(401): Nothing known about base class 'wxColourProperty'. Ignored.
Thing is, I'm not sure if it is a good idea to expose all the property
classes in wxPython, as that's *a lot* of SWIG code, and wxPG .pyd
file is already almost double the size of wxAUI one. That is why many
property classes and wxPropertyGridPageState have "#ifndef SWIG"
condition around them.
Ignoring a base class without a warning might be a bit more tricky. Maybe just a forward declaration will take care of it. Don't stress too much about it though, it's not a huge deal if you can't get rid of the warnings.
There is also this message from the SWIG runtime: "swig/python detected a memory leak of type 'wxColourPropertyValue *', no destructor found." This means that there is a wxColourPropertyValue object that was created in Python and the runtime thinks that the proxy object still owns the C++ object, but there is no destructor for it to call. To take care of this you can simply define a destructor for SWIG to see (it will just generate the "delete obj" code and it won't matter if there is a real dtor or just the implicit one created by the compiler.) If ownership of that object is ever transfered to some other object then be sure to use the disown directive so SWIG will clear the flag indicating that the proxy owns the C++ object. For example, in the wxListCtrl class I have this for disowning the imagelist when it is passed to AssignImageList:
Yes, I received this error message as well and wondered about it.
I'll try to fix it soon.
I have to admit I'm a bit stuck here. wxColourPropertyValue
(in advprops.h) inherits from wxObject and has a virtual
destructor that is visible to SWIG. I've added, for testings purposes,
which should cover all the cases visible to SWIG, but unfortunately
that doesn't make any difference. Only place where ownership might
be transferred is in PyObject<->wxVariant conversion code, but at least
my breakpoints in VC2008 IDE did not show that it was ever called. Also,
I handle wxCPV in the conversion code in the same way as wxFont and
wxColour, so I think that should not matter.
I'm getting some Assertion errors when starting up the demo, and also some tracebacks:
22:07:18: Debug: /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s == g_invalidStringContent" failed in InitAfterAdded(): Implement ValueToString() instead of GetValueAsString()
22:07:45: Debug: /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s == g_invalidStringContent" failed in InitAfterAdded(): Implement ValueToString() instead of GetValueAsString()
22:07:48: Debug: /projects/wx/2.9/wxWidgets/src/propgrid/propgridiface.cpp(571): assert "p" failed in GetPropertyByNameA(): no property with name 'NotARealProperty'
The above ones I don't get, at least not by just starting up the demo.
I'm testing on WinXP SP3, with Python 2.6.2 and wxPython debug builds
compiled using VC9 (debugging in VC2008 Express IDE).
Try running the PropertyGrid.py standalone (IOW, not from within the demo app.) The default assertion mode for wxPython apps is the assertions are turned into exceptions but those can be suppressed as you've done for the NotARealProperty and etc. items with an empty try/except, or sometimes other code nesting situations can cause the error to be cleared before it is displayed as is happening with the ValueToString assertions. The default wx mode on the other hand is to show an assertion dialog and the run.py script (used when running a sample standalone) sets the assertion mode to behave that way so you can be sure to see those messages
I've made some changes to the demo to avoid the assertions, but somethings is still not right with the property classes defined in the demo. Could you please take a look at those?
Also, some of the property widgets are a little too cramped on the Mac. I'll attach a couple samples.
Right, but as of this time I don't have a Mac OS X box to develop with,
I don't think I can do much about it.
There is also this message from the SWIG runtime: "swig/python detected a memory leak of type 'wxColourPropertyValue *', no destructor found." This means that there is a wxColourPropertyValue object that was created in Python and the runtime thinks that the proxy object still owns the C++ object, but there is no destructor for it to call. To take care of this you can simply define a destructor for SWIG to see (it will just generate the "delete obj" code and it won't matter if there is a real dtor or just the implicit one created by the compiler.) If ownership of that object is ever transfered to some other object then be sure to use the disown directive so SWIG will clear the flag indicating that the proxy owns the C++ object. For example, in the wxListCtrl class I have this for disowning the imagelist when it is passed to AssignImageList:
Yes, I received this error message as well and wondered about it.
I'll try to fix it soon.
I have to admit I'm a bit stuck here. wxColourPropertyValue
(in advprops.h) inherits from wxObject and has a virtual
destructor that is visible to SWIG. I've added, for testings purposes,
which should cover all the cases visible to SWIG, but unfortunately
that doesn't make any difference. Only place where ownership might
be transferred is in PyObject<->wxVariant conversion code, but at least
my breakpoints in VC2008 IDE did not show that it was ever called. Also,
I handle wxCPV in the conversion code in the same way as wxFont and
wxColour, so I think that should not matter.
Any additional debug tips are appreciated!
Best tips I can offer is to actually debug it! Since I didn't do that before and just made an assumption about the problem I sent you on a wild snake chase.
I just used a Python debugger and tracked down the source of the problem to the wxpg.SystemColourProperty in the demo. When the GetPropertyValues is called from the demo there is a problem in converting the value of that variant type and so what is being returned is the bare PySwigObject without any proxy class wrapped around it. I then jumped into the C++ debugger and found that when your wxVariant_to_PyObject tries to convert a variant of type "wxColourPropertyValue" the SWIG_Python_NewPointerObject function is not creating a new proxy instance because there is no Python class defined for wxColourPropertyValue. SWIG knows about the existance of the type, but since advprops.h was not being %included then it didn't see the full definition and it was not generating any wrapper code for it. Adding that %include and giving that header an additional #ifndef SWIG seems to have taken care of it. (Although the Get/SetPropertyValues in the demo for that type could use some help.)
Best tips I can offer is to actually debug it! Since I didn't do that before and just made an assumption about the problem I sent you on a wild snake chase.
I just used a Python debugger and tracked down the source of the problem to the wxpg.SystemColourProperty in the demo. When the GetPropertyValues is called from the demo there is a problem in converting the value of that variant type and so what is being returned is the bare PySwigObject without any proxy class wrapped around it. I then jumped into the C++ debugger and found that when your wxVariant_to_PyObject tries to convert a variant of type "wxColourPropertyValue" the SWIG_Python_NewPointerObject function is not creating a new proxy instance because there is no Python class defined for wxColourPropertyValue. SWIG knows about the existance of the type, but since advprops.h was not being %included then it didn't see the full definition and it was not generating any wrapper code for it. Adding that %include and giving that header an additional #ifndef SWIG seems to have taken care of it. (Although the Get/SetPropertyValues in the demo for that type could use some help.)
Many thanks for debugging and resolving this. One more useful thing to
back port into wxPG 1.4