【问题标题】:How do I override a Panel's minimum size?如何覆盖面板的最小尺寸?
【发布时间】:2013-01-28 09:36:45
【问题描述】:

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

我遇到的问题是面板上的DoGetBestSizeGetMinSize 之类的覆盖函数没有任何效果,因为这些函数从未被调用(我通过插入断点进行了检查)。我猜面板的父级直接与面板的 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

能达到我想要的效果吗?如果是这样,我该如何规避上述问题?

Here is the code in which I'm trying to use the scrolled panel.


更新

我想我会尝试覆盖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()

【问题讨论】:

    标签: python wxpython wxwidgets


    【解决方案1】:

    wxPython 中的重写方法目前需要使用基类,这些基类旨在反映对 Python 中重写方法的某些 C++ 虚拟函数的调用。这意味着如果你想在一个面板中捕捉那些你需要从 wx.PyPanel 而不是 wx.Panel 派生你的类。见http://wiki.wxpython.org/OverridingMethods

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • -1 这是不正确的。设置虚拟大小会影响控件的布局,但它永远不会产生滚动条。
      • 这绝对是正确的,这就是wxScrolledWindow 的工作方式。不过,您可能也需要致电SetScrollRate()
      • 如果wxScrolledWindow 是这样工作的,那么wxPanelwxScrolledWindow 有什么区别?
      • 没那么多。基本滚动在 wxWidgets 中的wxWindow 级别实现,wxScrolledWindow "just" 添加了方便的方法来配置它和更新滚动条。
      【解决方案3】:

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

      你应该使用它。 wxPython demo有一个例子。

      编辑:这是一个在 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()
      

      【讨论】:

      • 我不是在重新发明轮子,而是在努力改进它。 wx.lib.scrolledpanel.ScrolledPanel 需要有固定的位置和大小才能工作。当我将它放入尺寸测定仪时,它开始像普通面板一样工作。
      • 不确定你在做什么,但我可以让一个 scrolledPanel 在 sizer 中正常工作。它不需要固定的位置或大小。我添加了一个示例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-16
      • 1970-01-01
      • 1970-01-01
      • 2017-09-30
      • 1970-01-01
      • 2018-01-16
      • 2023-03-19
      相关资源
      最近更新 更多