【问题标题】:Appropriate wx.Sizer(s) for the job?适合这项工作的 wx.Sizer(s) 吗?
【发布时间】:2010-03-30 16:46:18
【问题描述】:

我有一个空间,我希望某些元素(这里用 A、B、D 和 G 表示)在设计的每个“角落”中都有。角应该排成一列,就好像四个元素中的每一个都相互排斥一样;一个矩形。这将包含在不可调整大小的面板中。我将有几个类似的面板,并希望尽可能保持元素的位置相同。 (我需要比 wx.Wizard 更复杂一点的东西,但总体思路相同。)

AAAAAAAAAA      BB


CCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCC


DDD EEE FFF    GGG

A 代表大字体的文本。

B 表示小字体的数字进度表(例如“1 of 7”)。

C 代表一大块文本。

D、E、F 和 G 是按钮。

G 按钮在功能上与其他按钮分开。

我尝试嵌套wx.BoxSizers(一个垂直框内的水平框)没有运气。我对wx.BoxSizer 的第一个问题是我最后一行的.SetMinSize 没有被兑现。第二个问题是我不知道如何让 G 按钮“占用空间”而不会变得可笑地变大,或者如何将它卡在右边缘和底部边缘。

我曾尝试使用wx.GridBagSizer,但遇到了完全不同的问题。

在浏览了各种在线教程和 wxPython in Action 之后,我有点沮丧。相关论坛似乎每两周就会出现一次活动。 “玩弄它”让我无处可去;我感觉好像我正在努力抚平铺垫不当的地毯上的隆起。

