2013-05-28 4 views
1

방금 ​​Python으로 프로그래밍을 시작 했으므로 미터기 (회전 카운터)로 구성된 간단한 GUI에서 시도했습니다. 및 막대 그래프. 이것은 모두 작동합니다 (코드는 아래에 첨부되어 있습니다). 그러나 화면 상쾌하게하기 (Windows XP) 때문에 매우 깜박입니다. Buffered DC를 사용해야하지만 실제로 필요한 모든 게시물에서 해결할 수는 없습니다. WxPython, 간단한 GUI (Rev 카운터 및 막대 그래프)에서 버퍼가있는 DC 및 패널 새로 고침 사용

그러나 나의 가정은 다음과 같습니다

  1. 는 처음에 '상주'에 버퍼 이미지의 메모리 DC를 만든 다음
  2. 은 버퍼 DC
  3. 바인드 온은 버퍼 DC에 페인트 인스턴스화.

필자는 관련 미터 페이스 (눈금)를 제공하기 위해 Autocad에서이 모든 것을 그렸고 막대 그래프와 미터 바늘이 겹쳐있는 jpg (HMIV0.2.bmp)로 변환했습니다.

루프의 끝에서 새로 고침을 사용하고 있으며 이것이 '나쁜 습관'인지 궁금합니다. 그러나 내 의도는 프로그램을 자유롭게 실행하고 루프의 각 패스에서 관련 값 (회전 수)을 '선택'하는 것입니다. 따라서 외부 이벤트가 없어 페인트를 트리거 할 수 있습니다.

옳은 방향의 조언이나 포인터는 매우 높이 평가됩니다 ... 저는 영감을 얻기 위해 Cody Precord의 'Wx.Python 2.8 Application Development Cookbook'을 구입했습니다.

import wx 
import random 
import time 
import math 

def Data(): 
    data_value =random.randint(0,400) 
    return data_value 

def Pointer(): 
    meter_value =float(random.randint(0,260)) 
    Needle_centre_x = 253 
    Needle_centre_y = 239 
    Needle_length = float(125) 
    Needle_sweep = math.radians(214) #Number of degrees (converted to radians) that the needle is to deflect through 
    Meter_max_scale = 260 # maximum value on the meter scale 
    lo_reflect = float(20) # Meter reading that are less than this value are below the horizontal-Lo 
    Angle_per_digit = Needle_sweep/Meter_max_scale # Angle_per_digit is in radians 
    print '*******************NEW CYCLE*****************************' 
    print 'The meter value is ' +str(meter_value) 

    Start_displac = Angle_per_digit * lo_reflect 
    needle_ang = -1*(Start_displac -(meter_value * Angle_per_digit)) 
    Needle_x = Needle_length * (math.cos(needle_ang)) 
    Needle_y = Needle_length * (math.sin(needle_ang)) 
    needle_degrees = math.degrees(needle_ang) 
    anglea = needle_ang - math.pi/2 
    angleb = needle_ang + math.pi/2 
    base_x = 10*(math.cos(anglea)) 
    base_y = 10*(math.sin(anglea)) 
    print 'The needle angle is' + str(needle_degrees) 
    print 'Angle A is ' + str(math.degrees(anglea)) 
    print 'Angle B is ' + str(math.degrees(angleb))  
    print 'The needle deflection angle is ' + str(math.degrees(needle_ang)) 
    basea_y = int(Needle_centre_y- base_y) 
    basea_x = int(Needle_centre_x - base_x) 
    baseb_y = int(Needle_centre_y + base_y) 
    baseb_x = int(Needle_centre_x + base_x)     
    needle_y = int(Needle_centre_y - Needle_y) 
    needle_x = int(Needle_centre_x - Needle_x)    
    Needle = [Needle_centre_x,Needle_centre_y,needle_x,needle_y,basea_x,basea_y,baseb_x,baseb_y] #Needle = [x1,y1,x2,y2,pointa_y,pointa_x,pointb_y,pointb_x] 
    return Needle 

