1

コンテンツが垂直方向の境界を超えた場合に垂直スクロールバーを自動的に挿入するパネル サブクラスを実装しようとしています。パネルがあらゆる点で通常のパネルとまったく同じように機能するようにしたいのですが、1 つの点を除いて: パネルの最小の高さがサイザーの最小の高さである代わりに、静的な値 (200 など) を持つ必要があります。パネルがサイザーの高さよりも低い場合、垂直スクロールバーが表示されます。つまり、パネルの高さがサイザーの最小高さよりも高い場合、通常のパネルとまったく同じように機能する必要があります。

私が抱えている問題は、パネル上のDoGetBestSizeやのような関数をオーバーライドしても効果がないことです。これらの関数は呼び出されないためです (ブレークポイントを挿入して確認しました)。GetMinSizeパネルの親はパネルのサイザーと直接通信していると思います。この場合、パネルの外側から設定された通常のボックスサイザーです。

class ScrolledPanel(wx.Panel):
    """A panel that will automatically add scrollbars when needed."""

    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        self.SetBackgroundColour('#FF0000')

    # This function is never called.
    def DoGetBestSize(self):
        """Override the minimum size of the panel."""

        default = self.GetSizer().GetMinSize()
        default.SetHeight(250)

        return default

私が求めている効果を達成することは可能ですか?もしそうなら、どうすれば上記の問題を回避できますか?

これは、スクロールされたパネルを使用しようとしているコードです


アップデート

私はSetSizer関数をオーバーライドしようと考え、サイザーの人質を取り、サイズについて相談しましたが、実際にはパネルにサイザーを設定しませんでした。そうすれば、次のようなカスタム サイズ関数DoGetBestSizeが呼び出されます。しかし、それは失敗しました。sizer が設定されていない場合でも、これらの関数が呼び出されることはありません。Panelと の両方を試しましたPyPanel。ここに私の現在のスクロールパネルがあります:

class ScrolledPanel(wx.PyPanel):
    """A panel that will automatically add scrollbars when needed."""

    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        self.SetBackgroundColour('#FF0000')

    # This function is called.
    def SetSizer(self, sizer):
        import pdb; pdb.set_trace()
        self._pet_sizer = sizer

    # The below functions are never called.
    def DoGetBestSize(self):
        """Override the minimum size of the panel."""
        import pdb; pdb.set_trace()
        default = self.GetSizer().GetMinSize()
        default.SetHeight(250)

        return default

    def DoGetClientSize(self):
        import pdb; pdb.set_trace()

    def DoGetSize(self):
        import pdb; pdb.set_trace()

    def DoGetVirtualSize(self):
        import pdb; pdb.set_trace()
4

3 に答える 3

2

現在、wxPython でメソッドをオーバーライドするには、Python でオーバーライドされたメソッドへの C++ 仮想への呼び出しの一部を反映するように設計された基本クラスを使用する必要があります。つまり、パネルでこれらをキャッチしたい場合は、wx.Panel ではなく wx.PyPanel からクラスを派生させる必要があります。http://wiki.wxpython.org/OverridingMethodsを参照してください。

于 2013-01-28T21:27:08.667 に答える
0

特別なことをする必要はありません。を含むSetVirtualSize()いずれかを呼び出すと、必要に応じてすでにスクロールバーが表示され、サイザーは仮想サイズを使用してこのウィンドウのコンテンツをレイアウトします。wxWindowwxPanel

于 2013-01-28T15:46:43.250 に答える
0

なぜ車輪の再発明をするのですか?wxPython は ScrolledPanel ウィジェットを提供します: wx.lib.scrolledpanel

あなたはそれを使うべきです。wxPython デモには例があります。

編集: これは、サイザー内に scrolledPanel を含むスクリプトの例です。

import wx
import  wx.lib.scrolledpanel as scrolled

########################################################################
class MyScrolledPanel(scrolled.ScrolledPanel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        scrolled.ScrolledPanel.__init__(self, parent)


########################################################################
class MainPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)

        text = "one two buckle my shoe three four shut the door five six pick up sticks seven eight lay them straight nine ten big fat hen"

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sPanel = MyScrolledPanel(self)

        words = text.split()
        for word in words:
            hSizer = wx.BoxSizer(wx.HORIZONTAL)
            label = wx.StaticText(sPanel, -1, word+":")
            tc = wx.TextCtrl(sPanel, -1, word, size=(50,-1))

            hSizer.Add(label, flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=10)
            hSizer.Add(tc, flag=wx.LEFT, border=10)
            sizer.Add(hSizer)

        sPanel.SetSizer(sizer)
        sPanel.SetAutoLayout(1)
        sPanel.SetupScrolling()

        mainSizer.Add(sPanel, 1, wx.EXPAND)
        self.SetSizer(mainSizer)


########################################################################
class MainFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None)
        panel = MainPanel(self)

if __name__ == "__main__":
    app = wx.App(False)
    frame = MainFrame()
    frame.Show()
    app.MainLoop()
于 2013-01-28T14:20:06.277 に答える