Dibujo al panel dentro del marco en wxPython

Abajo, tengo un panel dentro de un marco. ¿Por qué no puedo dibujar en el panel? Acabo de conseguir una pantalla blanca lisa. Si me deshago del panel y dibujo directamente al marco … funciona. Cualquier ayuda sería apreciada.

import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self,None,-1,'window',(200,200),(600,600)) self.Center() self.panel=wx.Panel(self) self.panel.SetBackgroundColour('white') self.firstpoint=wx.Point(300,300) self.secondpoint=wx.Point(400,400) self.Bind(wx.EVT_PAINT,self.onPaint) def onPaint(self,event): dc=wx.PaintDC(self.panel) dc.DrawLine(self.firstpoint.x,self.firstpoint.y, self.secondpoint.x,self.secondpoint.y) 

Intente vincular el evento al panel, no a todo el marco:

 self.panel.Bind(wx.EVT_PAINT, self.onPaint) 

Su versión es bastante buena para mí (windows), pero sigue dibujando de nuevo el panel para que se coman todo el procesador.

De la documentación: Tenga en cuenta que en un controlador de eventos de pintura, la aplicación siempre debe crear un objeto wxPaintDC, incluso si no lo usa. De lo contrario, en MS Windows, la actualización de esta y otras ventanas saldrá mal.

Aquí, recibió el evento de pintura para todo el fotogtwig, pero utilizó el dc para el panel.

EDITAR: Este http://wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind explica muy bien por qué esto no funciona:

 self.Bind(wx.EVT_PAINT, self.onPaint, self.panel) 

En este caso, nunca se llama al controlador onPaint.

Estaba buscando un buen ejemplo completo de un control wx.Panel Python personalizado en qué subclases wx.Panel y realiza dibujos personalizados en sí mismo, y no pude encontrar ninguno. Gracias a estas (y otras) preguntas, finalmente logré llegar a un mínimo ejemplo de trabajo, que voy a publicar aquí, porque muestra “dibujar en el Panel dentro de un Marco”; excepto, a diferencia del OP, donde el Marco hace el dibujo en el Panel – aquí el Panel se basa en sí mismo (mientras está sentado en el Marco).

El código produce algo como esto:

test.png

… y, básicamente, el rectángulo rojo se volverá a dibujar cuando cambie el tamaño de la ventana.

Tenga en cuenta los comentarios del código, especialmente sobre la necesidad de Actualizar () en OnSize para evitar la representación / parpadeo corruptos.

El código MWE:

 import wx # tested on wxPython 2.8.11.0, Python 2.7.1+, Ubuntu 11.04 # http://stackoverflow.com/questions/2053268/side-effects-of-handling-evt-paint-event-in-wxpython # http://stackoverflow.com/questions/25756896/drawing-to-panel-inside-of-frame-in-wxpython # http://www.infinity77.net/pycon/tutorial/pyar/wxpython.html # also, see: wx-2.8-gtk2-unicode/wx/lib/agw/buttonpanel.py class MyPanel(wx.Panel): #(wx.PyPanel): #PyPanel also works def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, name="MyPanel"): super(MyPanel, self).__init__(parent, id, pos, size, style, name) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_PAINT, self.OnPaint) def OnSize(self, event): print("OnSize" +str(event)) #self.SetClientRect(event.GetRect()) # no need self.Refresh() # MUST have this, else the rectangle gets rendered corruptly when resizing the window! event.Skip() # seems to reduce the ammount of OnSize and OnPaint events generated when resizing the window def OnPaint(self, event): #~ dc = wx.BufferedPaintDC(self) # works, somewhat dc = wx.PaintDC(self) # works print(dc) rect = self.GetClientRect() # "Set a red brush to draw a rectangle" dc.SetBrush(wx.RED_BRUSH) dc.DrawRectangle(10, 10, rect[2]-20, 50) #self.Refresh() # recurses here! class MyFrame(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, -1, "Custom Panel Demo") self.SetSize((300, 200)) self.panel = MyPanel(self) #wx.Panel(self) self.panel.SetBackgroundColour(wx.Colour(10,10,10)) self.panel.SetForegroundColour(wx.Colour(50,50,50)) sizer_1 = wx.BoxSizer(wx.HORIZONTAL) sizer_1.Add(self.panel, 1, wx.EXPAND | wx.ALL, 0) self.SetSizer(sizer_1) self.Layout() app = wx.App(0) frame = MyFrame(None) app.SetTopWindow(frame) frame.Show() app.MainLoop()