1

我正在尝试实现一个面板子类,如果内容超出其垂直边界,它将自动插入垂直滚动条。我希望面板在各个方面都像普通面板一样工作除了一个:面板的最小高度不是它的尺寸器的最小高度,它应该有一个静态值(比如 200),并且当面板低于其尺寸器的高度,应该会出现一个垂直滚动条。换句话说,当面板的高度高于sizer的最小高度时,它的功能应该与普通面板完全一样。

我遇到的问题是面板上的DoGetBestSize和之类的覆盖函数GetMinSize没有任何效果,因为这些函数从未被调用(我通过插入断点进行了检查)。我猜面板的父级直接与面板的 sizer 通信,在这种情况下,它是从面板外部设置的普通 box sizer。

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功能,将那个sizer作为人质并就尺寸进行咨询,但实际上并没有在面板上设置sizer。这样DoGetBestSize就可以调用自定义大小函数。虽然失败了。即使没有设置 sizer,这些函数仍然不会被调用。我都试过了PanelPyPanel。这是我当前的滚动面板:

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.PyPanel 而不是 wx.Panel 派生你的类。见http://wiki.wxpython.org/OverridingMethods

于 2013-01-28T21:27:08.667 回答
0

你不需要做任何特别的事情。如果您调用SetVirtualSize()any wxWindow,包括wxPanel,它已经会根据需要显示滚动条,并且 sizer 将使用虚拟大小来布置此窗口内容。

于 2013-01-28T15:46:43.250 回答
0

你为什么要重新发明轮子?wxPython 提供了一个 ScrolledPanel 小部件:wx.lib.scrolledpanel

你应该只使用它。wxPython 演示有一个示例。

编辑:这是一个在 sizer 内带有 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 回答