如何以受控的纵横比居中面板

How to center panel with controlled aspect ratio

在 wxPython 中,我无法将我创建的具有固定纵横比的子面板居中。

为了控制纵横比,子面板需要捕获Size事件,然后做一个显式的SetSize。所以,我已经做到了,而且效果很好。不幸的是,当我将此子面板嵌入另一个面板(使用 sizer)时,wx.ALIGN_CENTER_HORIZONTAL 标志不起作用。

显然,sizer 告诉我的子面板它有适合的整个宽度。当我的 window 不使用整个宽度时,sizer 不会调整。这是显示问题的代码的简化版本:

import wx

ROWS = 6
COLS = 25

class TestPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        label = wx.StaticText(self, -1, 'Label')
        grid  = TestGrid(self)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(label, 0, flag=wx.ALIGN_CENTER_HORIZONTAL)
        sizer.Add(grid,  1, flag=wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND)
        self.SetSizer(sizer)

class TestGrid(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)
        self.SetBackgroundColour(wx.BLUE)
        self.Bind(wx.EVT_SIZE,  self.OnSize)

    def OnSize(self, event):
        w, h = self.GetSizeTuple()
        delta = min(w // COLS, h // ROWS)
        self.SetSize((COLS*delta, ROWS*delta))
        self.Refresh()

if __name__ == '__main__':
    app = wx.App()
    frame = wx.Frame(None, -1, "Test", size=(600, 200))
    panel = TestPanel(frame)
    frame.Show(True)
    app.MainLoop()

这是屏幕截图:

您不能,或者至少不应该,从其自己的 wxEVT_SIZE 处理程序调整 window 的大小。我不确定你到底想达到什么目的,但如果目标是将所有内容封装在 TestGrid class 中,那么你应该让它具有任何大小并创建一个嵌套的 window 在其中,您将在 OnSize.

中调整到适当的大小

正如 VZ 在他的回答中解释的那样,您的 wxEVT_SIZE 处理程序不是一个好主意。去掉它。使用 sizer 时,您必须在 sizer 基础结构中工作才能实现您想要的。

您希望 TestGrid 在其父级中尽可能多地填充 space,同时保持一定的纵横比;这正是 wx.SHAPED 的用途(结合您已经拥有的大于 0 的 proportion)。因此,您应该像这样将 grid 添加到 sizer:

sizer.Add(grid,  1, flag=wx.ALIGN_CENTER_HORIZONTAL|wx.SHAPED)

您唯一需要做的另一件事就是告诉 sizer 您想要的纵横比是多少。最简单的方法是为 TestGrid 设置一个初始大小(在它被添加到 sizer 之前);例如,设置其 wxPanel 基数的大小:

wx.Panel.__init__(self, parent, -1, size=(COLS*7, ROWS*7))

仅此而已。

(我只是在猜测 Python 语法,所以忽略任何明显的错误:-))