2010-04-01 11 views
10

Como se hace referencia en mi previous question, estoy tratando de hacer algo ligeramente parecido a un asistente en función. Me he decidido por un solo cuadro con un sizer agregado. Construyo paneles para cada una de las pantallas que me gustaría que los usuarios vean, los agrego al tamaño del marco, luego cambio entre los paneles por .Hide() en un panel, y luego llamo a un .ShowYourself() personalizado en el siguiente panel. Obviamente, me gustaría que los botones permanezcan en el mismo lugar a medida que el usuario avanza en el proceso.¿Por qué los paneles .Hide() ing y .Show() ing en wxPython dan como resultado que el Sizer cambie el diseño?

He vinculado dos paneles en un bucle infinito por sus botones "Atrás" y "Siguiente" para que pueda ver lo que está pasando. El primer panel se ve genial; El código de tom10 funcionó en ese nivel, ya que evitó mi intento inicial, demasiado sofisticado, con fronteras volando en todas direcciones. Y luego, el segundo panel parece haberse reducido al mínimo. Cuando volvemos al primer panel, la contracción también ha ocurrido aquí. ¿Por qué se ve bien en el primer panel, pero no después de que regrese allí? ¿Por qué es necesario llamar a .Fit() si no quiero un fajo de 10 píxeles por 10 píxeles de gris? Y si es necesario, ¿por qué el .Fit() arroja resultados inconsistentes?

Este ciclo infinito parece caracterizar mi experiencia con esto: corrijo el diseño en un panel, solo para encontrar que el cambio arruina el diseño de otros paneles. Soluciono ese problema, usando sizer_h.Add(self.panel1, 0) en lugar de sizer_h.Add(self.panel1, 1, wx.EXPAND), y ahora mis diseños están desactivados nuevamente.

Hasta ahora, mi "solución" es agregar un mastersizer.SetMinSize((475, 592)) al medidor maestro de cada panel (comentado en el código a continuación). Esta es una solución cruddy porque 1) He tenido que encontrar los números que funcionan por ensayo y error (-5 píxeles para el ancho, -28 píxeles para la altura). 2) No entiendo por qué el problema subyacente aún sucede.

¿Cuál es la solución correcta y no fea? En lugar de agregar todos los paneles al calibrador del marco de una sola vez, ¿deberían los paneles de conmutación incluir .Detach() en ese panel desde el clasificador del marco y luego .Add() en el siguiente panel al marco del marco? ¿Existe un método .JustMakeThisFillThePanel() escondido en algún lugar que he omitido tanto en wxWidgets como en los documentos wxPython en línea?

Obviamente me falta algo en mi modelo mental de diseño. Código minimalista pegado a continuación.

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

Voy a ver esto. –

+0

funciona bien en GTK –

+0

Me pregunto si existe alguna diferencia funcional entre GTK y Windows 7 (mi plataforma de destino) que no se ha tenido en cuenta en la versión actual de wxPython para Windows. Es útil saberlo, Steven. Significa que tal vez lo que estoy pensando acerca de esto no está completamente apagado. – MetaHyperBolic

Respuesta

16

creo que lo he descubierto. En lugar de las llamadas a los métodos Show y Hide de los paneles, es necesario llamar a los Show y Hide métodos de la medidor de la raíz:

self.Show() 

convierte

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

... y así sucesivamente.

Además, después de cada llamada, es necesario

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

Lo hice. Moví la declaración self.SetSizer (sizer_h) en la clase My_Frame antes de que se creen los paneles, o bien self.GetParent(). GetSizer() es devuelve None. Después de eso, definitivamente encuentra el calibrador. Pero, self.GetParent(). GetSizer(). Show (self) devuelve "False" en la primera llamada y veo ambos paneles agrupados en el marco. Una vez que empiezo a hacer clic en los botones Atrás y Siguiente, volvemos al mismo comportamiento de bajar el tamaño del panel a algo mucho más pequeño que el marco. En ese momento, self.GetParent(). GetSizer(). Show (self) devuelve True en el método ShowYourself. – MetaHyperBolic

+0

¡Ah, y estaba retocando mi programa cuando agregó Layout! A punto de darle una oportunidad. – MetaHyperBolic

+0

¡Eso funcionó! Eso solo debe invocarse al final de la función ShowYourself(). Por lo tanto, mi problema conceptual era que estaba ignorando la jerarquía de calibradores, y su solución es que estos también deben ser llamados. ¿Tienes una lista de deseos de Amazon donde podría comprarte un libro? En serio, este problema en particular me tenía bastante deprimido. – MetaHyperBolic

2

Sí, sé que esto ya está contestada, pero aquí ir de todos modos:

Sólo debería tener que llamar a Layout() en el panel de padre, entonces algo así como self.GetParent(). Layout() debería hacer el truco.Ver este artículo: http://www.blog.pythonlibrary.org/2010/06/16/wxpython-how-to-switch-between-panels/

Si desea que los botones se muestren siempre, cree dos paneles en un calibrador vertical. El de arriba mostrará tus paneles y el de abajo mostrará los botones. Luego use PubSub o algo para comunicarse entre ellos.

Cuestiones relacionadas