我的问题
我在 Python 中使用 wxWidgets 库(通过 wxPython 包装器)。我正在尝试实现一个类 PaddedStaticText,它的行为与 WX StaticText 类相同,但在每一侧都有一个用户可配置的填充。理想情况下,PaddedStaticText 将成为 StaticText 的替代品。那种尖叫“子类”,对吧?不幸的是,我认为如果我要继承 StaticText,我基本上必须重新实现它的所有绘图例程,而我没有 WX 专业知识来做到这一点。
解决方案一
我想出的解决方案是实现一个具有 StaticText 属性的类,该属性将放置在几个 Sizer 中以影响填充:
class PaddedStaticText(wx.Window):
def __init__(self, parent, label='', padding=(0, 0, 0, 0), **kwargs):
wx.Window.__init__(self, parent)
self.text = wx.StaticText(self, label=label, **kwargs)
inner_sizer = wx.BoxSizer(wx.VERTICAL)
inner_sizer.Add((0, padding[0]))
inner_sizer.Add(self.text, proportion=1, flag=wx.EXPAND)
inner_sizer.Add((0, padding[2]))
outer_sizer = wx.BoxSizer(wx.HORIZONTAL)
outer_sizer.Add((padding[3], 0))
outer_sizer.Add(inner_sizer, proportion=1, flag=wx.EXPAND)
outer_sizer.Add((padding[1], 0))
self.SetSizer(outer_sizer)
这个类继承自 wx.Window,因此它可以在许多我可以使用 StaticText 的相同上下文中使用——例如,将它添加到 Sizer。但是,由于 PaddedStaticText 实际上不是 StaticText,我不能只在其中一个实例上调用 SetFont()。我必须制作自己的代理方法:
def SetFont(self, *args, **kwargs):
self.text.SetFont(*args, **kwargs)
当然,我必须为我希望可用的每个 StaticText 方法编写这样的存根。这种方法有效,但感觉一点也不优雅。我认为在 Python 中必须有更好的方法来做这样的事情。
解决方案二
基于this SO answer我写了这个简单的代理类:
class Proxy(object):
def __init__(self, underlying_object):
self._underlying_object = underlying_object
def __getattribute__(self, name):
obj = object.__getattribute__(self, '_underlying_object')
return object.__getattribute__(obj, name)
然后我可以将 PaddedStaticText 表示为 Proxy 的子类,并将其underlying_object
设置为 StaticText 实例。不幸的是,当我尝试将新的 PaddedStaticText 实例添加到 Sizer 时,WX 犹豫了。由于它是 C++ 库的包装器,我猜 WX 并不真正尊重 Python 的鸭子类型:即使 PaddedStaticText 可以在调用 StaticText 方法时做出适当的响应,wxPython 关心的只是它继承自 Proxy 而不是来自 wx.Window。
从那里我简单地尝试让 PaddedStaticText 从 Proxy 和 wx.Window 继承,但这没有用(无论如何它是继承菱形的一个例子)。我怎样才能以恰到好处的方式实现我的 PaddedStaticText 类?我很感激关于我的任何一个解决方案想法的建议,或者解决问题的完全不同的东西。