在wxPython中绘制到Frame内部的Panel

时间:2014-09-10 03:33:40

标签: python wxpython

下面,我在一个框架内有一个面板。为什么我无法抽到面板?我只是得到一个纯白色的屏幕。如果我摆脱面板并直接绘制到框架......它的工作原理。任何帮助将不胜感激。

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)

2 个答案:

答案 0 :(得分:7)

尝试将事件绑定到面板,而不是整个框架:

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

您的版本对我来说是一种工作(windows),但它不断重绘面板,因此它会占用整个处理器。

来自文档: 请注意,在paint事件处理程序中,即使您不使用它,应用程序也必须始终创建一个wxPaintDC对象。否则,在MS Windows下,刷新此窗口和其他窗口将出错。

在这里,您收到了整个画面的绘画事件,但是使用了DC作为面板。

编辑:http://wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind很好地解释了为什么这不起作用:

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

在这种情况下,永远不会调用onPaint处理程序。

答案 1 :(得分:1)

我正在寻找一个完整的自定义wx Python控件的完整工作示例,它继承wx.Panel并自行进行自定义绘图,而我找不到任何东西。感谢这个(以及其他)问题,我终于设法找到了一个最小的工作示例 - 我将在这里发布,因为它确实显示了“绘制到框架内的面板”;除了OP之外,Frame在Panel上绘制图形 - 这里面板自行绘制(坐在框架中)。

代码生成如下内容:

test.png

...当您调整窗口大小时,基本上会重绘红色矩形。

注意代码注释,特别是OnSize中需要Refresh()以避免损坏的渲染/闪烁。

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