I modified the example from propgrid.PGProperty - creating-custom-properties.
The wiki class did not function, as it a) raised a TypeError (see below[1]), b) the value 44 was not displayed in the property grid.
With my modification, my “MiniApp” below [2]
- does not display the value 44 and crashes when I close the gui window (MainLoop exception [3])
- -or-
- displays the value 44, but only if I set a break point right after super().init() in MyProperty and interrupt the interpreter by that manner.
Can someone tell me, what I am missing? Why is the value display if put a breakpoint in the script? Why do I get that exception [2]? I have implemented GetValueAsString and still raise the assertion error.
I should not have to implement my own wxVariant type, or do I have to? The documentation (also found at link above) is uncertain:
```
Since wx.propgrid.PGProperty derives from wx.Object, you can use standard DECLARE_DYNAMIC_CLASS and IMPLEMENT_DYNAMIC_CLASS macros. From the above example they were omitted for sake of simplicity, and besides, they are only really needed if you need to use RTTI with your property class. You can change the ‘value type’ of a property by simply assigning different type of variant with SetValue. It is mandatory to implement VariantData class for all data types used as property values. You can use macros declared in wx.propgrid.PropertyGrid headers. For instance: […WHERE???]
# NOTE: wxVariants are handled internally in wxPython. Conversions are
# implicitly done for those types that wxVariant already knows about, and
# the Raw PyObject is used for those that it doesn’t know about.
```
[1]:
TypeError: descriptor '__init__' requires a 'sip.simplewrapper' object but received a 'str'
[2]
Python313\site-packages\wx\core.py", line 2262, in MainLoop
rv = wx.PyApp.MainLoop(self)
wx._core.wxAssertionError: C++ assertion ""GetChildCount() > 0"" failed at ..\..\src\propgrid\property.cpp(1016) in wxPGProperty::ValueToString(): If user property does not have any children, it must override GetValueAsString
[3] My snippet. Raises [2].
import wx
import wx.propgrid
class Alpha:
def __init__(self, val: int = None, str_val: str = None):
if val is None:
self.value = int(str_val)
else:
self.value = val
@property
def Value(self) -> int:
return self.value
def to_str(self) -> str:
return str(self.value)
class MyProperty(wx.propgrid.PGProperty):
def __init__(self, label, name, value : Alpha):
super().__init__(label, name)
self.m_value = value
# self.SetValue(value) # tried as alternative
def DoGetEditorClass(self):
return wx.propgrid.PGTextCtrlEditor
def ValueToString(self, value, argFlags=0):
return value.to_str()
def StringToValue(self, text, argFlags=0):
return True, Alpha(str_val=text)
def GetValueAsString(self, argFlags=0):
return self.m_value.to_str()
class MiniFrame(wx.Frame):
def __init__(self):
super().__init__(None, title="PGProperty")
pan = wx.Panel(self)
siz = wx.BoxSizer(wx.VERTICAL)
pan.SetSizer(siz)
ppgm = wx.propgrid.PropertyGridManager(pan, style=wx.propgrid.PG_TOOLBAR | wx.propgrid.PGMAN_DEFAULT_STYLE)
siz.Add(ppgm, 1, wx.EXPAND)
ppg = ppgm.AddPage("1")
ppg.Append(MyProperty("c", "c", Alpha(44)))
self.SetSize(wx.Size(300, 200))
self.Fit()
class MiniApp(wx.App):
def OnInit(self):
try:
self.frm = MiniFrame()
self.frm.CenterOnScreen()
self.frm.Show()
except Exception as e:
import traceback as tb
wx.MessageBox("\n".join(tb.format_exception(e)))
exit()
return True
if __name__ == "__main__":
app = MiniApp()
app.MainLoop()