2012-03-01 3 views
0

저는 wxPython을 배우고 자습서 예제에서 다음과 같은 결함에 직면했습니다.wxPython : 동적으로 그려진 그림이 깨졌습니다.

응용 프로그램을 시작하면 응용 프로그램 창의 크기에 따라 크기가있는 그림이 표시됩니다. 그리고 처음에는 그것이 있어야하는 것처럼 보입니다. 그러나 창 크기를 조정할 때 도면이 손상됩니다. 여기에 비디오 http://screencast.com/t/0XOetqJ2W5x

입니다 그리고 여기에 코드입니다 :

# Chapter 8: Drawing to the Screen, Using Device Contexts 
# Recipe 1: Screen Drawing 
# 
import os 
import wx 

#---- Recipe Code ----# 

class Smiley(wx.PyControl): 
    def __init__(self, parent, size=(50,50)): 
     super(Smiley, self).__init__(parent, 
            size=size, 
            style=wx.NO_BORDER) 

     # Event Handlers 
     self.Bind(wx.EVT_PAINT, self.OnPaint) 

    def OnPaint(self, event): 
     """Draw the image on to the panel""" 
     dc = wx.PaintDC(self) # Must create a PaintDC 

     # Get the working rectangle we can draw in 
     rect = self.GetClientRect() 

     # Setup the DC 
     dc.SetPen(wx.BLACK_PEN) # for drawing lines/borders 
     yellowbrush = wx.Brush(wx.Colour(255, 255, 0)) 
     dc.SetBrush(yellowbrush) # Yellow fill 

     # Find the center and draw the circle 
     cx = (rect.width/2) + rect.x 
     cy = (rect.width/2) + rect.y 
     radius = min(rect.width, rect.height)/2 
     dc.DrawCircle(cx, cy, radius) 

     # Give it some square blue eyes 
     # Calc the size of the eyes 1/8th total 
     eyesz = (rect.width/8, rect.height/8) 
     eyepos = (cx/2, cy/2) 
     dc.SetBrush(wx.BLUE_BRUSH) 
     dc.DrawRectangle(eyepos[0], eyepos[1], 
         eyesz[0], eyesz[1]) 
     eyepos = (eyepos[0] + (cx - eyesz[0]), eyepos[1]) 
     dc.DrawRectangle(eyepos[0], eyepos[1], 
         eyesz[0], eyesz[1]) 

     # Draw the smile 
     dc.SetBrush(yellowbrush) 
     startpos = (cx/2, (cy/2) + cy) 
     endpos = (cx + startpos[0], startpos[1]) 
     dc.DrawArc(startpos[0], startpos[1], 
        endpos[0], endpos[1], cx, cy) 

     # Draw a yellow rectangle to cover up the 
     # unwanted black lines from the wedge part of 
     # our arc 
     dc.SetPen(wx.TRANSPARENT_PEN) 
     dc.DrawRectangle(startpos[0], cy, 
         endpos[0] - startpos[0], 
         startpos[1] - cy) 

#---- End Recipe Code ----# 

class SmileyApp(wx.App): 
    def OnInit(self): 
     self.frame = SmileyFrame(None, 
           title="Drawing Shapes", 
           size=(300,400)) 
     self.frame.Show() 
     return True 

class SmileyFrame(wx.Frame): 
    def __init__(self, parent, *args, **kwargs): 
     wx.Frame.__init__(self, parent, *args, **kwargs) 

     # Attributes 
     self.panel = SmileyPanel(self) 

     # Layout 
     sizer = wx.BoxSizer(wx.VERTICAL) 
     sizer.Add(self.panel, 1, wx.EXPAND) 
     self.SetSizer(sizer) 

class SmileyPanel(wx.Panel): 
    def __init__(self, parent): 
     wx.Panel.__init__(self, parent) 

     # Layout 
     self.__DoLayout() 

    def __DoLayout(self): 
     # Layout a grid of 4 smileys 
     msizer = wx.GridSizer(2, 2, 0, 0) 

     for x in range(4): 
      smile = Smiley(self) 
      msizer.Add(smile, 0, wx.EXPAND) 

     self.SetSizer(msizer) 

if __name__ == '__main__': 
    app = SmileyApp(False) 
    app.MainLoop() 

드로잉의 funstions가 wx.EVT_PAINT 이벤트에 바인더 제본 된 OnPaint 메서드에 배치됩니다 볼 수 있듯이. 그래서 저는 시스템이 창을 다시 그릴 때마다 패널에 새로운 이미지를 그려야한다고 생각했습니다. 내가 Win7에, Python2.7와 wxPython을 2.8.12.1

나는 그것의 창에서 확장 다이어그램과 aplication를 작성하는거야으로이 나를 위해 중요하다을 사용하고

.

답변

0

그래서 해결책을 찾았습니다. wx.BufferedDC와 wx.EmptyBitmap을 사용해야합니다. 'wxPython in Action'책 (Sketch 앱에 대한 예)에서 발견했습니다.

import wx 


