Printing framework - Part 1 (Phoenix)

Keywords : Printing, Printout, Preview, Printer, PrintData, PrintDialogData, PageSetupDialogData, PageSetupDialog, PrintPreview, PreviewFrame, Canvas, Grid, HtmlEasyPrinting, PDFViewer, PDFWindow, ReportLab.


Introduction

The Printer framework for wx.Windows / wx.Python is quite complicated.

Because of this, wx.HtmlEasyPrinting is provided to help simplify basic printing functionality.

This Recipe covers a simplified approach to using both wx.HtmlEasyPrinting and the more complicated wx.Printout.


What Objects are Involved

The following classes will be used in these recipes :


Demonstrating :

Tested py3.x, wx4.x and Win10.

Printing is an essential element for your programs, here we show you how to print.

Are you ready to use some samples ? ;)

Test, modify, correct, complete, improve and share your discoveries ! (!)


Direct printing

img_sample_one.png

   1 # sample_one.py
   2 
   3 import sys
   4 import os
   5 import platform
   6 import wx
   7 
   8 # class My_Frame
   9 # class My_App
  10 
  11 #-------------------------------------------------------------------------------
  12 
  13 if os.name == "posix":
  14     print("\nPlatform : UNIX - Linux")
  15 elif os.name in ['nt', 'dos', 'ce']:
  16     print("\nPlatform : Windows")
  17 else:
  18     print("\nPlatform : ", platform.system())
  19 
  20 #-------------------------------------------------------------------------------
  21 
  22 class My_Frame(wx.Frame):
  23     """
  24     Create a main frame for my application.
  25     """
  26     def __init__(self, parent, id, title=""):
  27         wx.Frame.__init__(self,
  28                           parent,
  29                           id,
  30                           title,
  31                           size=(600, 350),
  32                           style=wx.DEFAULT_FRAME_STYLE)
  33 
  34         #------------
  35 
  36         # Simplified init method.
  37         self.SetProperties()
  38         self.CreateMenu()
  39         self.CreateCtrls()
  40         self.BindEvents()
  41         self.DoLayout()
  42 
  43         #------------
  44 
  45         self.CenterOnScreen()
  46 
  47     #---------------------------------------------------------------------------
  48 
  49     def SetProperties(self):
  50         """
  51         Set the main frame properties (title, icon...).
  52         """
  53 
  54         frameicon = wx.Icon("Icons/wxWidgets.ico")
  55         self.SetIcon(frameicon)
  56 
  57         #------------
  58 
  59         self.SetTitle("Printing test...")
  60 
  61 
  62     def CreateMenu(self):
  63         """
  64         Make the frame menus.
  65         """
  66 
  67         menub = wx.MenuBar()
  68 
  69         fmenu = wx.Menu()
  70         fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
  71         fmenu.AppendSeparator()
  72         fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
  73         menub.Append(fmenu, "&File")
  74 
  75         self.SetMenuBar(menub)
  76 
  77 
  78     def CreateCtrls(self):
  79         """
  80         Make widgets for my application.
  81         """
  82 
  83         boldFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
  84         boldFont.SetWeight(wx.BOLD)
  85         boldFont.SetPointSize(10)
  86 
  87         #------------
  88 
  89         # First create the controls.
  90         self.panel = wx.Panel(self,
  91                               id=-1,
  92                               style=wx.BORDER_THEME|
  93                               wx.TAB_TRAVERSAL)
  94 
  95         self.text = wx.StaticText(self.panel,
  96                                   id=-1,
  97                                   label="Demonstrating :")
  98         self.text.SetFont(boldFont)
  99 
 100         self.info = wx.StaticText(self.panel,
 101                                   id=-1,
 102                                   label="> Direct printing.")
 103         self.info.SetForegroundColour("red")
 104 
 105         self.tc = wx.TextCtrl(self.panel,
 106                               id=-1,
 107                               size=(200, -1),
 108                               value="Hello, World ! A sample text.")
 109 
 110         self.btnPrint = wx.Button(self.panel,
 111                                   id=wx.ID_PRINT,
 112                                   label="")
 113         self.btnPrint.SetFocus()
 114 
 115         self.btnClose = wx.Button(self.panel,
 116                                   id=wx.ID_CLOSE,
 117                                   label="E&xit")
 118 
 119 
 120     def BindEvents(self):
 121         """
 122         Bind all the events related to my application.
 123         """
 124 
 125         # Bind some menu events to an events handler.
 126         self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
 127         self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
 128 
 129         # Bind the close event to an event handler.
 130         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 131 
 132         # Bind some buttons events to an events handler.
 133         self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
 134         self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
 135 
 136 
 137     def DoLayout(self):
 138         """
 139         Manage widgets Layout.
 140         """
 141 
 142         # MainSizer is the top-level one that manages everything.
 143         mainSizer = wx.BoxSizer(wx.VERTICAL)
 144 
 145         #------------
 146 
 147         hBox1 = wx.BoxSizer(wx.HORIZONTAL)
 148         hBox1.Add(self.info, 0, wx.ALL, 15)
 149 
 150         #------------
 151 
 152         hBox2 = wx.BoxSizer(wx.HORIZONTAL)
 153         hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
 154         hBox2.Add(self.btnClose, 0, wx.ALL, 10)
 155 
 156         #------------
 157 
 158         mainSizer.Add(self.text, 0, wx.ALL, 10)
 159         mainSizer.Add(wx.StaticLine(self.panel),
 160                       0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
 161         mainSizer.Add(self.tc, 0, wx.ALL, 15)
 162         mainSizer.Add(hBox1, 0, wx.ALL, 5)
 163         mainSizer.Add(hBox2, 0, wx.ALL, 5)
 164 
 165         #------------
 166 
 167         # Finally, tell the panel to use the mainSizer for layout.
 168         self.panel.SetSizer(mainSizer)
 169 
 170 
 171     def OnBtnPrint(self, event):
 172         """
 173         Print the document.
 174         """
 175 
 176         text = self.tc.GetValue()
 177 
 178         #------------
 179 
 180         pd = wx.PrintData()
 181 
 182         pd.SetPrinterName("")
 183         pd.SetOrientation(wx.PORTRAIT)
 184         pd.SetPaperId(wx.PAPER_A4)
 185         pd.SetQuality(wx.PRINT_QUALITY_DRAFT)
 186         # Black and white printing if False.
 187         pd.SetColour(True)
 188         pd.SetNoCopies(1)
 189         pd.SetCollate(True)
 190 
 191         #------------
 192 
 193         pdd = wx.PrintDialogData()
 194 
 195         pdd.SetPrintData(pd)
 196         pdd.SetMinPage(1)
 197         pdd.SetMaxPage(1)
 198         pdd.SetFromPage(1)
 199         pdd.SetToPage(1)
 200         pdd.SetPrintToFile(False)
 201         # pdd.SetSetupDialog(False)
 202         # pdd.EnableSelection(True)
 203         # pdd.EnablePrintToFile(True)
 204         # pdd.EnablePageNumbers(True)
 205         # pdd.SetAllPages(True)
 206 
 207         #------------
 208 
 209         dlg = wx.PrintDialog(self, pdd)
 210 
 211         if dlg.ShowModal() == wx.ID_OK:
 212             dc = dlg.GetPrintDC()
 213 
 214             dc.StartDoc("My document title")
 215             dc.StartPage()
 216 
 217             # (wx.MM_METRIC) ---> Each logical unit is 1 mm.
 218             # (wx.MM_POINTS) ---> Each logical unit is a "printer point" i.e.
 219             dc.SetMapMode(wx.MM_POINTS)
 220 
 221             dc.SetTextForeground("red")
 222             dc.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.BOLD))
 223             dc.DrawText(text, 50, 100)
 224 
 225             dc.EndPage()
 226             dc.EndDoc()
 227             del dc
 228 
 229         else :
 230             dlg.Destroy()
 231 
 232 
 233     def OnBtnClose(self, event):
 234         """
 235         ...
 236         """
 237 
 238         self.Close(True)
 239 
 240 
 241     def OnCloseWindow(self, event):
 242         """
 243         ...
 244         """
 245 
 246         self.Destroy()
 247 
 248 #-------------------------------------------------------------------------------
 249 
 250 class My_App(wx.App):
 251     """
 252     ...
 253     """
 254     def OnInit(self):
 255 
 256         #------------
 257 
 258         frame = My_Frame(None, id=-1)
 259         self.SetTopWindow(frame)
 260         frame.Show(True)
 261 
 262         return True
 263 
 264 #-------------------------------------------------------------------------------
 265 
 266 def main():
 267     app = My_App(False)
 268     app.MainLoop()
 269 
 270 #-------------------------------------------------------------------------------
 271 
 272 if __name__ == "__main__" :
 273     main()