class MyPanel(wx.Panel): 
    def __init__(self, parent): 
     wx.Panel.__init__(self, parent,pos = (0,0), size = (800,500)) 
     self.Bind(wx.EVT_PAINT, self.OnPaint) 

    def OnPaint(self, data_value):   
     data_value = Data() 
     dc = wx.PaintDC(self) 
     bmp = wx.Bitmap("HMIV0.2.bmp") 
     dc.DrawBitmap(bmp, 0, 0)   

     if data_value > 300: 
      dc.SetBrush(wx.RED_BRUSH) 
      dc.DrawRoundedRectangle(12,450,40,-1*(data_value),2) 
      dc.SetBrush(wx.BLUE_BRUSH) 
      dc.DrawRoundedRectangle(12,450,40,-1*300,2) 
      dc.SetBrush(wx.GREEN_BRUSH) 
      dc.DrawRoundedRectangle(12,450,40,-1*200,2) 

     if data_value < 300 and data_value > 200 : 
      dc.SetBrush(wx.BLUE_BRUSH) 
      dc.DrawRoundedRectangle(12,450,40,-1*(data_value),2) 
      dc.SetBrush(wx.GREEN_BRUSH) 
      dc.DrawRoundedRectangle(12,450,40,-1*200,2) 

     if data_value < 200: 
      dc.SetBrush(wx.GREEN_BRUSH) 
      dc.DrawRoundedRectangle(12,450,40,-1*(data_value),2)   

     dc.SetBrush(wx.BLUE_BRUSH) 
     HMI_needle = Pointer() 
     print 'the contents of HMI needle are' + str(HMI_needle) 
     print 'Needle_centre_x,Needle_centre_y,needle_x,needle_y,basea_x,basea_y,baseb_x,baseb_y' 
     print type(HMI_needle) 
     Points = [(HMI_needle[2],HMI_needle[3]),(HMI_needle[4],HMI_needle[5]),(HMI_needle[6],HMI_needle[7])] 
     dc.DrawPolygon(Points) 
     dc.DrawCircle(253,239,20)     
     time.sleep(0.1)  
     self.Refresh()  

class MyFrame(wx.Frame): 
    def __init__(self, parent, title, size): 
     wx.Frame.__init__(self, parent, wx.ID_ANY, title, wx.DefaultPosition, size,) 
     bitmap = wx.Bitmap("Background.jpg", type=wx.BITMAP_TYPE_JPEG) 
     self.bitmap =wx.StaticBitmap(self,bitmap =bitmap) 
     self.Panel = MyPanel(self) 


app = wx.PySimpleApp(redirect=False, filename = "C:\output.txt", clearSigInt=True) 
frame = MyFrame(None,"WxPaint", size=(800,500))#size=(800,480)) 
frame.Show() 
app.SetTopWindow(frame) 
app.MainLoop() 
+0

감사합니다, Foglebird! 그것은 대접을했습니다! 안부, 롭 – Robert

답변

1
    당신의 OnPaint 핸들러에 wx.Panel
  • 사용 wx.AutoBufferedPaintDC
  • 사용 wx.BG_STYLE_CUSTOM

여기에 내 예제 코드를 참조하십시오

Best Canvas for WxPython

+0

'wx.Panel'을 사용하는 FWIW는 실제로 필요하지 않습니다. 간단한'wx.Window'도 마찬가지입니다. –

0

그것은 거의 없다 대부분 다른 이벤트가 처리되지 못하기 때문에 이벤트 핸들러에 지연을 넣는 것이 좋습니다. 대신에 당신의 OnPaint 처리기를 종료의 :

time.sleep(0.1)  
self.Refresh()  

사용한다 :

wx.CallLater(100,self.Refresh) 

또한, 내가 깜박임을 방지하기 위해 발견, 나는 배경으로 삭제하지 않도록 :

self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: 0)