Почему?Hide()ing and.Показать () панели ing в wxPython приводят к изменению компоновки Sizer?
как указано в my предыдущий вопрос, Я пытаюсь сделать что-то немного похожее на волшебника в функции. Я остановился на одном кадре с добавлением sizer. Я создаю панели для каждого из экранов, которые я хотел бы видеть, добавляю их в размер кадра, а затем переключаюсь между панелями по .Hide()
ing одна панель, затем вызов пользовательского .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) я не понимаю, почему эта проблема все еще происходит.
каково правильное, не уродливое решение? Вместо того, чтобы добавлять все панели в sizer кадра сразу, следует включать панели переключения .Detach()
ing этой панели от sizer кадра, а затем .Add()
ing следующая панель к sizer рамки? Есть ли .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 BoringnProgram', (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 0nn'
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 BoringnProgram', (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 1nn'
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()
2 ответов
кажется, я понял. Вместо звонков в Show
и Hide
методы панелей, вам нужно вызвать Show
и Hide
методы корневого sizer:
self.Show()
становится
self.GetParent().GetSizer().Show(self)
...и так далее.
кроме того, после каждого звонка, вам понадобится
self.GetParent().GetSizer().Layout()
Да, я знаю, что на это уже ответили, но все равно:
вам нужно только вызвать Layout () на родительской панели, поэтому что-то вроде self.GetParent().Layout () должен сделать трюк. См. эту статью: http://www.blog.pythonlibrary.org/2010/06/16/wxpython-how-to-switch-between-panels/
Если хотите, чтобы кнопки всегда показывают, создать две панели в одной вертикальной сайзер. Одна сверху покажет ваши панели, а другая снизу будут показаны кнопки. Затем используйте PubSub или что-то, чтобы общаться между ними.