Met*_*lic 12 wxwidgets wxpython sizer
正如我在上一个问题中所提到的,我试图在功能上做一些类似向导的东西.我已经选择了添加了sizer的单帧.我为每个希望用户看到的屏幕构建面板,将它们添加到框架的sizer中,然后.Hide()通过一个面板在面板之间切换,然后.ShowYourself()在下一个面板上调用自定义面板.显然,我希望按钮与用户在整个过程中保持同一位置.
我通过"后退"和"下一步"按钮将两个面板链接在一个无限循环中,这样你就可以看到发生了什么.第一个小组看起来很棒; tom10的代码在那个级别上工作,因为它避开了我最初的,过度花哨的尝试,边界各处飞行.然后第二个小组似乎缩小到最低限度.当我们返回第一个面板时,这里也发生了收缩.为什么它在第一个面板上看起来很好,但是在我返回后没有?.Fit()如果我不想要10像素乘10像素的灰色,为什么需要调用?如果有必要,为什么会.Fit()给出不一致的结果?
这个无限循环似乎是我对此经历的一个特征:我在面板上修复了布局,但却发现切换会破坏其他面板的布局.我解决了这个问题,通过使用sizer_h.Add(self.panel1, 0)而不是sizer_h.Add(self.panel1, 1, wx.EXPAND),现在我的布局再次关闭.
到目前为止,我的"解决方案"是为mastersizer.SetMinSize((475, 592))每个面板的主sizer 添加一个(在下面的代码中注释掉).这是一个肮脏的解决方案,因为1)我必须找到通过试验和错误工作的数字(宽度为-5像素,高度为-28像素).2)我不明白为什么潜在的问题仍然存在.
什么是正确的,非丑陋的解决方案?如果切换面板不是将所有面板同时添加到框架的大小调整器中,而是应该.Detach()从框架的大小调整器中将面板包含在内,然后.Add()将下一个面板连接到框架的大小调整器上?是否有一种.JustMakeThisFillThePanel()隐藏在wxWidgets和wxPython文档在线的错过的方法?
我显然在布局的心理模型中遗漏了一些东西.粘贴在下面的极简主义代码.

