2010-04-01 19 views
10

Jak wspomniano w mojej previous question, próbuję zrobić coś nieco czarodziejskiego w funkcji. Ustaliłem jedną ramkę z dodanym sizerem. Buduję panele dla każdego z ekranów, które chciałbym zobaczyć dla użytkowników, dodam je do ramki, następnie przełączam między panelami przez .Hide() na jednym panelu, a następnie wywołując niestandardowy .ShowYourself() na następnym panelu. Oczywiście, chciałbym, aby przyciski pozostały w tym samym miejscu, w którym użytkownik przechodzi przez cały proces.Dlaczego robi .Hide() ing i .Show() ing Panele w wxPython Wynik w Sizer zmiany układu?

Połączyłem ze sobą dwa panele w nieskończonej pętli za pomocą przycisków "Wstecz" i "Następny", aby zobaczyć, co się dzieje. Pierwszy panel wygląda świetnie; Kod tom10 działał na tym poziomie, ponieważ zlikwidował moją początkową, nadmierną próbę graniczącą z każdym krajem. A potem drugi panel zdaje się zmniejszać do absolutnego minimum. Gdy wracamy do pierwszego panelu, nastąpiło tu również kurczenie się. Dlaczego wygląda dobrze na pierwszym panelu, ale nie po powrocie? Dlaczego konieczne jest wywołanie .Fit(), jeśli nie chcę mieć 10-pikselowego szarego piksela o 10 pikseli? A jeśli jest to konieczne, dlaczego .Fit() daje niespójne wyniki?

Ta nieskończona pętla wydaje się scharakteryzować moje doświadczenia z tym: Naprawiam układ na panelu, tylko po to, aby przełączanie niszczyło układ dla innych paneli. Naprawię ten problem, używając sizer_h.Add(self.panel1, 0) zamiast sizer_h.Add(self.panel1, 1, wx.EXPAND), a teraz moje układy są wyłączone ponownie.

Do tej pory moje "rozwiązanie" polega na dodawaniu mastersizer.SetMinSize((475, 592)) do głównych rozmiarów paneli każdego panelu (skomentowano w poniższym kodzie). Jest to bardzo proste rozwiązanie, ponieważ 1) musiałem znaleźć numery, które działają metodą prób i błędów (-5 pikseli dla szerokości, -28 pikseli dla wysokości). 2) Nie rozumiem, dlaczego problem nadal występuje.

Jakie jest prawidłowe, nie brzydkie rozwiązanie? Zamiast dodawać wszystkie panele od razu do ramki, czy panele przełączające powinny obejmować panel z obramowaniem ramki, a następnie .Add() następnego panelu do ramki? Czy istnieje metoda ukrywania gdzieś, o czym pominąłem zarówno w dokumentach wxWidgets, jak i wxPython w Internecie?

Najwyraźniej brakuje mi czegoś w moim mentalnym modelu układu. Minimalistyczny kod wklejony poniżej.

enter image description here

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() 
+0

Zajrzę do tego. –

+0

działa poprawnie na GTK –

+0

Zastanawiam się, czy jest jakaś funkcjonalna różnica między GTK i Windows 7 (moja platforma docelowa), która nie została uwzględniona w aktualnej wersji wxPython dla Windows. To bardzo przydatne, Steven. Oznacza to, że być może to, co o tym myślę, nie jest kompletne. – MetaHyperBolic

Odpowiedz

16

myślę zdobione. Zamiast rozmów do Show i Hide metod paneli, trzeba wezwać Show i Hide metod klasyfikatorze root:

self.Show() 

staje

self.GetParent().GetSizer().Show(self) 

... i tak dalej.

Ponadto, po każdej rozmowie, trzeba

self.GetParent().GetSizer().Layout() 
+0

Zrobiłem to. Przesunąłem instrukcję self.SetSizer (sizer_h) w klasie My_Frame przed utworzeniem paneli, lub self.GetParent(). GetSizer() zwraca None. Po tym zdecydowanie znajduje sizer. Ale, self.GetParent(). GetSizer(). Show (self) zwraca "False" przy pierwszym wywołaniu i widzę oba panele stłoczone razem na ramie. Kiedy zacznę klikać przyciski Wstecz i Dalej, wracamy do tego samego zachowania, wciągając rozmiar panelu do czegoś znacznie mniejszego niż ramka. W tym momencie self.GetParent(). GetSizer(). Show (self) zwraca True w metodzie ShowYourself. – MetaHyperBolic

+0

Ah, i ulepszyłem mój program po dodaniu Układu! O, aby dać temu szansę. – MetaHyperBolic

+0

To działało! To może być wywołane tylko na końcu funkcji ShowYourself(). Tak więc, moim konceptualnym problemem było to, że ignorowałem hierarchię rozmiarów, a twoim rozwiązaniem jest to, że one również muszą zostać wywołane. Czy masz listę życzeń Amazon, gdzie mogę kupić książkę? Poważnie, ten szczególny problem mnie zepsuł. – MetaHyperBolic

2

Tak, wiem, że to jest już odpowiedź, ale tutaj przejść w każdym razie:

Trzeba tylko zadzwonić Layout() na panelu rodzic, więc coś jak self.GetParent(). Layout() powinien załatwić sprawę.Zobacz ten artykuł: http://www.blog.pythonlibrary.org/2010/06/16/wxpython-how-to-switch-between-panels/

Jeśli chcesz, aby przyciski zawsze się wyświetlały, utwórz dwa panele w jednym pionowym segregatorze. Ten na górze pokaże panele, a ten na dole pokaże przyciski. Następnie użyj PubSub lub czegoś, aby komunikować się między nimi.