From 50d340f9005075e38ba1cafe075503fbaacf5c7c Mon Sep 17 00:00:00 2001 From: Duane Johnson Date: Tue, 8 Nov 2011 09:37:35 -0600 Subject: [PATCH] Fixed transparency issues in Windows by using a GraphicsContext. Changed background to white. - The white background is a workaround for not being able to set the exact color of gray for the XY/Z widgets. --- bufferedcanvas.py | 50 ++++++++++------------------------------------- pronterface.py | 1 + test.py | 1 + xybuttons.py | 48 ++++++++++++++++++++------------------------- zbuttons.py | 18 ++++++++++------- 5 files changed, 44 insertions(+), 74 deletions(-) diff --git a/bufferedcanvas.py b/bufferedcanvas.py index 88fcc37..2609300 100644 --- a/bufferedcanvas.py +++ b/bufferedcanvas.py @@ -1,6 +1,6 @@ """ -BufferedCanvas -- Double-buffered, flicker-free canvas widget -Copyright (C) 2005, 2006 Daniel Keep +BufferedCanvas -- flicker-free canvas widget +Copyright (C) 2005, 2006 Daniel Keep, 2011 Duane Johnson To use this widget, just override or replace the draw method. This will be called whenever the widget size changes, or when @@ -46,16 +46,12 @@ import wx class BufferedCanvas(wx.Panel): """ - Implements a double-buffered, flicker-free canvas widget. + Implements a flicker-free canvas widget. Standard usage is to subclass this class, and override the draw method. The draw method is passed a device context, which should be used to do your drawing. - Also, you should NOT call dc.BeginDrawing() and dc.EndDrawing() -- - these methods are automatically called for you, although you still - need to manually clear the device context. - If you want to force a redraw (for whatever reason), you should call the update method. This is because the draw method is never called as a result of an EVT_PAINT event. @@ -77,16 +73,12 @@ class BufferedCanvas(wx.Panel): # Bind events self.Bind(wx.EVT_PAINT, self.onPaint) - self.Bind(wx.EVT_SIZE, self.onSize) # Disable background erasing (flicker-licious) def disable_event(*pargs,**kwargs): pass # the sauce, please self.Bind(wx.EVT_ERASE_BACKGROUND, disable_event) - # Ensure that the buffers are setup correctly - self.onSize(None) - ## ## General methods ## @@ -97,27 +89,11 @@ class BufferedCanvas(wx.Panel): """ pass - - def flip(self): - """ - Flips the front and back buffers. - """ - self.buffer,self.backbuffer = self.backbuffer,self.buffer - self.Refresh() - - def update(self): """ Causes the canvas to be updated. """ - dc = wx.MemoryDC() - width,height = self.getWidthHeight() - self.backbuffer = wx.EmptyBitmapRGBA(width,height,alpha=0) - dc.SelectObject(self.backbuffer) - dc.BeginDrawing() - self.draw(dc) - dc.EndDrawing() - self.flip() + self.Refresh() def getWidthHeight(self): width,height = self.GetClientSizeTuple() @@ -133,15 +109,9 @@ class BufferedCanvas(wx.Panel): def onPaint(self, event): # Blit the front buffer to the screen - dc = wx.BufferedPaintDC(self, self.buffer) - - - def onSize(self, event): - # Here we need to create a new off-screen buffer to hold - # the in-progress drawings on. - w, h = self.getWidthHeight() - self.buffer = wx.EmptyBitmapRGBA(w, h, alpha=0) - self.backbuffer = wx.EmptyBitmapRGBA(w, h, alpha=0) - - # Now update the screen - self.update() + w, h = self.GetClientSizeTuple() + if not w or not h: + return + else: + dc = wx.BufferedPaintDC(self) + self.draw(dc, w, h) diff --git a/pronterface.py b/pronterface.py index 9318f85..99738c8 100755 --- a/pronterface.py +++ b/pronterface.py @@ -120,6 +120,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): self.starttime=0 self.curlayer=0 self.cur_button=None + self.SetBackgroundColour("white") def startcb(self): self.starttime=time.time() diff --git a/test.py b/test.py index f222361..a5ab9f7 100644 --- a/test.py +++ b/test.py @@ -14,6 +14,7 @@ class MyFrame(wx.Frame): sizer.Add(self.z, flag=wx.ALIGN_CENTER) self.SetSizer(sizer) + self.SetBackgroundColour("white") def moveXY(self, x, y): print "got x", x, 'y', y diff --git a/xybuttons.py b/xybuttons.py index e877433..5da0394 100644 --- a/xybuttons.py +++ b/xybuttons.py @@ -13,7 +13,7 @@ class XYButtons(BufferedCanvas): keypad_positions = { 0: (126, 126), 1: (100, 100), - 2: (78, 78), + 2: (80, 80), 3: (60, 60) } concentric_circle_radii = [15, 55, 86, 117, 142] @@ -101,7 +101,7 @@ class XYButtons(BufferedCanvas): def mouseOverKeypad(self, mpos): for idx, kpos in XYButtons.keypad_positions.items(): - rect = wx.Rect(kpos[0], kpos[1], 44, 32) + rect = wx.Rect(kpos[0], kpos[1], self.keypad_bmp.GetWidth(), self.keypad_bmp.GetHeight()) if rect.Contains(mpos): return idx return None @@ -144,28 +144,19 @@ class XYButtons(BufferedCanvas): self.concentric = None self.update() - def drawPartialPie(self, dc, center, r1, r2, angle1, angle2): + def drawPartialPie(self, gc, center, r1, r2, angle1, angle2): parts = 64 angle_dist = angle2 - angle1 angle_inc = angle_dist / parts p1 = wx.Point(center.x + r1*math.cos(angle1), center.y + r1*math.sin(angle1)) - p2 = wx.Point(center.x + r2*math.cos(angle1), center.y + r2*math.sin(angle1)) - p3 = wx.Point(center.x + r2*math.cos(angle2), center.y + r2*math.sin(angle2)) - p4 = wx.Point(center.x + r1*math.cos(angle2), center.y + r1*math.sin(angle2)) - - points = [p1, p2] - - points.extend([wx.Point( - center.x + r1*math.cos(angle1+i*angle_inc), - center.y + r1*math.sin(angle1+i*angle_inc)) for i in range(0, parts)]) - # points.extend([p3]) - - points.extend([wx.Point( - center.x + r2*math.cos(angle1+i*angle_inc), - center.y + r2*math.sin(angle1+i*angle_inc)) for i in range(parts, 0, -1)]) - dc.DrawPolygon(points) + path = gc.CreatePath() + path.MoveToPoint(p1.x, p1.y) + path.AddArc(center.x, center.y, r1, angle1, angle2, True) + path.AddArc(center.x, center.y, r2, angle2, angle1, False) + path.AddLineToPoint(p1.x, p1.y) + gc.DrawPath(path) def distanceToLine(self, pos, x1, y1, x2, y2): xlen = x2 - x1 @@ -174,7 +165,7 @@ class XYButtons(BufferedCanvas): pylen = y1 - pos.y return abs(xlen*pylen-ylen*pxlen)/math.sqrt(xlen**2+ylen**2) - def highlightQuadrant(self, dc, quadrant, concentric): + def highlightQuadrant(self, gc, quadrant, concentric): assert(quadrant >= 0 and quadrant <= 3) assert(concentric >= 0 and concentric <= 3) @@ -197,21 +188,24 @@ class XYButtons(BufferedCanvas): r1 = XYButtons.concentric_circle_radii[concentric] r2 = XYButtons.concentric_circle_radii[concentric+1] - self.drawPartialPie(dc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge) - def draw(self, dc): + self.drawPartialPie(gc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge) + + def draw(self, dc, w, h): + dc.Clear() + gc = wx.GraphicsContext.Create(dc) + center = wx.Point(XYButtons.center[0], XYButtons.center[1]) - dc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4)) - dc.SetBrush(wx.Brush(wx.Colour(0,0,0,128))) - - dc.DrawBitmap(self.bg_bmp, 0, 0) + gc.DrawBitmap(self.bg_bmp, 0, 0, self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight()) if self.quadrant != None and self.concentric != None: - self.highlightQuadrant(dc, self.quadrant, self.concentric) + gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4)) + gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128))) + self.highlightQuadrant(gc, self.quadrant, self.concentric) if self.keypad_idx >= 0: pos = XYButtons.keypad_positions[self.keypad_idx] - dc.DrawBitmap(self.keypad_bmp, pos[0], pos[1]) + gc.DrawBitmap(self.keypad_bmp, pos[0], pos[1], self.keypad_bmp.GetWidth(), self.keypad_bmp.GetHeight()) return True diff --git a/zbuttons.py b/zbuttons.py index e72c670..fa4ac42 100644 --- a/zbuttons.py +++ b/zbuttons.py @@ -38,7 +38,7 @@ class ZButtons(BufferedCanvas): idx += 1 return None - def highlight(self, dc, rng, dir): + def highlight(self, gc, rng, dir): assert(rng >= -1 and rng <= 3) assert(dir >= -1 and dir <= 1) @@ -49,7 +49,8 @@ class ZButtons(BufferedCanvas): k = 1 if dir > 0 else 0 y = ZButtons.center[1] - (dir * ZButtons.button_ydistances[rng+k]) h = ZButtons.button_ydistances[rng+1] - ZButtons.button_ydistances[rng] - dc.DrawRectangle(x, y, w, h) + gc.DrawRoundedRectangle(x, y, w, h, 4) + # gc.DrawRectangle(x, y, w, h) # self.drawPartialPie(dc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge) def getRangeDir(self, pos): @@ -78,13 +79,16 @@ class ZButtons(BufferedCanvas): self.direction = None self.update() - def draw(self, dc): - dc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4)) - dc.SetBrush(wx.Brush(wx.Colour(0,0,0,128))) + def draw(self, dc, w, h): + dc.Clear() + gc = wx.GraphicsContext.Create(dc) - dc.DrawBitmap(self.bg_bmp, 0, 0) + gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4)) + gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128))) + + gc.DrawBitmap(self.bg_bmp, 0, 0, self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight()) if self.range != None and self.direction != None: - self.highlight(dc, self.range, self.direction) + self.highlight(gc, self.range, self.direction) return True