【问题讨论】:

    标签: wxpython wxwidgets sizer


    【解决方案1】:

    使用 BoxSizers 和一些标志,如 wx.EXPAND 和 wx.ALIGN_RIGHT 等,你可以得到你想要的。这是一个例子

    import wx
    import string
    AF = string.ascii_uppercase[:7]
    
    class MyFrame(wx.Frame):
    
        def __init__(self):
            wx.Frame.__init__(self, None, size=(300,300))
    
            a, b, c, d, e, f, g = [wx.Button(self, -1, 4*c) for c in AF]
            a.SetMaxSize((200,100))   # 'a' won't get bigger than 200 wide
    
            # build the top row (with sizers I usually work from inside to out)
            hs0 = wx.BoxSizer(wx.HORIZONTAL)
            hs0.Add(a, 1, wx.ALIGN_LEFT)  # 1 here means expand with weight 1
            hs0.Add((0,0), 1)  # also expand the spacing
            hs0.Add(b, 0, wx.ALIGN_RIGHT)  # 0 means don't expand this
    
            # build the bottom row
            hs1 = wx.BoxSizer(wx.HORIZONTAL)
            hs1.Add(d, 0, wx.ALIGN_LEFT)
            hs1.Add((10,10), 0)
            hs1.Add(e, 0)
            hs1.Add((10,10), 0)
            hs1.Add(f, 0)
            hs1.Add((10, 10), 1)
            hs1.Add(g, 0, wx.ALIGN_RIGHT)
    
            # stack the rows vertically
            vs = wx.BoxSizer(wx.VERTICAL)
            vs.Add(hs0, flag=wx.EXPAND)   # expand in the orthogonal direction to sizer (here horizontal)
            vs.Add(c, 1, flag=wx.EXPAND)  
            vs.Add(hs1, flag=wx.EXPAND)
            self.SetSizer(vs)
    
    app = wx.PySimpleApp()
    frame = MyFrame()
    frame.Show(1)
    app.MainLoop()
    

    【讨论】:

    • 我已经用代码和图片在下面给出了答案。或者至少是一个小图片的链接。似乎无法掌握链接图像的窍门。
    • 是的,当然,我会马上研究它。甚至没有感谢或赞成或任何解释为什么我的答案对您不起作用(尽管我看到您粘贴了我的代码而没有在您的答案中注明出处),或者您甚至没有花时间弄清楚如何上传一张照片,我迫不及待地想用我下午剩下的时间来帮你解决你的问题......
    • 化妆品?看起来很棒。但是您的代码又带回了我在面板之间切换时遇到的同样问题。第一次看起来不错,但一旦我在面板之间切换,布局决定它希望与框架不同。当我还不知道什么真正解决了问题时,现在投票还为时过早。
    【解决方案2】:

    首先,您需要一个垂直大小调整器将窗口分成 3 行:AB、C 和 DEFG:

    frame_sizer = wx.BoxSizer(wx.VERTICAL)
    

    接下来,您需要为第一行设置一个水平尺寸器:

    first_sizer = wx.BoxSizer(wx.HORIZONTAL)
    # add the items A and B to first_sizer
    # now we add first_sizer to frame_sizer
    frame_sizer.Add(first_sizer)
    

    然后,对于第二行,我们只需将 C 控件添加到 sizer:

    frame_sizer.Add(C)
    

    ...确保以下几点:

    • 使用指定大小创建控件(通过其构造函数)
    • 控件具有最小大小 (C.SetMinSize())

    现在,对于最后一行,最好的办法可能是使用另一个水平尺寸器。

    wx.BoxSizer(wx.HORIZONTAL)
    # add DEF
    # now add some space between them
    wx.AddSizer(10)
    # now add G
    

    希望这对你有用。如果没有,你最好的选择是在 Code::Blocks 中使用像 wxSmith 这样的 GUI 设计器(它是为 C++ 设计的,但至少可以用来了解事物的外观 - wxPython 应该有一个 1-to -1 对应 wxWidgets)

    【讨论】:

    • 这是我之前的策略,失败了。 sizer 的每一行都希望具有与其他行不同的宽度。我看不出有什么办法可以说:“你,那里!你应该是 x 像素宽,不多也不少。你在这里!你得到同样的结果。”它看起来不像 Code::Blocks 在 Windows 7 上运行。相比之下,我在 CSS 早期尝试设计跨浏览器网站的经验似乎微不足道。
    • 哦,是的。我忘了——当你添加sizer时,你必须用wx.EXPAND标志调用Add。这应该可以解决问题。
    • @MetaHyperBolic: Code::Blocks 应该在 Windows 7 上运行良好。
    • codeblocks.org/downloads/5 甚至没有将 Windows 7 列为选项。该页面表明 Code::Blocks 附带的编译器无法在 Vista 上运行。而且我显然必须编译 wxWidgets 才能使用 wxSmith,所以我必须使用 Windows XP。
    • @MetaHyperBolic:我在 Vista 上使用它没有任何问题(我已经广泛使用了一年多)。它应该可以在 Windows 7 上正常工作。您无需编译 wxWidgets 即可使用 wxSmith。它预先配置了 Code::Blocks。我的第一条评论中的建议有用吗?
    【解决方案3】:

    我只有一帧。我在框架中内置了几个面板。它们都是隐藏的,只有一个。 “下一步”按钮在该面板上执行 .Hide(),然后调用名为 .ShowYourself 的函数。我想要一些类似巫师的东西,你可以在 previous question 中看到它

    我正在尝试在面板上放置一个尺寸测定器。正如您从picture http://tinypic.com/r/14nh651/5 中看到的那样,我无法让sizer 占据整个面板。图片没有在预览中显示,所以这里是http://tinypic.com/r/14nh651/5

    import wx
    import sys
    
    class MyApp(
        wx.App      # This makes a subclass of the wx.App class
    
    ):
    
    def OnInit(self):
        # image = wx.Image('wxPython.jpg', wx.BITMAP_TYPE_JPEG)
        self.frame = MyFrame(None)
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True
    
    def OnExit(self):
        print 'Dying ...'
    
    ####################################################################################################
    
    class MyFrame(
        wx.Frame    # This makes a subclass of the wx.Frame class
        ):
        """Frame class that displays an image."""
    
        def __init__(self, 
            image, 
            parent=None,                # "None" as a parameter means this is a top-level window
            id=-1,                  # "-1" means automatically generate a new ID
            title='Generic Title',          # What words appear in the title bar?
            pos=wx.DefaultPosition,         # Where is the upper left-hand corner?
            style=wx.CAPTION | wx.STAY_ON_TOP   # Style with only a caption
            ):      
    
        """Create a wx.Frame instance and display image."""
    
        size = (500, 500)
        wx.Frame.__init__(self, parent, id, 'Program Title', pos, size, style)
    
        sizer_h = wx.BoxSizer(wx.HORIZONTAL)
    
        self.panelX = TestLayout3(self)     
        sizer_h.Add(self.panelX)
    
        self.SetSizer(sizer_h)
    
        self.panelX.ShowYourself()
    
    def ShutDown(self):
    
            self.Destroy()
    
    ####################################################################################################
    
    class TestLayout3(wx.Panel):
    
    # 0 - Splash screen with "Next" and "Cancel and Exit" buttons
    
    def __init__(self, parent, id=-1):
        size = (600, 600)
        wx.Panel.__init__(self, parent, id, size)
    
        a, b, c, d, e, f, g = [wx.Button(self, -1, 4*c) for c in 'ABCDEFG']
        a.SetMaxSize((200,100))   # 'a' won't get bigger than 200 wide
    
        # build the top row (with sizers I usually work from inside to out)
        hs0 = wx.BoxSizer(wx.HORIZONTAL)
        hs0.Add(a, 1, wx.ALIGN_LEFT)  # 1 here means expand with weight 1
        hs0.Add((0,0), 1)  # also expand the spacing
        hs0.Add(b, 0, wx.ALIGN_RIGHT)  # 0 means don't expand this
    
        # build the bottom row
        hs2 = wx.BoxSizer(wx.HORIZONTAL)
        hs2.Add(d, 0, wx.ALIGN_LEFT)
        hs2.Add((10,10), 0)
        hs2.Add(e, 0)
        hs2.Add((10,10), 0)
        hs2.Add(f, 0)
        hs2.Add((10, 10), 1)
        hs2.Add(g, 0, wx.ALIGN_RIGHT)
    
        # stack the rows vertically
        vs = wx.BoxSizer(wx.VERTICAL)
        vs.Add(hs0, flag=wx.EXPAND)   # expand in the orthogonal direction to sizer (here horizontal)
        vs.Add(c, 1, flag=wx.EXPAND)  
        vs.Add(hs2, flag=wx.EXPAND)
        self.SetSizer(vs)
    
        self.Raise()
        self.SetPosition((0,0))
        self.Fit()  
        self.Hide()
    
    
    # reveal this panel
    def ShowYourself(self):
        self.Raise()
        self.SetPosition((0,0))
        self.Fit()
        self.Show()
    
    
    # what do we do when the "Back" button is clicked?
    def OnBack(self, event):
        self.Hide()
        self.GetParent().panel1.ShowYourself()
    
    # what do we do when the "Next" button is clicked?
    def OnNext(self, event):
        self.Hide()
        self.GetParent().panel1.ShowYourself()
    
        ![# what do we do when the "Cancel and Exit" button is clicked?
        def OnCancelAndExit(self, event):
            self.GetParent().ShutDown()
    
    ####################################################################################################
    
    def main():
        app = MyApp(redirect = False)
        app.MainLoop()
    
    ####################################################################################################
    
    if __name__ == '__main__':
        main()][3]
    

    【讨论】:

    • @MetaHyperBolic:嗯,一方面,当您将面板添加到 sizer 时,您没有使用 wx.EXPAND 标志。此外,您可能想在SetSizer 调用之后尝试调用sizer_h.SetSizeHints(self)。试试看它是否有效。至于在您的帖子中链接图片,您是否将其添加为:<img src="http...">
    • 对。我之前尝试使用 wx.EXPAND 将 Panel 添加到 sizer(您会看到一个非常精简的脚本,之前的问题已被注释掉)——我最终遇到了各种奇怪的问题,因为我有七个面板添加到顶级框架上的 sizer。
    • 我只是单击了工具栏上的图像图标并继续使用它,而不是尝试添加我更熟悉的 HTML。
    • 给我一些时间,我会试试你的脚本。或许我能找到问题所在——这个问题真的让我很困惑。
    • 我能够重现该问题。现在我将尝试找到解决方案。
    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    • 2012-06-09
    • 1970-01-01
    相关资源
    最近更新 更多