编辑:我将问题保留为开放状态,因为它仍然是一个好问题,答案可能对其他人有用。但是,我会注意到,通过对AuiManager使用完全不同的方法,我找到了解决问题的实际方法;请参阅下面的answer

我正在研究MultiSplitterWindow的设置(花了很多时间后
SashLayoutWindow布局怪癖作斗争)。不幸的是,当我
创建一个MultiSplitterWindow,在拖动时看到一些意外行为
窗框:窗框可以拖动到包含窗框的外部
布局方向。至少可以说,这是我要避免的行为。

这是基本设置(您可以在wxPython中确认以下行为)
演示,仅用leftwin代替Panel1等,另请参见下面的示例应用)。我有RootPanel/BoxSizer的地方,有一个面板
(或Frame或您喜欢的任何类型的容器元素)和BoxSizer再次将MultiSplitterWindow添加到其中(如演示中所示)。

+--------------------------------+
|       RootPanel/BoxSizer       |
|+------------------------------+|
||     MultiSplitterWindow      ||
||+--------++--------++--------+||
||| Panel1 || Panel2 || Panel3 |||
|||        ||        ||        |||
||+--------++--------++--------+||
|+------------------------------+|
+--------------------------------+

拖动时,您可能会得到如下所示的内容,其中~!表示该面板“存在”但没有显示:
+--------------------------------+
|       RootPanel/BoxSizer       |
|+-------------------------------|~~~~~~~~~~~~~+
||           MultiSplitterWindow |             !
||+-----------------++-----------|~~++~~~~~~~~+!
|||      Panel1     ||   Panel2  |  !! Panel3 !!
|||                 ||           |  !!        !!
||+-----------------++-----------|~~++~~~~~~~~+!
|+-------------------------------|~~~~~~~~~~~~~+
+--------------------------------+

如果此时您将RootPanel拖动为比
整个面板集,您将再次看到所有面板。同样,如果您拖动
降低Panel1的宽度,您可以访问Panel3的腰带
再一次(当然,假设Panel2尚未太宽)。而且这个
正是检查工具报告的情况:RootPanel保留其大小,但MultiSplitterWindow的大小超出了RootPanel/BoxSizer

使用检查工具进行的进一步检查显示,虚拟宽度和客户端宽度值都为0,但是实际大小值在超出范围时为负(通过将其拖出窗口的相应像素数)。同样,这是坚果行为。我无法想象为什么人们会希望窗口以这种方式运行。

现在,如果按下Shift,这样_OnMouse方法MultiSplitterWindow调整邻居,这不会发生。因此,我的一个
方法就是简单地重写该方法。它有效,但是我更愿意
如果绝对必要,则以这种方式重写方法。还有另一种更好的方法
解决这个问题?看来这不是预期的或不可取的
行为,所以我想有一种解决它的标准方法。

