Drawing Anti-Aliased Graphics Under Tkinter/Windows
Fredrik Lundh | October 2005 | Originally posted to online.effbot.org
I just posted a new aggdraw alpha, which borrows some Windows-specific display code from PIL. You can now create a DIB-compatible drawing surface, draw to it as usual, and blit it directly to screen, without having to convert it to a PIL image memory, a PhotoImage object, or whatever image object your GUI toolkit is using.
Here’s an outline:
import aggdraw dib = aggdraw.Dib("RGB", (800, 600)) ... draw into the dib, as usual ... dib.expose(handle) # in 1.2a1 dib.expose(hwnd=handle) # in 1.2a2
(Note: the 1.2a1 release takes a single positional argument, but the upcoming 1.2a2 requires a keyword argument.)
The handle in this example is a Windows HWND for the window you want to draw into; under Tkinter, you can use the winfo_id() method to get this. The Dib object implements all the usual Draw methods; the only difference between a Draw instance and a Dib instance is that the latter uses a shared memory buffer, and knows how to copy itself to a window.
Here’s a somewhat larger example, using Tkinter:
import aggdraw import random import Tkinter root = Tkinter.Tk() size = 400, 300 # create a Dib surface draw = aggdraw.Dib("RGB", size) # draw something x0 = random.randint(0, size) y0 = random.randint(0, size) for i in range(500): x1 = random.randint(0, size) y1 = random.randint(0, size) draw.line((x0, y0, x1, y1), aggdraw.Pen("black")) x0 = x1; y0 = y1 # display the image frame = Tkinter.Frame(root, width=size, height=size, bg="") frame.bind("<Expose>", lambda e: draw.expose(hwnd=e.widget.winfo_id())) frame.pack() frame.mainloop()
In this example, the <Expose> binding makes sure that the widget is properly redrawn, when needed. The bg=”“ setting tells Tkinter not to draw any background into this window. If you’re using the WCK instead, put the expose code in the repair hook.