Have you ever thought that it would be cool to have your wxPython code take a screenshot of itself? Well, Andrea Gavana figured out a cool way to do just that and between what he told us on the wxPython mailing list and what I learned from other sources, you will soon learn how to not only take the screenshot, but how to send it to your printer!
Let’s take a look at how to take the screenshot first:
import sys import wx import snapshotPrinter class MyForm(wx.Frame): #---------------------------------------------------------------------- def __init__(self): wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial", size=(500,500)) # Add a panel so it looks the correct on all platforms panel = wx.Panel(self, wx.ID_ANY) screenshotBtn = wx.Button(panel, wx.ID_ANY, "Take Screenshot") screenshotBtn.Bind(wx.EVT_BUTTON, self.onTakeScreenShot) printBtn = wx.Button(panel, label="Print Screenshot") printBtn.Bind(wx.EVT_BUTTON, self.onPrint) sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(screenshotBtn, 0, wx.ALL|wx.CENTER, 5) sizer.Add(printBtn, 0, wx.ALL|wx.CENTER, 5) panel.SetSizer(sizer) def onTakeScreenShot(self, event): """ Takes a screenshot of the screen at give pos & size (rect). """ print 'Taking screenshot...' rect = self.GetRect() # see http://aspn.activestate.com/ASPN/Mail/Message/wxpython-users/3575899 # created by Andrea Gavana # adjust widths for Linux (figured out by John Torres # http://article.gmane.org/gmane.comp.python.wxpython/67327) if sys.platform == 'linux2': client_x, client_y = self.ClientToScreen((0, 0)) border_width = client_x - rect.x title_bar_height = client_y - rect.y rect.width += (border_width * 2) rect.height += title_bar_height + border_width #Create a DC for the whole screen area dcScreen = wx.ScreenDC() #Create a Bitmap that will hold the screenshot image later on #Note that the Bitmap must have a size big enough to hold the screenshot #-1 means using the current default colour depth bmp = wx.EmptyBitmap(rect.width, rect.height) #Create a memory DC that will be used for actually taking the screenshot memDC = wx.MemoryDC() #Tell the memory DC to use our Bitmap #all drawing action on the memory DC will go to the Bitmap now memDC.SelectObject(bmp) #Blit (in this case copy) the actual screen on the memory DC #and thus the Bitmap memDC.Blit( 0, #Copy to this X coordinate 0, #Copy to this Y coordinate rect.width, #Copy this width rect.height, #Copy this height dcScreen, #From where do we copy? rect.x, #What's the X offset in the original DC? rect.y #What's the Y offset in the original DC? ) #Select the Bitmap out of the memory DC by selecting a new #uninitialized Bitmap memDC.SelectObject(wx.NullBitmap) img = bmp.ConvertToImage() fileName = "myImage.png" img.SaveFile(fileName, wx.BITMAP_TYPE_PNG) print '...saving as png!' #---------------------------------------------------------------------- def onPrint(self, event): """ Send screenshot to the printer """ printer = snapshotPrinter.SnapshotPrinter() printer.sendToPrinter() # Run the program if __name__ == "__main__": app = wx.App(False) frame = MyForm() frame.Show() app.MainLoop()
This piece of code create a fairly large frame with two buttons in it. Yes, it’s pretty boring, but this is a demo, not an art show. The part we care about most is the onTakeScreenShot method. If you go to the first commented link, you’ll find Andrea Gavana’s original version of this script. We added a conditional from John Torres in there that makes this script behave better on Linux since it was originally written for Windows. The comments tell the story of the code, so take your time reading them and when you’re done, we can move on to how we can send our result to the printer.
The Snapshot Printer Script
####################################################################### # snapshotPrinter.py # # Created: 12/26/2007 by mld # # Description: Displays screenshot image using html and then allows # the user to print it. ####################################################################### import os import wx from wx.html import HtmlEasyPrinting, HtmlWindow class SnapshotPrinter(wx.Frame): #---------------------------------------------------------------------- def __init__(self, title='Snapshot Printer'): wx.Frame.__init__(self, None, wx.ID_ANY, title, size=(650,400)) self.panel = wx.Panel(self, wx.ID_ANY) self.printer = HtmlEasyPrinting(name='Printing', parentWindow=None) self.html = HtmlWindow(self.panel) self.html.SetRelatedFrame(self, self.GetTitle()) if not os.path.exists('screenshot.htm'): self.createHtml() self.html.LoadPage('screenshot.htm') pageSetupBtn = wx.Button(self.panel, wx.ID_ANY, 'Page Setup') printBtn = wx.Button(self.panel, wx.ID_ANY, 'Print') cancelBtn = wx.Button(self.panel, wx.ID_ANY, 'Cancel') self.Bind(wx.EVT_BUTTON, self.onSetup, pageSetupBtn) self.Bind(wx.EVT_BUTTON, self.onPrint, printBtn) self.Bind(wx.EVT_BUTTON, self.onCancel, cancelBtn) sizer = wx.BoxSizer(wx.VERTICAL) btnSizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(self.html, 1, wx.GROW) btnSizer.Add(pageSetupBtn, 0, wx.ALL, 5) btnSizer.Add(printBtn, 0, wx.ALL, 5) btnSizer.Add(cancelBtn, 0, wx.ALL, 5) sizer.Add(btnSizer) self.panel.SetSizer(sizer) self.panel.SetAutoLayout(True) #---------------------------------------------------------------------- def createHtml(self): ''' Creates an html file in the home directory of the application that contains the information to display the snapshot ''' print 'creating html...' html = '\n\n\n\n' f = file('screenshot.htm', 'w') f.write(html) f.close() #---------------------------------------------------------------------- def onSetup(self, event): self.printer.PageSetup() #---------------------------------------------------------------------- def onPrint(self, event): self.sendToPrinter() #---------------------------------------------------------------------- def sendToPrinter(self): """""" self.printer.GetPrintData().SetPaperId(wx.PAPER_LETTER) self.printer.PrintFile(self.html.GetOpenedPage()) #---------------------------------------------------------------------- def onCancel(self, event): self.Close() class wxHTML(HtmlWindow): #---------------------------------------------------------------------- def __init__(self, parent, id): html.HtmlWindow.__init__(self, parent, id, style=wx.NO_FULL_REPAINT_ON_RESIZE) if __name__ == '__main__': app = wx.App(False) frame = SnapshotPrinter() frame.Show() app.MainLoop()
This little script uses the HtmlWindow widget and the HtmlEasyPrinting method to send something to the printer. Basically, you can create some really simple HTML code (see the createHtml method) and then use the HtmlWindow to view it. Next you use HtmlEasyPrinting to send it to a printer. It will actually display the printer dialog and let you choose which printer you want to send the document to.
Well, I hope you have found this article helpful in your programming. I hope to hear from you in the comments!
Good Job! I like this post, Thanks 😉
P.S.:
“client_x, client_y = window.ClientToScreen((0, 0))” should be “client_x, client_y = self.ClientToScreen((0, 0))”
Just what I needed to avoid using pygtk from inside wxPython 🙂 Many thanks!