import wx
import sys
class My_App(wx.App):
def OnInit(self):
self.frame = My_Frame(None)
self.frame.Show()
self.SetTopWindow(self.frame)
return True
def OnExit(self):
print 'Dying ...'
class My_Frame(wx.Frame):
def __init__(self, image, parent=None,id=-1, title='Generic Title', pos=wx.DefaultPosition, style=wx.CAPTION | wx.STAY_ON_TOP):
size = (480, 620)
wx.Frame.__init__(self, parent, id, 'Program Title', pos, size, style)
sizer_h = wx.BoxSizer(wx.HORIZONTAL)
self.panel0 = User_Interaction0(self)
sizer_h.Add(self.panel0, 1, wx.EXPAND)
self.panel1 = User_Interaction1(self)
sizer_h.Add(self.panel1, 1, wx.EXPAND)
self.SetSizer(sizer_h)
self.panel0.ShowYourself()
def ShutDown(self):
self.Destroy()
class User_Interaction0(wx.Panel):
def __init__(self, parent, id=-1):
wx.Panel.__init__(self, parent, id)
# master sizer for the whole panel
mastersizer = wx.BoxSizer(wx.VERTICAL)
#mastersizer.SetMinSize((475, 592))
mastersizer.AddSpacer(15)
# build the top row
txtHeader = wx.StaticText(self, -1, 'Welcome to This Boring\nProgram', (0, 0))
font = wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.BOLD)
txtHeader.SetFont(font)
txtOutOf = wx.StaticText(self, -1, '1 out of 7', (0, 0))
rowtopsizer = wx.BoxSizer(wx.HORIZONTAL)
rowtopsizer.Add(txtHeader, 3, wx.ALIGN_LEFT)
rowtopsizer.Add((0,0), 1)
rowtopsizer.Add(txtOutOf, 0, wx.ALIGN_RIGHT)
mastersizer.Add(rowtopsizer, 0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=15)
# build the middle row
text = 'PANEL 0\n\n'
text = text + 'This could be a giant blob of explanatory text.\n'
txtBasic = wx.StaticText(self, -1, text)
font = wx.Font(11, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
txtBasic.SetFont(font)
mastersizer.Add(txtBasic, 1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=15)
# build the bottom row
btnBack = wx.Button(self, -1, 'Back')
self.Bind(wx.EVT_BUTTON, self.OnBack, id=btnBack.GetId())
btnNext = wx.Button(self, -1, 'Next')
self.Bind(wx.EVT_BUTTON, self.OnNext, id=btnNext.GetId())
btnCancelExit = wx.Button(self, -1, 'Cancel and Exit')
self.Bind(wx.EVT_BUTTON, self.OnCancelAndExit, id=btnCancelExit.GetId())
rowbottomsizer = wx.BoxSizer(wx.HORIZONTAL)
rowbottomsizer.Add(btnBack, 0, wx.ALIGN_LEFT)
rowbottomsizer.AddSpacer(5)
rowbottomsizer.Add(btnNext, 0)
rowbottomsizer.AddSpacer(5)
rowbottomsizer.AddStretchSpacer(1)
rowbottomsizer.Add(btnCancelExit, 0, wx.ALIGN_RIGHT)
mastersizer.Add(rowbottomsizer, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=15)
# finish master sizer
mastersizer.AddSpacer(15)
self.SetSizer(mastersizer)
self.Raise()
self.SetPosition((0,0))
self.Fit()
self.Hide()
def ShowYourself(self):
self.Raise()
self.SetPosition((0,0))
self.Fit()
self.Show()
def OnBack(self, event):
self.Hide()
self.GetParent().panel1.ShowYourself()
def OnNext(self, event):
self.Hide()
self.GetParent().panel1.ShowYourself()
def OnCancelAndExit(self, event):
self.GetParent().ShutDown()
class User_Interaction1(wx.Panel):
def __init__(self, parent, id=-1):
wx.Panel.__init__(self, parent, id)
# master sizer for the whole panel
mastersizer = wx.BoxSizer(wx.VERTICAL)
#mastersizer.SetMinSize((475, 592))
mastersizer.AddSpacer(15)
# build the top row
txtHeader = wx.StaticText(self, -1, 'Read about This Boring\nProgram', (0, 0))
font = wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.BOLD)
txtHeader.SetFont(font)
txtOutOf = wx.StaticText(self, -1, '2 out of 7', (0, 0))
rowtopsizer = wx.BoxSizer(wx.HORIZONTAL)
rowtopsizer.Add(txtHeader, 3, wx.ALIGN_LEFT)
rowtopsizer.Add((0,0), 1)
rowtopsizer.Add(txtOutOf, 0, wx.ALIGN_RIGHT)
mastersizer.Add(rowtopsizer, 0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=15)
# build the middle row
text = 'PANEL 1\n\n'
text = text + 'This could be a giant blob of boring text.\n'
txtBasic = wx.StaticText(self, -1, text)
font = wx.Font(11, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
txtBasic.SetFont(font)
mastersizer.Add(txtBasic, 1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=15)
# build the bottom row
btnBack = wx.Button(self, -1, 'Back')
self.Bind(wx.EVT_BUTTON, self.OnBack, id=btnBack.GetId())
btnNext = wx.Button(self, -1, 'Next')
self.Bind(wx.EVT_BUTTON, self.OnNext, id=btnNext.GetId())
btnCancelExit = wx.Button(self, -1, 'Cancel and Exit')
self.Bind(wx.EVT_BUTTON, self.OnCancelAndExit, id=btnCancelExit.GetId())
rowbottomsizer = wx.BoxSizer(wx.HORIZONTAL)
rowbottomsizer.Add(btnBack, 0, wx.ALIGN_LEFT)
rowbottomsizer.AddSpacer(5)
rowbottomsizer.Add(btnNext, 0)
rowbottomsizer.AddSpacer(5)
rowbottomsizer.AddStretchSpacer(1)
rowbottomsizer.Add(btnCancelExit, 0, wx.ALIGN_RIGHT)
mastersizer.Add(rowbottomsizer, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=15)
# finish master sizer
mastersizer.AddSpacer(15)
self.SetSizer(mastersizer)
self.Raise()
self.SetPosition((0,0))
self.Fit()
self.Hide()
def ShowYourself(self):
self.Raise()
self.SetPosition((0,0))
self.Fit()
self.Show()
def OnBack(self, event):
self.Hide()
self.GetParent().panel0.ShowYourself()
def OnNext(self, event):
self.Hide()
self.GetParent().panel0.ShowYourself()
def OnCancelAndExit(self, event):
self.GetParent().ShutDown()
def main():
app = My_App(redirect = False)
app.MainLoop()
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
Nat*_*man 17
我想我明白了.相反,呼叫到的Show与Hide面板的方法,你需要调用Show和Hide根分级机的方法:
self.Show()
Run Code Online (Sandbox Code Playgroud)
变
self.GetParent().GetSizer().Show(self)
Run Code Online (Sandbox Code Playgroud)
...等等.
此外,每次通话后,您都需要
self.GetParent().GetSizer().Layout()
Run Code Online (Sandbox Code Playgroud)
是的,我知道这个问题已经得到解答,但无论如何,你还是可以:
您应该只需要在面板的父级上调用 Layout() ,因此 self.GetParent().Layout() 之类的东西应该可以解决问题。请参阅这篇文章:http://www.blog.pythonlibrary.org/2010/06/16/wxpython-how-to-switch- Between-panels/
如果您希望按钮始终显示,请在一个垂直尺寸调整器中创建两个面板。顶部的一个将显示您的面板,底部的一个将显示按钮。然后使用PubSub什么的在他们之间进行通信。