2010-04-01 12 views
10

Come indicato nel mio previous question, sto cercando di creare qualcosa di simile a un wizard in funzione. Ho optato per un singolo frame con un sizer aggiunto ad esso. Costruisco pannelli per ciascuna delle schermate che vorrei che gli utenti vedessero, aggiungendole al sizer del frame, quindi passando da un pannello all'altro tramite .Hide() in un pannello, quindi chiamando uno personalizzato .ShowYourself() nel pannello successivo. Ovviamente, vorrei che i pulsanti rimanessero nello stesso posto in cui l'utente avanza nel processo.Perché fa .Hide() ing e .Show() ing Pannelli in wxPython Risultato in Sizer Cambiare il layout?

ho collegati tra loro due pannelli in un ciclo infinito dai loro pulsanti "Indietro" e "Avanti" in modo da poter vedere cosa sta succedendo. Il primo pannello sembra fantastico; Il codice di tom10 ha funzionato a quel livello, in quanto ha evitato il mio tentativo iniziale e stravagante con i confini che volavano in ogni direzione. E poi il secondo pannello sembra essersi ridotto al minimo. Quando torniamo al primo pannello, anche qui si è verificato il restringimento. Perché sembra perfetto nel primo pannello, ma non dopo il mio ritorno? Perché è necessario chiamare .Fit() se non voglio un batuffolo di grigio da 10 pixel per 10 pixel? E se è necessario, perché .Fit() dà risultati incoerenti?

Questo ciclo infinito sembra caratterizzare la mia esperienza con questo: ho risolto il layout su un pannello, solo per scoprire che il passaggio rovina il layout per altri pannelli. Ho risolto il problema utilizzando sizer_h.Add(self.panel1, 0) anziché sizer_h.Add(self.panel1, 1, wx.EXPAND) e ora i miei layout sono nuovamente disattivati.

Finora, la mia "soluzione" è quella di aggiungere uno mastersizer.SetMinSize((475, 592)) a ciascun master sizer di ogni pannello (commentato nel codice seguente). Questa è una soluzione cruda perché 1) ho dovuto trovare i numeri che funzionano per tentativi ed errori (-5 pixel per la larghezza, -28 pixel per l'altezza). 2) Non capisco perché il problema sottostante si verifica ancora.

Qual è la soluzione corretta, non brutta? Invece di aggiungere tutti i pannelli al sizer del frame in una sola volta, i pannelli di commutazione dovrebbero includere il pannello .Detach() dal sizer del frame e quindi .Add() il pannello successivo al sizer del frame? Esiste un metodo nascosto da qualche parte che ho perso sia in wxWidgets che nei documenti wxPython online?

Mi manca ovviamente qualcosa nel mio modello mentale di layout. Codice minimalista incollato di seguito.

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

Vedrò questo. –

+0

funziona correttamente su GTK –

+0

Mi chiedo se ci sia qualche differenza funzionale tra GTK e Windows 7 (la mia piattaforma di destinazione) che non è stata considerata nella versione corrente di wxPython per Windows. È utile sapere, Steven. Significa che forse come sto pensando a questo non è completamente fuori. – MetaHyperBolic

risposta

16

penso ho capito. Invece di chiamate ai Show e Hide metodi dei pannelli, è necessario chiamare le Show e Hide metodi del sizer radice:

self.Show() 

diventa

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

... e così via.

Inoltre, dopo ogni chiamata, è necessario

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

L'ho fatto. Ho spostato l'istruzione self.SetSizer (sizer_h) nella classe My_Frame prima della creazione dei pannelli, oppure self.GetParent(). GetSizer() restituisce None. Dopo di ciò, trova sicuramente il tastatore. Ma self.GetParent(). GetSizer(). Show (self) restituisce "False" alla prima chiamata e vedo entrambi i pannelli ammassati sul telaio. Quando comincio a fare clic sui pulsanti Indietro e Avanti, torniamo allo stesso modo di ridurre le dimensioni del pannello a qualcosa di molto più piccolo del fotogramma. A questo punto, self.GetParent(). GetSizer(). Show (self) restituisce True nel metodo ShowYourself. – MetaHyperBolic

+0

Ah, e ho modificato il mio programma quando hai aggiunto Layout! A proposito di dare un colpo. – MetaHyperBolic

+0

Ha funzionato! Questo deve essere chiamato solo alla fine della funzione ShowYourself(). Quindi, il mio problema concettuale era che ignoravo la gerarchia dei calibratori e la tua soluzione è che anche questi devono essere chiamati. Hai una lista dei desideri su Amazon dove potrei comprarti un libro? Seriamente, questo particolare problema mi aveva abbastanza giù. – MetaHyperBolic

2

Sì, so che questo è già una risposta, ma qui si va in ogni caso:

Si dovrebbe avere solo per chiamare Layout() sul pannello di genitore, quindi qualcosa come self.GetParent(). Layout() dovrebbe fare il trucco.Vedere questo articolo: http://www.blog.pythonlibrary.org/2010/06/16/wxpython-how-to-switch-between-panels/

Se si desidera che i pulsanti siano sempre visualizzati, creare due pannelli in un misuratore verticale. Quello in alto mostrerà i tuoi pannelli e quello in basso mostrerà i pulsanti. Quindi utilizzare PubSub o qualcosa per comunicare tra loro.

Problemi correlati