Para el trabajo de interfaz gráfica de usuario en general:
Menos es más
trabajo interfaz gráfica de usuario (incluso en los marcos productivos) es lo más divertido y productivo como pintar la Torre Eiffel con un cepillo de dientes. Ve por un diseño minimalista
Evitar el Estado como la peste
pones estado en su interfaz gráfica de usuario, o en el modelo? Si lo coloca en la GUI, se equivocará con rutas de código redundantes e inconsistentes. Si lo coloca en el modelo, se arriesga a un sistema demasiado complejo que no se sincroniza cuando la GUI no se actualiza desde el modelo. Ambos apestan.
wxPython
Si quieres aprender wxPython, aquí hay algunas trampas que me di cuenta:
El tutorial
Usar este tutorial - http://wiki.wxpython.org/AnotherTutorial
¡Es el mejor que encontré.
Pero recuerde alternar los números de línea para pegar fácilmente.
Eventos
Los eventos son un poco como excepciones, y se utilizan para hacer las cosas interactiva.
En un programa de vainilla pitón, se escribe algo como:
def doit(i):
print 'Doing i = ',i
for i in range(10):
doit()
print 'Results = ',result
En una interfaz gráfica de usuario, haces algo como:
def doit(event):
print 'An event',event,'just happened!'
event.Skip()
import wx
app = wx.App()
frame = wx.Frame(None, -1, 'The title goes here')
frame.Bind(wx.EVT_KEY_DOWN, doit)
frame.Show()
app.MainLoop()
Cada vez que el usuario pulsa una tecla, un evento ser criado. Como frame
está vinculado al evento (frame.Bind(wx.EVT_KEY_DOWN, doit)
), se llamará a la función doit
con el evento como argumento.
Imprimir en stderr no está demasiado caliente en una interfaz gráfica de usuario, pero también podría abrir un cuadro de diálogo o hacer lo que usted desee.
Además, puede generar sus propios eventos utilizando temporizadores.
Aplicaciones, marcos, las ventanas, paneles y Sizers
Todo tiene un padre. Si se produce un evento y el niño no lo omite (usando event.Skip()
), el padre también tendrá que manejar el evento. Esto es análogo a excepciones que aumentan a funciones de nivel superior.
A wx.App
es como la función Principal.
wx.Window
no se utiliza realmente. Las cosas heredan de él, y tiene todos los métodos para el tamaño y el diseño, pero no es necesario que lo sepa.
wx.Frame
es un marco flotante, como la ventana principal en Firefox. Tendrás un cuadro principal en una aplicación básica. Si desea editar varios archivos, es posible que tenga más. Un wx.Frame generalmente no tendrá padres.
wx.Panel
es parte de una ventana primaria. Puedes tener varios paneles dentro de un marco. Un panel puede tener un wx.Frame
como padre, o puede ser hijo de otro panel.
wx.Sizers
se utilizan para diseñar automáticamente paneles dentro de marcos (u otros paneles).
Código:
def doit1(event):
print 'event 1 happened'
def doit2(event):
print 'event 2 happened'
import wx
app = wx.App()
frame = wx.Frame(None, -1, 'The title goes here')
panel_1 = wx.Panel(frame,-1,style=wx.SIMPLE_BORDER)
panel_2 = wx.Panel(frame,-1,style=wx.SIMPLE_BORDER)
panel_1.Bind(wx.EVT_KEY_DOWN, doit1)
panel_2.Bind(wx.EVT_KEY_DOWN, doit2)
panel_1.SetBackgroundColour(wx.BLACK)
panel_2.SetBackgroundColour(wx.RED)
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(panel_1,1,wx.EXPAND)
box.Add(panel_2,1,wx.EXPAND)
frame.SetSizer(box)
frame.Show()
app.MainLoop()
he estado muy mal, y no se utilicen prácticas de programación orientada a objetos. Solo recuerde que incluso si odia OO en la mayoría de los contextos, la programación de GUI es el lugar donde realmente brilla la OOP.
El MCV
no consigo MCV. No creo que necesites un MCV. Creo que un marco de MW (modelo-widget) está bien.
Por ejemplo - 2 cuadros que editan el mismo fragmento de texto:
class Model(object):
def __init__(self):
self.value = 'Enter a value'
self.listeners = []
def Add_listener(self,listener):
self.listeners.append(listener)
def Set(self,new_value):
self.value = new_value
for listener in self.listeners:
listener.Update(self.value)
import wx
app = wx.App()
class CVFrame(wx.Frame):
def __init__(self, parent, id, title, model):
wx.Frame.__init__(self, parent, id, title, size = (100,100))
self.button = wx.Button(self, -1, 'Set model value')
self.textctrl = wx.TextCtrl(self, -1,model.value)
self.button.Bind(wx.EVT_BUTTON,self.OnSet)
self.model = model
model.Add_listener(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.button,0,wx.EXPAND)
sizer.Add(self.textctrl,1,wx.EXPAND)
self.SetSize((300,100))
self.SetSizer(sizer)
self.Center()
self.Show()
def OnSet(self,event):
self.model.Set(self.textctrl.GetValue())
def Update(self,value):
self.textctrl.SetValue(value)
model = Model()
frame1 = CVFrame(None, -1, 'Frame 1',model)
frame2 = CVFrame(None, -1, 'Frame 2',model)
app.MainLoop()
wxPython tiene un marco oyente abonado, que es una versión mejor del modelo acabo esbozado (Utiliza referencias débiles, los oyentes eliminados no se quedan, etc.), pero eso debería ayudarlo a entender la idea.
programación de gráficos en Python? ¿Seriamente? –
@David Lively - ¿Qué hay de malo en comenzar allí? Obviamente es un principiante en gráficos, y parece tener solo una comprensión básica de la programación (lo siento si estoy equivocado). – gahooa
Con la programación de gráficos, ¿se refiere a la programación gráfica de la interfaz de usuario? ¿O te refieres a gráficos de computadora, como en videojuegos y películas animadas? –