约束wxPython多分裂窗口窗格

2024-06-16 14:52:19 发布

您现在位置:Python中文网/ 问答频道 /正文

编辑:我将问题保留原样,因为这仍然是一个好问题,答案可能对其他人有用。但是,我要注意的是,我发现了一个实际的解决方案,它使用了一种完全不同的方法来处理AuiManager;请参阅下面的answer。在

我正在进行MultiSplitterWindow设置(在花了大量时间之后 与SashLayoutWindow布局怪癖作斗争)。不幸的是,当我 创建一个MultiSplitterWindow,当拖动 窗扇周围:窗扇可以拖动到包含窗口的外部 布局的方向。至少可以说,这是我想避免的行为。在

下面是基本设置(您可以在wxPython中确认以下行为 演示,只需将leftwin替换为Panel1,等等,也可以参见下面的示例应用程序)。在我有RootPanel/BoxSizer的地方,有一个面板 (或Frame,或您喜欢的任何类型的容器元素) 其中添加了MultiSplitterWindow-同样,如演示中所示。在

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

当您拖动时,您可以得到这样的结果,其中~和{} 指示面板“存在”,但不显示:

^{pr2}$

如果此时拖动RootPanel,使其比 整个面板集,您将再次看到所有面板。同样,如果你拖动 宽度回到Panel1上,您可以访问Panel3的窗框 再次(当然,假设Panel2不是太宽)。而且,这个 正是检查工具报告的情况:RootPanel 保留其大小,但MultiSplitterWindow的大小超过 RootPanel/BoxSizer。在

使用Inspection工具进一步检查后发现,虚拟宽度值和客户端宽度值均为0,但实际大小值在超出范围时是负值(根据从窗口中拖出的相应像素数)。再说一次,这是疯狂的行为;我无法想象为什么有人会希望一扇窗户表现出这样的行为。在

现在,如果按住Shift使_OnMouse方法 MultiSplitterWindow调整邻居,这不会发生。因此,我的 方法是简单地覆盖该方法。它很管用,但我更喜欢 如果绝对必要,则重写方法。还有其他更好的方法吗 解决这个问题?这似乎不是我们所期望的或是不可取的 一般的行为,所以我想有一个标准的方法来解决它。在

我尝试过的其他方法:

  • 正在检查MultiWindowSplitter中的值之和是否超过 包含窗口的宽度,使用 EVT_SPLITTER_SASH_POS_CHANGEDEVT_SPLITTER_SASH_POS_CHANGING事件, 然后尝试通过以下方式解决问题:
    • 使用event.Veto()调用
    • 在拆分器上使用SetSashPosition()方法
  • 重写_OnMouse()方法以使用通常的行为 与按住Shift键相关。这行得通,但最后还是结束了 给我其他我不喜欢的结果。在
  • 通过SetMinimumPaneSize方法设置最小窗格大小
  • 通过SetMaxSize()设置MultiSplitterWindow的最大大小
  • RootPanel上同时使用SetMaxSize()和{}设置RootPanel/BoxSizer的最大大小。
    • 我甚至用容器上的wx.EVT_SIZE的事件处理程序完成了这项工作,以便RootPanel始终具有来自父框架元素的适当的最大大小
    • 我尝试过对MultiSplitterWindow使用相同的事件处理方法,但也没有效果。在

版本信息

我已经确认它出现在Windows 32位和OS X 64位中,并且 wxPython的最新快照构建,针对python2.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()

Tags: 方法self面板宽度parentinnerwxpanel
2条回答

我会尝试设置面板的最大大小,甚至使用SetSizeHints()。这两种方法都允许您对小部件的大小设置一些限制。在

根据您的需要,可以使用高级用户界面工具包的MultiSplitterWindow(或SashLayoutWindow组合等)来代替自定义管理的AuiManager工具(Phoenix之前版本的文档here;Phoenix文档here)。AuiManager为您自动化了许多这类事情。在我的例子中,我试图使用MultiSplitterWindow来控制所讨论UI的可折叠和可调整大小的面板,因此AuiManager非常适合:它已经内置了我需要的所有控件和约束。在

在这种情况下,只需创建一个AuiManager实例

(我在这里把这个作为一个的答案,希望其他可能采取与我同样天真的方法的人会发现它有用,但不要选择它作为答案,因为它确实直接回答了原始问题。)

凤凰城下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()

相关问题 更多 >