编辑:我将问题保持原样,因为它仍然是一个很好的问题,答案可能对其他人有用。但是,我会注意到,通过使用与AuiManager
完全不同的方法,我找到了 my 问题的实际解决方案;请参阅下面的answer。
我正在进行MultiSplitterWindow
设置(花了很多时间之后)
努力反对SashLayoutWindow
布局怪癖。不幸的是,当我
创建一个MultiSplitterWindow
,我在拖动时会看到一些意外的行为
sashes around:可以将窗扇拖到窗口中的包含窗口之外
布局方向。至少可以说,这是我想避免的行为。
这是基本设置(您可以在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()
答案 0 :(得分:3)
根据用户的需要,使用一种可能的选项而不是自定义管理的MultiSplitterWindow
(或SashLayoutWindow
组合等)是高级用户界面工具包的AuiManager
工具(凤凰城前版本here的文档;凤凰文档here)。 AuiManager
为您自动完成了很多这类事情。就我而言,我试图使用MultiSplitterWindow
作为控制相关UI的可折叠和可调整大小的面板的方法,因此AuiManager
非常适合:它已经具有所有控件和约束我需要内置。
在这种情况下,所有人需要做的是创建一个AuiManager
实例
(我将此作为 答案留在此处,希望其他可能采取相同天真方法的人会发现它很有用,但不会选择它作为答案,因为它确实如此不直接回答原始问题。)
此代码示例正是我尝试对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()
答案 1 :(得分:0)
我会尝试设置面板的MaxSize,甚至尝试使用SetSizeHints()。这两个都允许您对窗口小部件的大小设置一些约束。