2

私の問題

Python で wxWidgets ライブラリを使用しています (wxPython ラッパーを介して)。私は、WX StaticText クラスと同じように動作するが、両側にユーザ​​ーが構成可能なパディングを持つクラス、PaddedStaticText を実装しようとしています。理想的には、PaddedStaticText は StaticText のドロップイン代替品になります。そういう悲鳴は「サブクラス」ですよね?残念ながら、StaticText をサブクラス化するには、基本的にすべての描画ルーチンを再実装する必要があると思いますが、それを行うための WX の専門知識はありません。

解決策 1

私が思いついた解決策は、パディングに影響を与えるためにいくつかのサイザー内に配置される StaticText 属性を持つクラスを実装することでした。

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 ではないため、インスタンスの 1 つで SetFont() を呼び出すことはできませんでした。独自のプロキシ メソッドを作成する必要がありました。

    def SetFont(self, *args, **kwargs):
        self.text.SetFont(*args, **kwargs)

もちろん、使用可能にしたい StaticText のメソッドごとに、そのようなスタブを作成する必要がありました。このアプローチは機能しますが、エレガントな感じはしませんでした。Python では、このようなことを行うためのより良い方法が必要であると考えました。

解決策 2

this SO answerに基づいて、この単純な Proxy クラスを作成しました。

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 のサブクラスとして表現し、StaticTextunderlying_objectインスタンスに設定します。残念ながら、新しい PaddedStaticText インスタンスを Sizer に追加しようとすると、WX が反応しなくなりました。これは C++ ライブラリのラッパーであるため、WX は Python のダック タイピングを実際には尊重していないと思います。PaddedStaticText は、StaticText メソッドが呼び出されるたびに適切に応答できますが、wxPython が気にしたのは、Proxy から継承されたものではなく、Proxy から継承されたという事実だけでした。 wx.Window から。

そこから、PaddedStaticText を Proxy と wx.Window の両方から継承するように簡単にいじりましたが、うまくいきませんでした (とにかく継承ダイヤモンドの例です)。Just Works の方法で PaddedStaticText クラスを実装するにはどうすればよいですか? 私のソリューションのアイデアのいずれか、または問題を解決するまったく別のものについての提案をいただければ幸いです。

4

1 に答える 1

1

私がすることは次のとおりです。

class PaddedStaticText(wx.Window):

    def __init__(...):
       self.text = ...
       ...

    def __getattr__(self, name):
        '''delegate missing attributes to text'''
        return getattr(self.text, name)

__getattr__これは、フェールオーバー (他に何も機能しない場合にのみ呼び出される) を使用して基本的な継承アプローチを委任に拡張します。

これにより、wxwindows が期待するものに近くなり、魔法の量が減りますが、それでもSetFont.

あるいは、.text( ではなく.__text) を使用する場合は、次のように使用できます。

foo = PaddedStaticText(...)
foo.text.SetFont(...)

ただし、既存の StaticText インスタンスを置き換えることはできません。

[編集] 遅くなったので、明日改善するかもしれませんが、使用する必要がある場合は、__getattribute__どのメソッドが必要かを明示することをお勧めします。それはより多くのタイピングですが、私の経験では、Python での完全自動プロキシは、厄介な方法であなたを驚かせることがよくあります。次のようなもの:

def __getattribute__(self, name):
    if name in ('SetFont', ...):
        return getattr(self.text, name)
    else:
        return super(...).__getattribute__(self, name)

または(おそらく高速ですが、インスタンスごとにより多くのメモリを消費します):

def __init__(...):
    self.text = ...
    for name in ('SetFont', ...):
        setattr(self, name, getattr(self.text, name))
于 2013-10-09T20:29:44.497 に答える