编辑:我将问题保留为开放状态,因为它仍然是一个好问题,答案可能对其他人有用。但是,我会注意到,通过对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_CHANGED
和EVT_SPLITTER_SASH_POS_CHANGING
事件,然后尝试通过以下方法解决此问题:
event.Veto()
调用SetSashPosition()
方法_OnMouse()
方法以使用通常的行为与按住
Shift
键相关联。这行得通,但是最终给我其他我不喜欢的结果。
SetMinimumPaneSize
方法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/