Printout class

img_sample_two.png

   1 # sample_two.py
   2 
   3 import sys
   4 import os
   5 import platform
   6 import wx
   7 
   8 # class My_Printout
   9 # class My_Frame
  10 # class My_App
  11 
  12 #-------------------------------------------------------------------------------
  13 
  14 if os.name == "posix":
  15     print("\nPlatform : UNIX - Linux")
  16 elif os.name in ['nt', 'dos', 'ce']:
  17     print("\nPlatform : Windows")
  18 else:
  19     print("\nPlatform : ", platform.system())
  20 
  21 #-------------------------------------------------------------------------------
  22 
  23 class My_Printout(wx.Printout):
  24     """
  25     Create a printout.
  26     """
  27     def __init__(self, text, title):
  28         wx.Printout.__init__(self, title)
  29 
  30         #------------
  31 
  32         self.lines = text
  33 
  34     #---------------------------------------------------------------------------
  35 
  36     def OnBeginDocument(self, start, end):
  37         """
  38         ...
  39         """
  40 
  41         return super(My_Printout, self).OnBeginDocument(start, end)
  42 
  43 
  44     def OnEndDocument(self):
  45         """
  46         ...
  47         """
  48 
  49         super(My_Printout, self).OnEndDocument()
  50 
  51 
  52     def OnBeginPrinting(self):
  53         """
  54         ...
  55         """
  56 
  57         super(My_Printout, self).OnBeginPrinting()
  58 
  59 
  60     def OnEndPrinting(self):
  61         """
  62         ...
  63         """
  64 
  65         super(My_Printout, self).OnEndPrinting()
  66 
  67 
  68     def OnPreparePrinting(self):
  69         """
  70         ...
  71         """
  72 
  73         super(My_Printout, self).OnPreparePrinting()
  74 
  75 
  76     def HasPage(self, page):
  77         """
  78         ...
  79         """
  80 
  81         if page <= 2:
  82             return True
  83         else:
  84             return False
  85 
  86 
  87     def GetPageInfo(self):
  88         """
  89         ...
  90         """
  91 
  92         return (1, 2, 1, 2)
  93 
  94 
  95     def OnPrintPage(self, page):
  96         """
  97         ...
  98         """
  99 
 100         dc = self.GetDC()
 101 
 102         # (wx.MM_METRIC) ---> Each logical unit is 1 mm.
 103         # (wx.MM_POINTS) ---> Each logical unit is a "printer point" i.e.
 104         dc.SetMapMode(wx.MM_POINTS)
 105 
 106         dc.SetTextForeground("red")
 107         dc.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.BOLD))
 108         dc.DrawText(self.lines, 50, 100)
 109 
 110         # R, V, B.
 111         dc.SetPen(wx.Pen(wx.Colour(255, 20, 5)))
 112         dc.SetBrush(wx.Brush(wx.Colour(30, 255, 20)))
 113         # x, y, radius.
 114         dc.DrawCircle(100, 275, 25)
 115         # x, y, width, height.
 116         dc.DrawEllipse(100, 275, 75, 50)
 117 
 118         return True
 119 
 120 #-------------------------------------------------------------------------------
 121 
 122 class My_Frame(wx.Frame):
 123     """
 124     Create a main frame for my application.
 125     """
 126     def __init__(self, parent, id, title=""):
 127         wx.Frame.__init__(self,
 128                           parent,
 129                           id,
 130                           title,
 131                           size=(600, 350),
 132                           style=wx.DEFAULT_FRAME_STYLE)
 133 
 134         #------------
 135 
 136         # Simplified init method.
 137         self.SetProperties()
 138         self.CreateMenu()
 139         self.CreateCtrls()
 140         self.CreatePrintData()
 141         self.BindEvents()
 142         self.DoLayout()
 143 
 144         #------------
 145 
 146         self.CenterOnScreen()
 147 
 148     #---------------------------------------------------------------------------
 149 
 150     def SetProperties(self):
 151         """
 152         Set the main frame properties (title, icon...).
 153         """
 154 
 155         frameicon = wx.Icon("Icons/wxWidgets.ico")
 156         self.SetIcon(frameicon)
 157 
 158         #------------
 159 
 160         self.SetTitle("Printing test...")
 161 
 162 
 163     def CreateMenu(self):
 164         """
 165         Make the frame menus.
 166         """
 167 
 168         menub = wx.MenuBar()
 169 
 170         fmenu = wx.Menu()
 171         fmenu.Append(wx.ID_PAGE_SETUP, "Page set&up\tCtrl+U")
 172         fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
 173         fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
 174         fmenu.AppendSeparator()
 175         fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
 176         menub.Append(fmenu, "&File")
 177 
 178         self.SetMenuBar(menub)
 179 
 180 
 181     def CreateCtrls(self):
 182         """
 183         Make widgets for my app.
 184         """
 185 
 186         font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
 187         font.SetWeight(wx.BOLD)
 188         font.SetPointSize(10)
 189 
 190         #------------
 191 
 192         # First create the controls.
 193         self.panel = wx.Panel(self,
 194                               id=-1,
 195                               style=wx.BORDER_THEME|
 196                               wx.TAB_TRAVERSAL)
 197 
 198         self.text = wx.StaticText(self.panel,
 199                                   id=-1,
 200                                   label="Demonstrating :")
 201         self.text.SetFont(font)
 202 
 203         self.info = wx.StaticText(self.panel,
 204                                   id=-1,
 205                                   label="1) Direct printing,\n"
 206                                         "2) Printout class,\n"
 207                                         "3) Preview,\n"
 208                                         "4) Menu,\n"
 209                                         "5) Page setup.")
 210         self.info.SetForegroundColour("red")
 211         font.SetWeight(wx.NORMAL)
 212         self.info.SetFont(font)
 213 
 214         self.tc = wx.TextCtrl(self.panel,
 215                               id=-1,
 216                               size=(200, -1),
 217                               value="Hello, World ! A sample text.")
 218 
 219         self.btnSetup = wx.Button(self.panel,
 220                                   id=wx.ID_PAGE_SETUP,
 221                                   label="Page set&up")
 222 
 223         self.btnPreview = wx.Button(self.panel,
 224                                     id=wx.ID_PREVIEW,
 225                                     label="Print pre&view")
 226         self.btnPreview.SetFocus()
 227 
 228         self.btnPrint = wx.Button(self.panel,
 229                                   id=wx.ID_PRINT,
 230                                   label="&Print")
 231 
 232         self.btnClose = wx.Button(self.panel,
 233                                   id=wx.ID_CLOSE,
 234                                   label="E&xit")
 235 
 236 
 237     def CreatePrintData(self):
 238         """
 239         Create printing data.
 240         """
 241 
 242         self.printdata = wx.PrintData()
 243 
 244         self.printdata.SetPrinterName('')
 245         self.printdata.SetOrientation(wx.PORTRAIT)
 246         self.printdata.SetPaperId(wx.PAPER_A4)
 247         self.printdata.SetQuality(wx.PRINT_QUALITY_DRAFT)
 248         # Black and white printing if False.
 249         self.printdata.SetColour(True)
 250         self.printdata.SetNoCopies(1)
 251         self.printdata.SetCollate(True)
 252         # self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
 253 
 254 
 255     def BindEvents(self):
 256         """
 257         Bind all the events related to my application.
 258         """
 259 
 260         # Bind some menu events to an events handler.
 261         self.Bind(wx.EVT_MENU, self.OnBtnPageSetup, id=wx.ID_PAGE_SETUP)
 262         self.Bind(wx.EVT_MENU, self.OnBtnPreview, id=wx.ID_PREVIEW)
 263         self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
 264         self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
 265 
 266         # Bind the close event to an event handler.
 267         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 268 
 269         # Bind some buttons events to an events handler.
 270         self.Bind(wx.EVT_BUTTON, self.OnBtnPageSetup, self.btnSetup)
 271         self.Bind(wx.EVT_BUTTON, self.OnBtnPreview, self.btnPreview)
 272         self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
 273         self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
 274 
 275 
 276     def DoLayout(self):
 277         """
 278         Manage widgets Layout.
 279         """
 280 
 281         # MainSizer is the top-level one that manages everything.
 282         mainSizer = wx.BoxSizer(wx.VERTICAL)
 283 
 284         #------------
 285 
 286         hBox1 = wx.BoxSizer(wx.HORIZONTAL)
 287         hBox1.Add(self.info, 0, wx.ALL, 15)
 288 
 289         #------------
 290 
 291         hBox2 = wx.BoxSizer(wx.HORIZONTAL)
 292         hBox2.Add(self.btnSetup, 0, wx.ALL, 10)
 293         hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
 294         hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
 295         hBox2.Add(self.btnClose, 0, wx.ALL, 10)
 296 
 297         #------------
 298 
 299         mainSizer.Add(self.text, 0, wx.ALL, 10)
 300         mainSizer.Add(wx.StaticLine(self.panel),
 301                       0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
 302         mainSizer.Add(self.tc, 0, wx.ALL, 15)
 303         mainSizer.Add(hBox1, 0, wx.ALL, 5)
 304         mainSizer.Add(hBox2, 0, wx.ALL, 5)
 305 
 306         #------------
 307 
 308         # Finally, tell the panel to use the mainSizer for layout.
 309         self.panel.SetSizer(mainSizer)
 310 
 311 
 312     def OnBtnPageSetup(self, event):
 313         """
 314         Show the PrinterSetup dialog.
 315         """
 316 
 317         psdd = wx.PageSetupDialogData(self.printdata)
 318 
 319         psdd.EnablePrinter(True)
 320         # psdd.CalculatePaperSizeFromId()
 321 
 322         #------------
 323 
 324         dlg = wx.PageSetupDialog(self, psdd)
 325         dlg.ShowModal()
 326 
 327         #------------
 328 
 329         # This makes a copy of the wx.PrintData instead of just saving
 330         # a reference to the one inside the PrintDialogData that will
 331         # be destroyed when the dialog is destroyed
 332         self.printdata = wx.PrintData(dlg.GetPageSetupData().GetPrintData())
 333 
 334         dlg.Destroy()
 335 
 336 
 337     def OnBtnPreview(self, event):
 338         """
 339         Show the print preview.
 340         """
 341 
 342         text = self.tc.GetValue()
 343 
 344         #------------
 345 
 346         data = wx.PrintDialogData(self.printdata)
 347 
 348         printout1 = My_Printout(text, "- My printing object")
 349         printout2 = My_Printout(text, "- My printing object")
 350 
 351         printPreview = wx.PrintPreview(printout1, printout2, data)
 352 
 353         # Initial zoom value.
 354         if "__WXMAC__" in wx.PlatformInfo:
 355             printPreview.SetZoom(50)
 356         else:
 357             printPreview.SetZoom(35)
 358 
 359         if not printPreview.IsOk():
 360             wx.MessageBox(("There was a problem printing.\nPerhaps "\
 361                            "your current printer is \nnot "\
 362                            "set correctly ?"),
 363                           ("Printing"),
 364                           wx.OK)
 365             return
 366 
 367         else:
 368             previewFrame = wx.PreviewFrame(printPreview, None, "Print preview")
 369             previewFrame.Initialize()
 370             previewFrame.SetPosition(self.GetPosition())
 371             previewFrame.SetSize(self.GetSize())
 372             # Or full screen :
 373             # previewFrame.Maximize()
 374             previewFrame.Show(True)
 375             previewFrame.Layout()
 376 
 377 
 378     def OnBtnPrint(self, event):
 379         """
 380         Prints the document.
 381         """
 382 
 383         text = self.tc.GetValue()
 384 
 385         #------------
 386 
 387         pdd = wx.PrintDialogData(self.printdata)
 388         pdd.SetPrintData(self.printdata)
 389         pdd.SetMinPage(1)
 390         pdd.SetMaxPage(1)
 391         pdd.SetFromPage(1)
 392         pdd.SetToPage(1)
 393         pdd.SetPrintToFile(False)
 394         # pdd.SetSetupDialog(False)
 395         # pdd.EnableSelection(True)
 396         # pdd.EnablePrintToFile(True)
 397         # pdd.EnablePageNumbers(True)
 398         # pdd.SetAllPages(True)
 399 
 400         #------------
 401 
 402         printer = wx.Printer(pdd)
 403 
 404         myPrintout = My_Printout(text, "- My printing object")
 405 
 406         if not printer.Print(self, myPrintout, True):
 407             wx.MessageBox(("There was a problem printing.\nPerhaps "\
 408                            "your current printer is \nnot "\
 409                            "set correctly ?"),
 410                           ("Printing"),
 411                           wx.OK)
 412             return
 413 
 414         else:
 415             self.printData = wx.PrintData(printer.GetPrintDialogData().GetPrintData())
 416         myPrintout.Destroy()
 417 
 418 
 419     def OnBtnClose(self, event):
 420         """
 421         ...
 422         """
 423 
 424         self.Close(True)
 425 
 426 
 427     def OnCloseWindow(self, event):
 428         """
 429         ...
 430         """
 431 
 432         self.Destroy()
 433 
 434 #-------------------------------------------------------------------------------
 435 
 436 class My_App(wx.App):
 437     """
 438     ...
 439     """
 440     def OnInit(self):
 441 
 442         #------------
 443 
 444         self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
 445 
 446         #------------
 447 
 448         frame = My_Frame(None, id=-1)
 449         self.SetTopWindow(frame)
 450         frame.Show(True)
 451 
 452         return True
 453 
 454 
 455 #-------------------------------------------------------------------------------
 456 
 457 def main():
 458     app = My_App(False)
 459     app.MainLoop()
 460 
 461 #-------------------------------------------------------------------------------
 462 
 463 if __name__ == "__main__" :
 464     main()


Canvas and printout class

img_sample_three.png

   1 # sample_three.py
   2 
   3 import sys
   4 import os
   5 import platform
   6 import time
   7 import wx
   8 
   9 # class My_Canvas
  10 # class My_Printout
  11 # class My_Frame
  12 # class My_App
  13 
  14 # There are two different approaches to drawing, buffered or direct.
  15 # This sample shows both approaches so you can easily compare and
  16 # contrast the two by changing this value :
  17 BUFFERED = 1
  18 
  19 #-------------------------------------------------------------------------------
  20 
  21 if os.name == "posix":
  22     print("\nPlatform : UNIX - Linux")
  23 elif os.name in ['nt', 'dos', 'ce']:
  24     print("\nPlatform : Windows")
  25 else:
  26     print("\nPlatform : ", platform.system())
  27 
  28 #-------------------------------------------------------------------------------
  29 
  30 class My_Canvas(wx.ScrolledWindow):
  31     """
  32     ...
  33     """
  34     def __init__(self, parent, id=-1, size=wx.DefaultSize):
  35         wx.ScrolledWindow.__init__(self,
  36                                    parent,
  37                                    id,
  38                                    pos=(0, 0),
  39                                    size=size,
  40                                    style=wx.SUNKEN_BORDER)
  41 
  42         #------------
  43 
  44         self.maxWidth  = 1000
  45         self.maxHeight = 1000
  46         self.x = self.y = 0
  47         self.drawing = False
  48 
  49         #------------
  50 
  51         self.SetVirtualSize((self.maxWidth, self.maxHeight))
  52         self.SetScrollRate(30, 30)
  53 
  54         #------------
  55 
  56         if BUFFERED:
  57             # Initialize the buffer bitmap.  No real DC is needed at this point
  58             self.buffer = wx.Bitmap(self.maxWidth, self.maxHeight)
  59             dc = wx.BufferedDC(None, self.buffer)
  60             dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
  61             dc.Clear()
  62             self.DoDrawing(dc)
  63 
  64         #------------
  65 
  66         # Bind a paint event to an events handler
  67         self.Bind(wx.EVT_PAINT, self.OnPaint)
  68 
  69     #---------------------------------------------------------------------------
  70 
  71     def GetWidth(self):
  72         """
  73         ...
  74         """
  75 
  76         return self.maxWidth
  77 
  78 
  79     def GetHeight(self):
  80         """
  81         ...
  82         """
  83 
  84         return self.maxHeight
  85 
  86 
  87     def OnPaint(self, event):
  88         """
  89         ...
  90         """
  91 
  92         if BUFFERED:
  93             # Create a buffered paint DC.  It will create the real
  94             # wx.PaintDC and then blit the bitmap to it when dc is
  95             # deleted.  Since we don't need to draw anything else
  96             # here that's all there is to it.
  97             dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)
  98         else:
  99             dc = wx.PaintDC(self)
 100             self.PrepareDC(dc)
 101             # Since we're not buffering in this case, we have to
 102             # (re)paint the all the contents of the window, which can
 103             # be potentially time consuming and flickery depending on
 104             # what is being drawn and how much of it there is.
 105             self.DoDrawing(dc)
 106 
 107 
 108     def DoDrawing(self, dc, printing=False):
 109         """
 110         ...
 111         """
 112 
 113         # Draw.
 114         pen = wx.Pen("BLACK", 4, wx.SOLID)
 115 
 116         dc.SetPen(wx.TRANSPARENT_PEN)
 117         dc.SetBrush(wx.Brush("#e0f0f0"))
 118 
 119         for i in range(56, 784, 56):
 120             dc.DrawRectangle(0,  i, 794, 28)
 121 
 122         pen.SetCap(wx.CAP_BUTT)
 123         dc.SetPen(pen)
 124         dc.DrawLine(397, 56, 397, 756)
 125 
 126         pen.SetCap(wx.CAP_BUTT)
 127         dc.SetPen(pen)
 128         dc.DrawLine(0, 756, 794, 756)
 129 
 130         pen.SetCap(wx.CAP_BUTT)
 131         dc.SetPen(pen)
 132         dc.DrawLine(0, 56, 794, 56)
 133 
 134         dc.SetTextForeground("BLACK")
 135         dc.SetFont(wx.Font(24, wx.DEFAULT, wx.NORMAL, wx.BOLD))
 136         dc.DrawText("Python", 15, 8)
 137 
 138         pen.SetJoin(wx.JOIN_MITER)
 139         dc.SetPen(pen)
 140         dc.SetBrush(wx.TRANSPARENT_BRUSH)
 141         dc.DrawRectangle(0, 0, 794, 794)
 142 
 143         dc.SetPen(wx.Pen("RED", 1))
 144         dc.DrawRectangle(0, 0, 1000, 1000)
 145 
 146 #-------------------------------------------------------------------------------
 147 
 148 class My_Printout(wx.Printout):
 149     """
 150     Create a printout.
 151     """
 152     def __init__(self, canvas, text, title):
 153         wx.Printout.__init__(self, title)
 154 
 155         #------------
 156 
 157         self.canvas = canvas
 158         self.lines = text
 159 
 160     #---------------------------------------------------------------------------
 161 
 162     def OnBeginDocument(self, start, end):
 163         """
 164         ...
 165         """
 166 
 167         return super(My_Printout, self).OnBeginDocument(start, end)
 168 
 169 
 170     def OnEndDocument(self):
 171         """
 172         ...
 173         """
 174 
 175         super(My_Printout, self).OnEndDocument()
 176 
 177 
 178     def OnBeginPrinting(self):
 179         """
 180         ...
 181         """
 182 
 183         super(My_Printout, self).OnBeginPrinting()
 184 
 185 
 186     def OnEndPrinting(self):
 187         """
 188         ...
 189         """
 190 
 191         super(My_Printout, self).OnEndPrinting()
 192 
 193 
 194     def OnPreparePrinting(self):
 195         """
 196         ...
 197         """
 198 
 199         super(My_Printout, self).OnPreparePrinting()
 200 
 201 
 202     def HasPage(self, page):
 203         """
 204         ...
 205         """
 206 
 207         if page <= 2:
 208             return True
 209         else:
 210             return False
 211 
 212 
 213     def GetPageInfo(self):
 214         """
 215         ...
 216         """
 217 
 218         return (1, 2, 1, 2)
 219 
 220 
 221     def OnPrintPage(self, page):
 222         """
 223         ...
 224         """
 225 
 226         dc = self.GetDC()
 227 
 228         # (wx.MM_METRIC) ---> Each logical unit is 1 mm.
 229         # (wx.MM_POINTS) ---> Each logical unit is a "printer point" i.e.
 230         # dc.SetMapMode(wx.MM_POINTS)
 231 
 232         #------------
 233 
 234         # One possible method of setting scaling factors...
 235         maxX = self.canvas.GetWidth()
 236         maxY = self.canvas.GetHeight()
 237 
 238         #------------
 239 
 240         # Let's have at least 50 device units margin.
 241         marginX = 180
 242         marginY = 180
 243 
 244         #------------
 245 
 246         # Add the margin to the graphic size.
 247         maxX = maxX + (2 * marginX)
 248         maxY = maxY + (2 * marginY)
 249 
 250         #------------
 251 
 252         # Get the size of the DC in pixels.
 253         # (w, h) = dc.GetSizeTuple()
 254         (w, h) = dc.GetSize()
 255 
 256         # Calculate a suitable scaling factor.
 257         scaleX = float(w) / maxX
 258         scaleY = float(h) / maxY
 259 
 260         # Use x or y scaling factor, whichever fits on the DC.
 261         actualScale = min(scaleX, scaleY)
 262 
 263         # Calculate the position on the DC for centering the graphic.
 264         posX = (w - (self.canvas.GetWidth() * actualScale)) / 2.0
 265         posY = (h - (self.canvas.GetHeight() * actualScale)) / 2.0
 266 
 267         # Set the scale and origin.
 268         dc.SetUserScale(actualScale, actualScale)
 269         dc.SetDeviceOrigin(int(posX), int(posY))
 270 
 271         #------------
 272 
 273         self.canvas.DoDrawing(dc, True)
 274 
 275         #------------
 276 
 277         # Draw.
 278         dc.SetTextForeground("RED")
 279         dc.SetFont(wx.Font(17, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
 280         dc.DrawText(self.lines, 6, 57)
 281         dc.DrawText(self.lines, 6, 85)
 282         dc.DrawText(self.lines, 6, 113)
 283         dc.DrawText(self.lines, 6, 141)
 284         dc.DrawText(self.lines, 6, 169)
 285         dc.DrawText(self.lines, 6, 197)
 286 
 287         dc.SetTextForeground("GRAY")
 288         dc.SetFont(wx.Font(32, wx.DEFAULT, wx.NORMAL, wx.BOLD))
 289         dc.DrawText(("wxPython sample :"), 0, -150)
 290 
 291         dc.SetTextForeground("BLACK")
 292         dc.SetFont(wx.Font(18, wx.DEFAULT, wx.NORMAL, wx.BOLD))
 293         dc.DrawText(("Page : %d") % page, int(marginX/2), int(maxY-marginY))
 294 
 295         tm = time.strftime(("Printing %a, %d %b %Y - %Hh%M"))
 296 
 297         dc.SetTextForeground("GRAY")
 298         dc.SetFont(wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
 299         dc.DrawText(tm, 10, 764)
 300 
 301         return True
 302 
 303 #-------------------------------------------------------------------------------
 304 
 305 class My_Frame(wx.Frame):
 306     """
 307     Create a main frame for my application.
 308     """
 309     def __init__(self, parent, id, title=""):
 310         wx.Frame.__init__(self,
 311                           parent,
 312                           id,
 313                           title,
 314                           size=(600, 367),
 315                           style=wx.DEFAULT_FRAME_STYLE)
 316 
 317         #------------
 318 
 319         # Simplified init method.
 320         self.SetProperties()
 321         self.CreateMenu()
 322         self.CreateCtrls()
 323         self.CreatePrintData()
 324         self.BindEvents()
 325         self.DoLayout()
 326 
 327         #------------
 328 
 329         self.CenterOnScreen()
 330 
 331     #---------------------------------------------------------------------------
 332 
 333     def SetProperties(self):
 334         """
 335         Set the main frame properties (title, icon...).
 336         """
 337 
 338         frameicon = wx.Icon("Icons/wxWidgets.ico")
 339         self.SetIcon(frameicon)
 340 
 341         #------------
 342 
 343         self.SetTitle("Printing test...")
 344 
 345 
 346     def CreateMenu(self):
 347         """
 348         Make the frame menus.
 349         """
 350 
 351         menub = wx.MenuBar()
 352 
 353         fmenu = wx.Menu()
 354         fmenu.Append(wx.ID_PAGE_SETUP, "Page set&up\tCtrl+U")
 355         fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
 356         fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
 357         fmenu.AppendSeparator()
 358         fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
 359         menub.Append(fmenu, "&File")
 360 
 361         self.SetMenuBar(menub)
 362 
 363 
 364     def CreateCtrls(self):
 365         """
 366         Make widgets for my app.
 367         """
 368 
 369         font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
 370         font.SetWeight(wx.BOLD)
 371         font.SetPointSize(10)
 372 
 373         #------------
 374 
 375         # First create the controls.
 376         self.panel = wx.Panel(self,
 377                               id=-1,
 378                               style=wx.BORDER_THEME|
 379                               wx.TAB_TRAVERSAL)
 380 
 381         self.text = wx.StaticText(self.panel,
 382                                   id=-1,
 383                                   label="Demonstrating :")
 384         self.text.SetFont(font)
 385 
 386         self.info = wx.StaticText(self.panel,
 387                                   id=-1,
 388                                   label="1) Direct printing,\n"
 389                                         "2) Printout class,\n"
 390                                         "3) Canvas class,\n"
 391                                         "4) Preview,\n"
 392                                         "5) Menu,\n"
 393                                         "6) Page setup.")
 394         self.info.SetForegroundColour("red")
 395         font.SetWeight(wx.NORMAL)
 396         self.info.SetFont(font)
 397 
 398         self.tc = wx.TextCtrl(self.panel,
 399                               id=-1,
 400                               size=(200, -1),
 401                               value="Hello, World ! A sample text.")
 402 
 403         self.canvas = My_Canvas(self.panel, size=(0, 0))
 404 
 405         self.btnSetup = wx.Button(self.panel,
 406                                   id=wx.ID_PAGE_SETUP,
 407                                   label="Page set&up")
 408 
 409         self.btnPreview = wx.Button(self.panel,
 410                                     id=wx.ID_PREVIEW,
 411                                     label="Print pre&view")
 412         self.btnPreview.SetFocus()
 413 
 414         self.btnPrint = wx.Button(self.panel,
 415                                   id=wx.ID_PRINT,
 416                                   label="&Print")
 417 
 418         self.btnClose = wx.Button(self.panel,
 419                                   id=wx.ID_CLOSE,
 420                                   label="E&xit")
 421 
 422 
 423     def CreatePrintData(self):
 424         """
 425         Create printing data.
 426         """
 427 
 428         self.printdata = wx.PrintData()
 429 
 430         self.printdata.SetPrinterName('')
 431         self.printdata.SetOrientation(wx.PORTRAIT)
 432         self.printdata.SetPaperId(wx.PAPER_A4)
 433         self.printdata.SetQuality(wx.PRINT_QUALITY_DRAFT)
 434         # Black and white printing if False.
 435         self.printdata.SetColour(True)
 436         self.printdata.SetNoCopies(1)
 437         self.printdata.SetCollate(True)
 438         # self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
 439 
 440 
 441     def BindEvents(self):
 442         """
 443         Bind all the events related to my application.
 444         """
 445 
 446         # Bind some menu events to an events handler.
 447         self.Bind(wx.EVT_MENU, self.OnBtnPageSetup, id=wx.ID_PAGE_SETUP)
 448         self.Bind(wx.EVT_MENU, self.OnBtnPreview, id=wx.ID_PREVIEW)
 449         self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
 450         self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
 451 
 452         # Bind the close event to an event handler.
 453         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 454 
 455         # Bind some buttons events to an events handler.
 456         self.Bind(wx.EVT_BUTTON, self.OnBtnPageSetup, self.btnSetup)
 457         self.Bind(wx.EVT_BUTTON, self.OnBtnPreview, self.btnPreview)
 458         self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
 459         self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
 460 
 461 
 462     def DoLayout(self):
 463         """
 464         Manage widgets Layout.
 465         """
 466 
 467         # MainSizer is the top-level one that manages everything.
 468         mainSizer = wx.BoxSizer(wx.VERTICAL)
 469 
 470         #------------
 471 
 472         hBox1 = wx.BoxSizer(wx.HORIZONTAL)
 473         hBox1.Add(self.info, 0, wx.ALL, 15)
 474 
 475         #------------
 476 
 477         hBox2 = wx.BoxSizer(wx.HORIZONTAL)
 478         hBox2.Add(self.btnSetup, 0, wx.ALL, 10)
 479         hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
 480         hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
 481         hBox2.Add(self.btnClose, 0, wx.ALL, 10)
 482 
 483         #------------
 484 
 485         mainSizer.Add(self.text, 0, wx.ALL, 10)
 486         mainSizer.Add(wx.StaticLine(self.panel),
 487                       0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
 488         mainSizer.Add(self.tc, 0, wx.ALL, 15)
 489         mainSizer.Add(hBox1, 0, wx.ALL, 5)
 490         mainSizer.Add(hBox2, 0, wx.ALL, 5)
 491 
 492         #------------
 493 
 494         # Finally, tell the panel to use the mainSizer for layout.
 495         self.panel.SetSizer(mainSizer)
 496 
 497 
 498     def OnBtnPageSetup(self, event):
 499         """
 500         Show the PrinterSetup dialog.
 501         """
 502 
 503         psdd = wx.PageSetupDialogData(self.printdata)
 504 
 505         psdd.EnablePrinter(True)
 506         # psdd.CalculatePaperSizeFromId()
 507 
 508         #------------
 509 
 510         dlg = wx.PageSetupDialog(self, psdd)
 511         dlg.ShowModal()
 512 
 513         #------------
 514 
 515         # This makes a copy of the wx.PrintData instead of just saving
 516         # a reference to the one inside the PrintDialogData that will
 517         # be destroyed when the dialog is destroyed
 518         self.printdata = wx.PrintData(dlg.GetPageSetupData().GetPrintData())
 519 
 520         dlg.Destroy()
 521 
 522 
 523     def OnBtnPreview(self, event):
 524         """
 525         Show the print preview.
 526         """
 527 
 528         text = self.tc.GetValue()
 529 
 530         #------------
 531 
 532         data = wx.PrintDialogData(self.printdata)
 533 
 534         printout1 = My_Printout(self.canvas, text, "- My printing object")
 535         printout2 = My_Printout(self.canvas, text, "- My printing object")
 536 
 537         printPreview = wx.PrintPreview(printout1, printout2, data)
 538 
 539         # Initial zoom value.
 540         if "__WXMAC__" in wx.PlatformInfo:
 541             printPreview.SetZoom(50)
 542         else:
 543             printPreview.SetZoom(35)
 544 
 545         if not printPreview.IsOk():
 546             wx.MessageBox(("There was a problem printing.\nPerhaps "\
 547                            "your current printer is \nnot "\
 548                            "set correctly ?"),
 549                           ("Printing"),
 550                           wx.OK)
 551             return
 552 
 553         else:
 554             previewFrame = wx.PreviewFrame(printPreview, None, "Print preview")
 555             previewFrame.Initialize()
 556             previewFrame.SetPosition(self.GetPosition())
 557             previewFrame.SetSize(self.GetSize())
 558             # Or full screen :
 559             # previewFrame.Maximize()
 560             previewFrame.Show(True)
 561             previewFrame.Layout()
 562 
 563 
 564     def OnBtnPrint(self, event):
 565         """
 566         Prints the document.
 567         """
 568 
 569         text = self.tc.GetValue()
 570 
 571         #------------
 572 
 573         pdd = wx.PrintDialogData(self.printdata)
 574         pdd.SetPrintData(self.printdata)
 575         pdd.SetMinPage(1)
 576         pdd.SetMaxPage(1)
 577         pdd.SetFromPage(1)
 578         pdd.SetToPage(1)
 579         pdd.SetPrintToFile(False)
 580         # pdd.SetSetupDialog(False)
 581         # pdd.EnableSelection(True)
 582         # pdd.EnablePrintToFile(True)
 583         # pdd.EnablePageNumbers(True)
 584         # pdd.SetAllPages(True)
 585 
 586         #------------
 587 
 588         printer = wx.Printer(pdd)
 589 
 590         myPrintout = My_Printout(self.canvas, text, "- My printing object")
 591 
 592         if not printer.Print(self, myPrintout, True):
 593             wx.MessageBox(("There was a problem printing.\nPerhaps "\
 594                            "your current printer is \nnot "\
 595                            "set correctly ?"),
 596                           ("Printing"),
 597                           wx.OK)
 598             return
 599 
 600         else:
 601             self.printData = wx.PrintData(printer.GetPrintDialogData().GetPrintData())
 602         myPrintout.Destroy()
 603 
 604 
 605     def OnBtnClose(self, event):
 606         """
 607         ...
 608         """
 609 
 610         self.Close(True)
 611 
 612 
 613     def OnCloseWindow(self, event):
 614         """
 615         ...
 616         """
 617 
 618         self.Destroy()
 619 
 620 #-------------------------------------------------------------------------------
 621 
 622 class My_App(wx.App):
 623     """
 624     ...
 625     """
 626     def OnInit(self):
 627 
 628         #------------
 629 
 630         self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
 631 
 632         #------------
 633 
 634         frame = My_Frame(None, id=-1)
 635         self.SetTopWindow(frame)
 636         frame.Show(True)
 637 
 638         return True
 639 
 640 #-------------------------------------------------------------------------------
 641 
 642 def main():
 643     app = My_App(False)
 644     app.MainLoop()
 645 
 646 #-------------------------------------------------------------------------------
 647 
 648 if __name__ == "__main__" :
 649     main()


Download source

source.zip


Additional Information

Link :

https://wiki.wxpython.org/MoreCommentsOnPrinting

https://wiki.wxpython.org/PrintingWithReportGenerators

http://www.blog.pythonlibrary.org/2012/06/17/an-intro-to-rst2pdf-changing-restructured-text-into-pdfs-with-python/

http://www.blog.pythonlibrary.org/2010/05/15/manipulating-pdfs-with-python-and-pypdf/

https://www.blog.pythonlibrary.org/2010/02/14/python-windows-and-printers/

- - - - -

https://wiki.wxpython.org/TitleIndex

https://docs.wxpython.org/


Thanks to

Lorne White, Jeff Grimmett, Vernon Cole, Robin Dunn, Andy Robinson / Robin Becker / The ReportLab team, David Hughe (PDFViewer), Ruikai Liu / Jorj X. McKie (PyMuPDF), Cody Precord, Mike Driscoll, Pascal Faut., Dietmar Schwertberger, Chris Barker, the wxPython community...

Thanks also to all known contributors or anonymous that I forgot.

And finally, congratulations to the many forums and blogs for all the available examples and the help which is the strength of wxPython. ;)


About this page

Date (d/m/y) Person (bot) Comments :

00/00/00 - Sean McKay (originally Created).

10/10/18 - Ecco (Updated page and published examples for wxPython Phoenix).


Comments

- blah, blah, blah....

Printing framework - Part 1 (Phoenix) (last edited 2020-10-07 10:34:37 by Ecco)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.