我尝试过的其他方法:
  • 检查MultiWindowSplitter中值的总和是否超过
    包含窗口的宽度,使用每个EVT_SPLITTER_SASH_POS_CHANGEDEVT_SPLITTER_SASH_POS_CHANGING事件,
    然后尝试通过以下方法解决此问题:
  • 使用event.Veto()调用
  • 在拆分器
  • 上使用SetSashPosition()方法
  • 覆盖_OnMouse()方法以使用通常的行为
    与按住Shift键相关联。这行得通,但是最终
    给我其他我不喜欢的结果。
  • 通过SetMinimumPaneSize方法
  • 设置最小 Pane 大小
  • 通过MultiSplitterWindow设置SetMaxSize()的最大大小
  • 使用RootPanel/BoxSizer上的SetMaxSize()SetSizeHints()来设置RootPanel的最大大小。
  • 我什至使用容器上wx.EVT_SIZE的事件处理程序来完成此操作,以便RootPanel始终具有来自父框架元素
  • 的适当最大大小
  • 我已经尝试对MultiSplitterWindow使用相同的事件处理方法,但是也没有任何效果。

  • 版本信息

    我已经确认这会出现在Windows 32位和OS X 64位中,
    wxPython的最新快照版本,同时针对Python 2.7和3.3。

    工作示例(包括检查工具)

    以下本质上是重复(并略微简化了)演示源。这是对该问题的有效演示。
    import wx, wx.adv
    import wx.lib.mixins.inspection as wit
    from wx.lib.splitter import MultiSplitterWindow
    
    
    class AppWInspection(wx.App, wit.InspectionMixin):
        def OnInit(self):
            self.Init()  # enable Inspection tool
            return True
    
    
    class MultiSplitterFrame(wx.Frame):
        def __init__(self, *args, **kwargs):
            super().__init__(size=(800, 800), *args, **kwargs)
            self.SetMinSize((600, 600))
    
            self.top_sizer = wx.BoxSizer(orient=wx.HORIZONTAL)
            self.SetSizer(self.top_sizer)
    
            self.splitter = MultiSplitterWindow(parent=self, style=wx.SP_LIVE_UPDATE)
            self.top_sizer.Add(self.splitter, wx.SizerFlags().Expand().Proportion(1).Border(wx.ALL, 10))
    
            inner_panel1 = wx.Panel(parent=self.splitter)
            inner_panel1.SetBackgroundColour('#999980')
            inner_panel1_text = wx.StaticText(inner_panel1, -1, 'Inner Panel 1')
            inner_panel1.SetMinSize((100, -1))
    
            inner_panel2 = wx.Panel(parent=self.splitter)
            inner_panel2.SetBackgroundColour('#999990')
            inner_panel2_text = wx.StaticText(inner_panel2, -1, 'Inner Panel 2')
            inner_panel2.SetMinSize((100, -1))
            inner_panel2.SetMaxSize((100, -1))
    
            inner_panel3 = wx.Panel(parent=self.splitter)
            inner_panel3.SetBackgroundColour('#9999A0')
            inner_panel3_text = wx.StaticText(inner_panel3, -1, 'Inner Panel 3')
            inner_panel3.SetMinSize((100, -1))
    
            self.splitter.AppendWindow(inner_panel1)
            self.splitter.AppendWindow(inner_panel2)
            self.splitter.AppendWindow(inner_panel3)
    
    if __name__ == '__main__':
        app = AppWInspection(0)
        frame = MultiSplitterFrame(parent=None, title='MultiSplitterFrame Test')
        app.SetTopWindow(frame)
        frame.Show()
        app.MainLoop()
    

    最佳答案

    根据用户的需求,高级用户界面工具包的MultiSplitterWindow工具(Phoenix之前的版本here的文档; Phoenix docs here)可以使用一种可能的选项代替自定义管理的SashLayoutWindow(或AuiManager组合等)。 AuiManager为您自动执行许多此类操作。就我而言,我尝试使用MultiSplitterWindow作为控制相关UI的可折叠面板和可调整大小面板的一种方式,因此AuiManager非常适合:它已经内置了我需要的所有控件和约束。

    在这种情况下,所有要做的就是创建一个AuiManager实例

    (我将其留在此处作为答案,希望其他可能采取与我相同的幼稚方法的人会发现它很有用,但不选择它作为答案,因为它不能直接回答原始问题。)

    在Phoenix下使用AUI的示例

    此代码示例完全实现了我对MultiSplitterWindow所做的尝试,但是由AuiManager自动管理。

    import wx, wx.adv
    import wx.lib.mixins.inspection as wit
    from wx.lib.agw import aui
    
    
    class AppWInspection(wx.App, wit.InspectionMixin):
        def OnInit(self):
            self.Init()  # enable Inspection tool
            return True
    
    
    class AuiFrame(wx.Frame):
        def __init__(self, *args, **kwargs):
            super().__init__(size=(800, 800), *args, **kwargs)
            self.SetMinSize((600, 600))
    
            # Create an AUI Manager and tell it to manage this Frame
            self._manager = aui.AuiManager()
            self._manager.SetManagedWindow(self)
    
            inner_panel1 = wx.Panel(parent=self)
            inner_panel1.SetBackgroundColour('#999980')
            inner_panel1.SetMinSize((100, 100))
            inner_panel1_info = aui.AuiPaneInfo().Name('inner_panel1').Caption('Inner Panel 1').Left().\
                CloseButton(True).MaximizeButton(True).MinimizeButton(True).Show().Floatable(True)
    
            inner_panel2 = wx.Panel(parent=self)
            inner_panel2.SetBackgroundColour('#999990')
            inner_panel2_info = aui.AuiPaneInfo().Name('inner_panel2').Caption('Inner Panel 2').Left().Row(1).\
                Show().Floatable(False)
    
            inner_panel3 = wx.Panel(parent=self)
            inner_panel3.SetBackgroundColour('#9999A0')
            inner_panel3.SetMinSize((100, 100))
            inner_panel3_info = aui.AuiPaneInfo().Name('inner_panel3').Caption('Inner Panel 3').CenterPane()
    
            self._manager.AddPane(inner_panel1, inner_panel1_info)
            self._manager.AddPane(inner_panel2, inner_panel2_info)
            self._manager.AddPane(inner_panel3, inner_panel3_info)
            self._manager.Update()
    
        def __OnQuit(self, event):
            self.manager.UnInit()
            del self.manager
            self.Destroy()
    
    if __name__ == '__main__':
        app = AppWInspection(0)
        frame = AuiFrame(parent=None, title='AUI Manager Test')
        app.SetTopWindow(frame)
        frame.Show()
        app.MainLoop()
    

    关于python - 约束wxPython MultiSplitterWindow Pane ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17818940/

    10-14 17:38