Drawing to Panel inside of Frame in wxPython

╄→гoц情女王★ 提交于 2019-12-18 08:43:22

问题


Below, I have a panel inside of a frame. Why am I not able to draw to the panel? I just get a plain white screen. If I get rid of the panel and draw directly to the frame...it works. any help would be appreciated.

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)

回答1:


Try binding the event to the panel, not to the whole frame:

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

Your version kind-of work for me (windows), but it keeps redrawing the panel so it eats up the whole processor.

From documentation: Note that In a paint event handler, the application must always create a wxPaintDC object, even if you do not use it. Otherwise, under MS Windows, refreshing for this and other windows will go wrong.

Here, you received the paint event for the whole frame but used the dc for the panel.

EDIT: This http://wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind explains quite nicely why this won't work:

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

In this case the onPaint handler is never called.




回答2:


I was looking for quite a bit for a complete working example of a custom wx Python control which subclasses wx.Panel and does custom drawing on itself, and I couldn't find any. Thanks to this (and other) questions, I finally managed to come to a minimal working example - which I'm going to post here, because it does show "drawing to Panel inside of a Frame"; except, unlike the OP, where the Frame does the drawing on the Panel - here the Panel draws on itself (while sitting in the Frame).

The code produces something like this:

... and basically the red rectangle will be redrawn when you resize the window.

Note the code comments, especially about the need to Refresh() in OnSize to avoid corrupt rendering / flicker.

The MWE code:

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


来源:https://stackoverflow.com/questions/25756896/drawing-to-panel-inside-of-frame-in-wxpython

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!