2014-09-10 5 views
4

Ниже у меня есть панель внутри рамки. Почему я не могу привлечь к панели? Я просто получаю простой белый экран. Если я избавлюсь от панели и рисую непосредственно на рамку ... она работает. любая помощь будет оценена по достоинству.Рисунок на панели внутри рамки в 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) 
+1

Код выше работает, как ожидалось. Изменение 'self.Bind (...)' '' self.panel.Bind (...) 'работает тоже. –

ответ

6

Постарайтесь связывание события на панель, а не весь кадра:

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

Вашей версию добрейшей работы для меня (окон), но он держит перерисовывать панель, так что съедает весь процессор.

От документации: Обратите внимание: В обработчике событий рисования приложение всегда должно создавать объект wxPaintDC, даже если вы его не используете. В противном случае, в MS Windows, обновление для этого и других окон пойдет не так.

Здесь вы получили событие рисования для всего кадра, но использовали панель управления для панели.

EDIT: Это http://wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind объясняет довольно хорошо, почему это не будет работать:

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

В этом случае обработчик OnPaint не вызывается.

+0

Это сработало. Спасибо. Один вопрос, хотя ... self.Panel.Bind (wx.EVT_PAINT, self.onPaint) работает, но self.Bind (wx.EVT_PAINT, self.onPaint, self.Panel) не делает. Я думал, что эти два утверждения эквивалентны? Почему они не работают одинаково? – BPoy

+0

Обновлен мой ответ ... –

1

Я искал довольно много для полного рабочего примера пользовательского элемента управления wx Python, который подклассы wx.Panel и делает собственный чертеж сам по себе, и я не смог найти его. Благодаря этим (и другим) вопросам я, наконец, смог подойти к минимальному рабочему примеру, который я собираюсь разместить здесь, потому что он показывает «рисование на панели внутри кадра»; кроме, в отличие от OP, где рамка рисует на панели - здесь панель рисует сам (сидя в кадре).

код выдает что-то вроде этого:

test.png

... и в основном красный прямоугольник будет перерисовывать при изменении размеров окна.

Обратите внимание на комментарии к коду, особенно о необходимости обновления() в OnSize, чтобы избежать искажения/мерцания.

Код 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() 
+0

Если вы хотите обновить, я рекомендую использовать: wx.CallAfter (self.Refresh) не имеет смысла вызывать Refresh внутри подпрограммы Paint, потому что, как вы обнаружили, обновите вызовите OnPaint. – RufusVS

Смежные вопросы