class Smiley(wx.PyControl): 
    def __init__(self, parent, size=(50,50)): 
     super(Smiley, self).__init__(parent, 
            size=size, 
            style=wx.NO_BORDER) 

     self.InitBuffer()     # new 
     self.Bind(wx.EVT_SIZE, self.OnSize) # new 
     self.Bind(wx.EVT_IDLE, self.OnIdle) # new 

     self.Bind(wx.EVT_PAINT, self.OnPaint) 

# new block 
    def InitBuffer(self): 
     self.client_size = self.GetClientSize() 
     self.buffer = wx.EmptyBitmap(self.client_size.width, self.client_size.height) 
     dc = wx.BufferedDC(None, self.buffer) 
     dc.SetBackground(wx.Brush(self.GetBackgroundColour())) 
     dc.Clear() 
     self.DrawImage(dc) 
     self.reInitBuffer = False 

    def OnSize(self, event): 
     self.reInitBuffer = True 

    def OnIdle(self, event): 
     if self.reInitBuffer: 
      self.InitBuffer() 
      self.Refresh(False) 

    def DrawImage(self, dc): 

     # Get the working rectangle we can draw in 
     rect = self.client_size 

     # Find a square inside a rectangle (size of the client) 
     min_side = min(rect.x, rect.y) 
     rect.SetHeight(min_side) 
     rect.SetWidth(min_side) 

     # Setup the DC 
     dc.SetPen(wx.BLACK_PEN) # for drawing lines/borders 
     yellowbrush = wx.Brush(wx.Colour(255, 255, 0)) 
     dc.SetBrush(yellowbrush) # Yellow fill 

     # Find the center and draw the circle 
     cx = rect.width/2 
     cy = rect.width/2 
     radius = min(rect.width, rect.height)/2 
     dc.DrawCircle(cx, cy, radius) 

     # Give it some square blue eyes 
     # Calc the size of the eyes 1/8th total 
     eyesz = (rect.width/8, rect.height/8) 
     eyepos = (cx/2, cy/2) 
     dc.SetBrush(wx.BLUE_BRUSH) 
     dc.DrawRectangle(eyepos[0], eyepos[1], 
         eyesz[0], eyesz[1]) 
     eyepos = (eyepos[0] + (cx - eyesz[0]), eyepos[1]) 
     dc.DrawRectangle(eyepos[0], eyepos[1], 
         eyesz[0], eyesz[1]) 

     # Draw the smile 
     dc.SetBrush(yellowbrush) 
     startpos = (cx/2, (cy/2) + cy) 
     endpos = (cx + startpos[0], startpos[1]) 
     dc.DrawArc(startpos[0], startpos[1], 
        endpos[0], endpos[1], cx, cy) 

     # Draw a yellow rectangle to cover up the 
     # unwanted black lines from the wedge part of 
     # our arc 
     dc.SetPen(wx.TRANSPARENT_PEN) 
     dc.DrawRectangle(startpos[0], cy, 
         endpos[0] - startpos[0], 
         startpos[1] - cy) 
# end of a new block 

    def OnPaint(self, event): 
     wx.BufferedPaintDC(self, self.buffer) 


class SmileyApp(wx.App): 
    def OnInit(self): 
     self.frame = SmileyFrame(None, 
           title="Drawing Shapes", 
           size=(300,400)) 
     self.frame.Show() 
     return True 

class SmileyFrame(wx.Frame): 
    def __init__(self, parent, *args, **kwargs): 
     wx.Frame.__init__(self, parent, *args, **kwargs) 

     # Attributes 
     self.panel = SmileyPanel(self) 

     # Layout 
     sizer = wx.BoxSizer(wx.VERTICAL) 
     sizer.Add(self.panel, 1, wx.EXPAND) 
     self.SetSizer(sizer) 

class SmileyPanel(wx.Panel): 
    def __init__(self, parent): 
     wx.Panel.__init__(self, parent) 

     # Layout 
     self.__DoLayout() 

    def __DoLayout(self): 
     # Layout a grid of 4 smileys 
     msizer = wx.GridSizer(2, 2, 0, 0) 

     for x in range(4): 
      smile = Smiley(self) 
      msizer.Add(smile, 0, wx.EXPAND) 

     self.SetSizer(msizer) 

if __name__ == '__main__': 
    app = SmileyApp(False) 
    app.MainLoop() 

그리고 여기에 지금 작동하는 방법 : http://screencast.com/t/HXohd4tVJi

완벽하지,하지만 훨씬 더

여기에 새로운 코드입니다. 완벽하게 작동하도록 좀 더 가깝게 만들 수있는 방법을 찾길 바랍니다.

0

완전히 다른 것을 찾고 있었지만 wx.Python을 하루 종일 그리 웠습니다. 신속하게 - 창 크기가 조정될 때마다 self.InitBuffer()으로 전화하십시오.

대부분 고정 코드의 라인 28에 self.InitBuffer()을 추가하면 완벽하게 작동합니다.

def OnSize(self, event): 
    self.reInitBuffer = True 
    self.InitBuffer() 
관련 문제