1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
import wx
import colorsys
from math import cos, sin, radians
from Main import opj
#----------------------------------------------------------------------
BASE = 80.0 # sizes used in shapes drawn below
BASE2 = BASE/2
BASE4 = BASE/4
USE_BUFFER = ('wxMSW' in wx.PlatformInfo) # use buffered drawing on Windows
class TestPanel(wx.Panel):
def __init__(self, parent, log):
self.log = log
wx.Panel.__init__(self, parent, -1)
self.Bind(wx.EVT_PAINT, self.OnPaint)
if USE_BUFFER:
self.Bind(wx.EVT_SIZE, self.OnSize)
def OnSize(self, evt):
# When there is a size event then recreate the buffer to match
# the new size of the window.
self.InitBuffer()
evt.Skip()
def OnPaint(self, evt):
if USE_BUFFER:
# The buffer already contains our drawing, so no need to
# do anything else but create the buffered DC. When this
# method exits and dc is collected then the buffer will be
# blitted to the paint DC automagically
dc = wx.BufferedPaintDC(self, self._buffer)
else:
# Otherwise we need to draw our content to the paint DC at
# this time.
dc = wx.PaintDC(self)
gc = self.MakeGC(dc)
self.Draw(gc)
def InitBuffer(self):
sz = self.GetClientSize()
sz.width = max(1, sz.width)
sz.height = max(1, sz.height)
self._buffer = wx.EmptyBitmap(sz.width, sz.height, 32)
dc = wx.MemoryDC(self._buffer)
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
dc.Clear()
gc = self.MakeGC(dc)
self.Draw(gc)
def MakeGC(self, dc):
try:
if False:
# If you want to force the use of Cairo instead of the
# native GraphicsContext backend then create the
# context like this. It works on Windows so far, (on
# wxGTK the Cairo context is already being used as the
# native default.)
gcr = wx.GraphicsRenderer.GetCairoRenderer
gc = gcr() and gcr().CreateContext(dc)
if gc is None:
wx.MessageBox("Unable to create Cairo Context.", "Oops")
gc = wx.GraphicsContext.Create(dc)
else:
# Otherwise, creating it this way will use the native
# backend, (GDI+ on Windows, CoreGraphics on Mac, or
# Cairo on GTK).
gc = wx.GraphicsContext.Create(dc)
except NotImplementedError:
dc.DrawText("This build of wxPython does not support the wx.GraphicsContext "
"family of classes.",
25, 25)
return None
return gc
def Draw(self, gc):
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
font.SetWeight(wx.BOLD)
gc.SetFont(font)
# make a path that contains a circle and some lines, centered at 0,0
path = gc.CreatePath()
path.AddCircle(0, 0, BASE2)
path.MoveToPoint(0, -BASE2)
path.AddLineToPoint(0, BASE2)
path.MoveToPoint(-BASE2, 0)
path.AddLineToPoint(BASE2, 0)
path.CloseSubpath()
path.AddRectangle(-BASE4, -BASE4/2, BASE2, BASE4)
# Now use that path to demonstrate various capbilites of the grpahics context
gc.PushState() # save current translation/scale/other state
gc.Translate(60, 75) # reposition the context origin
gc.SetPen(wx.Pen("navy", 1))
gc.SetBrush(wx.Brush("pink"))
# show the difference between stroking, filling and drawing
for label, PathFunc in [("StrokePath", gc.StrokePath),
("FillPath", gc.FillPath),
("DrawPath", gc.DrawPath)]:
w, h = gc.GetTextExtent(label)
gc.DrawText(label, -w/2, -BASE2-h-4)
PathFunc(path)
gc.Translate(2*BASE, 0)
gc.PopState() # restore saved state
gc.PushState() # save it again
gc.Translate(60, 200) # offset to the lower part of the window
gc.DrawText("Scale", 0, -BASE2)
gc.Translate(0, 20)
# for testing clipping
#gc.Clip(0, 0, 100, 100)
#rgn = wx.RegionFromPoints([ (0,0), (75,0), (75,25,), (100, 25),
# (100,100), (0,100), (0,0) ])
#gc.ClipRegion(rgn)
#gc.ResetClip()
gc.SetBrush(wx.Brush(wx.Colour(178, 34, 34, 128))) # 128 == half transparent
for cnt in range(8):
gc.Scale(1.08, 1.08) # increase scale by 8%
gc.Translate(5,5)
gc.DrawPath(path)
gc.PopState() # restore saved state
gc.PushState() # save it again
gc.Translate(400, 200)
gc.DrawText("Rotate", 0, -BASE2)
# Move the origin over to the next location
gc.Translate(0, 75)
# draw our path again, rotating it about the central point,
# and changing colors as we go
for angle in range(0, 360, 30):
gc.PushState() # save this new current state so we can
# pop back to it at the end of the loop
r, g, b = [int(c * 255) for c in colorsys.hsv_to_rgb(float(angle)/360, 1, 1)]
gc.SetBrush(wx.Brush(wx.Colour(r, g, b, 64)))
gc.SetPen(wx.Pen(wx.Colour(r, g, b, 128)))
# use translate to artfully reposition each drawn path
gc.Translate(1.5 * BASE2 * cos(radians(angle)),
1.5 * BASE2 * sin(radians(angle)))
# use Rotate to rotate the path
gc.Rotate(radians(angle))
# now draw it
gc.DrawPath(path)
gc.PopState()
# Draw a bitmap with an alpha channel on top of the last group
bmp = wx.Bitmap(opj('bitmaps/toucan.png'))
bsz = bmp.GetSize()
gc.DrawBitmap(bmp,
#-bsz.width,
#-bsz.height/2,
-bsz.width/2.5,
-bsz.height/2.5,
bsz.width, bsz.height)
gc.PopState()
#----------------------------------------------------------------------
def runTest(frame, nb, log):
win = TestPanel(nb, log)
return win
#----------------------------------------------------------------------
overview = """<html><body>
<h2><center>wx.GraphicsContext and wx.GraphicsPath</center></h2>
The new advanced 2D drawing API is implemented via the
wx.GraphicsContext and wx.GraphicsPath classes. They wrap GDI+ on
Windows, Cairo on wxGTK and CoreGraphics on OS X. They allow
path-based drawing with alpha-blending and anti-aliasing, and use a
floating point cooridnate system.
<p>When viewing this sample pay attention to how the rounded edges are
smoothed with anti-aliased drawing, and how the shapes on the lower
half of the window are partially transparent, allowing you to see what
was drawn before.
</body></html>
"""
if __name__ == '__main__':
import sys,os
import run
run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
|