第17章 wxPython的打印构架

本章内容

  • wxPython打印

  • 创建和显示打印对话框
  • 创建和显示页面设置对话框
  • 在你的程序中执行打印
  • 执行一个打印预览

在第16章中,我们已经关注了wxPython的一打印方法:使用wx.HtmlEasyPrinting。如果你用该方法打印HTML(或某些容易转换为HTML的文件)的话,这个方法将会工作的很好,但是要作为一个完善打印办法还是不够的。在wxPython中还有一个更为通用的打印构架,你可以用它来打印你想打印的任何东西。基本上,该构架使你能够使用设备上下文和绘制操作来执行打印。你也可以创建打印预览。

本章将讨论该构架中最重要的类:wx.Printout,它管理实际的图片部分。打印输出实例可以由一个代表打印机的wx.Printer对象或用于打印预览的wx.PrintPreview对象来管理。多们也将讨论几个管理与打印相关的数据的类,以及用来显示信息给用户的对话框。

1. 如何用wxPython打印?

我们将以类wx.Printout作为开始。首先你要创建你自定义的wx.Printout的子类。接着你要覆盖wx.Printout的方法以定义你自定义的打印行为。wx.Printout有7个你可以覆盖以自定义打印行为的方法。这些方法在一个打印会话过程期间被wxPython自动调用。图17.1其中的六个方法,它们被特定的事件触发。在大多数情况下,你不需要全部覆盖它们。

图17.1

1.1. 理解打印输出的生命周期

你通过创建一个你的打印输出对象的实例和一个类wx.Printer的实例启动一个打印会话:

wx.Printer(data=None)

可选的data参数是wx.PrintDialogData的一个实例。要开始实际的打印,需要调用wx.PrinterPrint(parent, printout, prompt=True)方法。参数parent是父窗口(它被用作对话框的窗口中)。参数printout是你的wx.Printout实例。如果参数promptTrue,那么在打印之前,wxPython将显示打印对话框,否则不显示。

Print()方法开始后,它调用wx.Printout的第一个可被覆盖的方法OnPreparePrint()OnPreparePrint()方法在wx.Printout实例做任何其它的事之前被确保调用,因此该方法是放置收集你的数据或做那些必须在打印开始之前所要做的计算的一个好的地方。实际的打印使用OnBeginPrinting()方法开始,你可以对该方法进行覆盖,以自定主你想要的行为——默认情况下,该方法什么也不做。OnBeginPrinting()在整个打印会话中只会被调用一次。

你希望打印的文档的每个单独的拷贝触发对OnBeginDocument(startPage, endPage)的一个调用,其中参数startPage, endPage告诉wxPython打印的起始页和最后一页。这两个参数都应该指定。如果你想覆盖这个方法,那么你必须调用它的基类的方法,因为基类的方法要做一些重要的工作(如调用wx.DC.StartDoc())。在wxPython中,你可以使用base_OnBeginDocument(startPage, endPage)来调用其父类的方法。如果OnBeginDocument返回False,那么将取消打印工作。

你最有可能去覆盖的方法是OnPrintPage(pageNum),该方法是你放置关于每一页的绘制命令的地方。参数pageNum是要打印的页的页码。在这个方法中,你调用GetDC()GetDC()根据你当前的系统平台返回一个适当的设备上下文。对于实际的打印,如果你是在一个微软的Windows系统上的话,那么GetDC()返回的是类wx.PrinterDC的实例。对于其它的系统,返回的是类wx.PostScriptDC的实例。如果你是处在一个打印预览操作中,那么对于任何的操作系统,GetDC()返回的都是一个wx.MemoryDC。一旦你有了设备上下文,你就可以做你想做的设备上下文绘制操作,并且它们将被打印或预览。

在一个文档的副本打印结束后,一个OnEndDocument()调用被触发。另外,如果你要覆盖OnEndDocument()方法,那么你必须调用其基类的方法base_OnEndDocument()base_OnEndDocument()将调用wx.DC.EndDoc()方法。当你的所有的副本被打印完后,OnEndPrinting()方法被调用,这样就结束了打印会话。

wx.Printout还有另一个可被覆盖的方法:HasPage(pageNum)。该方法通常需要被覆盖,它被打印架构用于循环控制。如果参数pageNum存在于文档中,那么该方法返回True,否则返回False

1.2. 实战打印构架

下面我们将通过一个例子来展示打印构架实际上是如何工作的。这个例子由一个简单的用于打印文本文件的构架组成,并且应用程序让你能够键入简单的文本。图17.2显示了这个应用程序的结果。

图17.1

例17.1显示了我们已经讨论过的打印构架和我们将要接触的打印对话框机制。

例17.1 打印构架的一个较长的例子

   1 import wx
   2 import os
   3 
   4 FONTSIZE = 10
   5 
   6 class TextDocPrintout(wx.Printout):
   7     """
   8     A printout class that is able to print simple text documents.
   9     Does not handle page numbers o titles, and it assumes that no
  10     lines are longer than what will fit within the page width.  Those
  11     features are left as an exercise for the reader. ;-)
  12     """
  13     def __init__(self, text, title, margins):
  14         wx.Printout.__init__(self, title)
  15         self.lines = text.split('\n')
  16         self.margins = margins
  17 
  18 
  19     def HasPage(self, page):
  20         return page  = self.numPages
  21 
  22     def GetPageInfo(self):
  23         return (1, self.numPages, 1, self.numPages)
  24 
  25 
  26     def CalculateScale(self, dc):
  27         # Scale the DC such that the printout is roughly the same as
  28         # the screen scaling.
  29         ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
  30         ppiScreenX, ppiScreenY = self.GetPPIScreen()
  31         logScale = float(ppiPrinterX)/float(ppiScreenX)
  32 
  33         # Now adjust if the real page size is reduced (such as when
  34         # drawing on a scaled wx.MemoryDC in the Print Preview.)  If
  35         # page width == DC width then nothing changes, otherwise we
  36         # scale down for the DC.
  37         pw, ph = self.GetPageSizePixels()
  38         dw, dh = dc.GetSize()
  39         scale = logScale * float(dw)/float(pw)
  40 
  41         # Set the DC's scale.
  42         dc.SetUserScale(scale, scale)
  43 
  44         # Find the logical units per millimeter (for calculating the
  45         # margins)
  46         self.logUnitsMM = float(ppiPrinterX)/(logScale*25.4)
  47 
  48 
  49     def CalculateLayout(self, dc):
  50         # Determine the position of the margins and the
  51         # page/line height
  52         topLeft, bottomRight = self.margins
  53         dw, dh = dc.GetSize()
  54         self.x1 = topLeft.x * self.logUnitsMM
  55         self.y1 = topLeft.y * self.logUnitsMM
  56         self.x2 = dc.DeviceToLogicalXRel(dw) - bottomRight.x * self.logUnitsMM
  57         self.y2 = dc.DeviceToLogicalYRel(dh) - bottomRight.y * self.logUnitsMM
  58 
  59         # use a 1mm buffer around the inside of the box, and a few
  60         # pixels between each line
  61         self.pageHeight = self.y2 - self.y1 - 2*self.logUnitsMM
  62         font = wx.Font(FONTSIZE, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
  63         dc.SetFont(font)
  64         self.lineHeight = dc.GetCharHeight()
  65         self.linesPerPage = int(self.pageHeight/self.lineHeight)
  66 
  67 
  68     def OnPreparePrinting(self):
  69         # calculate the number of pages
  70         dc = self.GetDC()
  71         self.CalculateScale(dc)
  72         self.CalculateLayout(dc)
  73         self.numPages = len(self.lines) / self.linesPerPage
  74         if len(self.lines) % self.linesPerPage != 0:
  75             self.numPages += 1
  76 
  77 
  78     def OnPrintPage(self, page):
  79         dc = self.GetDC()
  80         self.CalculateScale(dc)
  81         self.CalculateLayout(dc)
  82 
  83         # draw a page outline at the margin points
  84         dc.SetPen(wx.Pen("black", 0))
  85         dc.SetBrush(wx.TRANSPARENT_BRUSH)
  86         r = wx.RectPP((self.x1, self.y1),
  87                       (self.x2, self.y2))
  88         dc.DrawRectangleRect(r)
  89         dc.SetClippingRect(r)
  90 
  91         # Draw the text lines for this page
  92         line = (page-1) * self.linesPerPage
  93         x = self.x1 + self.logUnitsMM
  94         y = self.y1 + self.logUnitsMM
  95         while line   (page * self.linesPerPage):
  96             dc.DrawText(self.lines[line], x, y)
  97             y += self.lineHeight
  98             line += 1
  99             if line  = len(self.lines):
 100                 break
 101         return True
 102 
 103 
 104 class PrintFrameworkSample(wx.Frame):
 105     def __init__(self):
 106         wx.Frame.__init__(self, None, size=(640, 480),
 107                           title="Print Framework Sample")
 108         self.CreateStatusBar()
 109 
 110         # A text widget to display the doc and let it be edited
 111         self.tc = wx.TextCtrl(self, -1, "",
 112                               style=wx.TE_MULTILINE|wx.TE_DONTWRAP)
 113         self.tc.SetFont(wx.Font(FONTSIZE, wx.TELETYPE, wx.NORMAL, wx.NORMAL))
 114         filename = os.path.join(os.path.dirname(__file__), "sample-text.txt")
 115         self.tc.SetValue(open(filename).read())
 116         self.tc.Bind(wx.EVT_SET_FOCUS, self.OnClearSelection)
 117         wx.CallAfter(self.tc.SetInsertionPoint, 0)
 118 
 119         # Create the menu and menubar
 120         menu = wx.Menu()
 121         item = menu.Append(-1, "Page Setup...\tF5",
 122                            "Set up page margins and etc.")
 123         self.Bind(wx.EVT_MENU, self.OnPageSetup, item)
 124         item = menu.Append(-1, "Print Setup...\tF6",
 125                            "Set up the printer options, etc.")
 126         self.Bind(wx.EVT_MENU, self.OnPrintSetup, item)
 127         item = menu.Append(-1, "Print Preview...\tF7",
 128                            "View the printout on-screen")
 129         self.Bind(wx.EVT_MENU, self.OnPrintPreview, item)
 130         item = menu.Append(-1, "Print...\tF8", "Print the document")
 131         self.Bind(wx.EVT_MENU, self.OnPrint, item)
 132         menu.AppendSeparator()
 133         item = menu.Append(-1, "E ", "Close this application")
 134         self.Bind(wx.EVT_MENU, self.OnExit, item)
 135 
 136         menubar = wx.MenuBar()
 137         menubar.Append(menu, " ")
 138         self.SetMenuBar(menubar)
 139 
 140         # initialize the print data and set some default values
 141         self.pdata = wx.PrintData()
 142         self.pdata.SetPaperId(wx.PAPER_LETTER)
 143         self.pdata.SetOrientation(wx.PORTRAIT)
 144         self.margins = (wx.Point(15,15), wx.Point(15,15))
 145 
 146 
 147     def OnExit(self, evt):
 148         self.Close()
 149 
 150 
 151     def OnClearSelection(self, evt):
 152         evt.Skip()
 153         wx.CallAfter(self.tc.SetInsertionPoint,
 154                      self.tc.GetInsertionPoint())
 155 
 156 
 157     def OnPageSetup(self, evt):
 158         data = wx.PageSetupDialogData()
 159         data.SetPrintData(self.pdata)
 160 
 161         data.SetDefaultMinMargins(True)
 162         data.SetMarginTopLeft(self.margins[0])
 163         data.SetMarginBottomRight(self.margins[1])
 164 
 165         dlg = wx.PageSetupDialog(self, data)
 166         if dlg.ShowModal() == wx.ID_OK:
 167             data = dlg.GetPageSetupData()
 168             self.pdata = wx.PrintData(data.GetPrintData()) # force a copy
 169             self.pdata.SetPaperId(data.GetPaperId())
 170             self.margins = (data.GetMarginTopLeft(),
 171                             data.GetMarginBottomRight())
 172         dlg.Destroy()
 173 
 174 
 175     def OnPrintSetup(self, evt):
 176         data = wx.PrintDialogData(self.pdata)
 177         dlg = wx.PrintDialog(self, data)
 178         dlg.GetPrintDialogData().SetSetupDialog(True)
 179         dlg.ShowModal();
 180         data = dlg.GetPrintDialogData()
 181         self.pdata = wx.PrintData(data.GetPrintData()) # force a copy
 182         dlg.Destroy()
 183 
 184 
 185     def OnPrintPreview(self, evt):
 186         data = wx.PrintDialogData(self.pdata)
 187         text = self.tc.GetValue()
 188         printout1 = TextDocPrintout(text, "title", self.margins)
 189         printout2 = None #TextDocPrintout(text, "title", self.margins)
 190         preview = wx.PrintPreview(printout1, printout2, data)
 191         if not preview.Ok():
 192             wx.MessageBox("Unable to create PrintPreview!", "Error")
 193         else:
 194             # create the preview frame such that it overlays the app frame
 195             frame = wx.PreviewFrame(preview, self, "Print Preview",
 196                                     pos=self.GetPosition(),
 197                                     size=self.GetSize())
 198             frame.Initialize()
 199             frame.Show()
 200 
 201 
 202     def OnPrint(self, evt):
 203         data = wx.PrintDialogData(self.pdata)
 204         printer = wx.Printer(data)
 205         text = self.tc.GetValue()
 206         printout = TextDocPrintout(text, "title", self.margins)
 207         useSetupDialog = True
 208         if not printer.Print(self, printout, useSetupDialog) \
           and printer.GetLastError() == wx.PRINTER_ERROR:
 209             wx.MessageBox(
 210                 "There was a problem printing.\n"
 211                 "Perhaps your current printer is not set correctly?",
 212                 "Printing Error", wx.OK)
 213         else:
 214             data = printer.GetPrintDialogData()
 215             self.pdata = wx.PrintData(data.GetPrintData()) # force a copy
 216         printout.Destroy()
 217 
 218 
 219 app = wx.PySimpleApp()
 220 frm = PrintFrameworkSample()
 221 frm.Show()
 222 app.MainLoop()

例17.2中的打印输出类能够打印简单的文本文档,但是不能处理页码或标题,并且它创假设了行的宽度没有超过页面的宽度。对于例子的完善就留给读者作为一个练习。

上面最重要的代码片断是在构架的OnPreparePrinting()OnPrintPage()以及示例窗口的OnPrint()方法中。

1.3. 使用wx.Printout的方法工作

wx.Printout中有几个get*方法,它们使你能够获取当前打印环境的有关信息。表17.1列出了这些方法。

表17.1 wx.Printout的信息获取方法

GetDC()

该方法返回关于打印机或打印预览的用于绘制文档的设备上下文。

GetPageInfo()

返回一个含有四个元素的元组(minPage, maxPage, pageFrom, pageTo)minPage, maxPage分别是所允许的最小和最大页码,默认是1和32000。pageFrom, pageTo是必须被打印的范围,默认为1。你可以在你的子类中覆盖这个方法。

GetPageSizeMM()

返回包含一个页面的宽度和高度的一个(w, h)元组,以毫米为单位。

GetPageSizePixels()

返回一个页面的宽度和高度的一个(w, h)元组,以像素为单位。如果打印输出被用于打印预览,那么像素数将反应当前的缩放比列,意思就是说像素将会随缩放比列而变。

GetPPIPrinter()

返回当前打印机在垂直和水平方向上每英寸的像素的一个(w, h)元组。在预览中,这个值也是始终一致的,即使打印预览的缩放比列变化了。

GetPPIScreen()

返回当前屏幕在垂直和水平方向上每英寸的像素的一个(w, h)元组。在预览中,这个值也是始终一致的,即使打印预览的缩放比列变化了。

GetTitle()

返回打印输出的标题。

在后面的几节中,我们将讨论如何呈现打印对话框给用户。

2. 如何显示打印对话框?

诸如要打印那些面面,要打印多少副本这些关于打印工作的数据是由标准的打印对话框来管理的。打印对话框是与字体和颜色对话框类似的,wxPython中的打印对话框实例仅仅是对本地控件和一个储存了对话框数据的分离的数据对象的简单封装。

2.1. 创建一个打印对话框

图17.3显示了打印设置对话框的样例。

图17.3

这里的对话框是类wx.PrintDialog的一个实例,你可以使用下面的构造函数来得到:

wx.PrintDialog(parent, data=None)

其中,参数parent是对话框的父框架,参数data是一个预先存在的wx.PrintDialogData实例,它用于对话框的初始数据。

使用方法

一旦你有了打印对话框,你就可以使用标准的ShowModal()方法来显示它,ShowModal()方法将根据用户关闭对话框的方式而返回wx.ID_OKwx.ID_CANCEL。 在你关闭了对话框之后,你可以使用GetPrintDialogData()方法来得到用户输入的数据。你也可以使用GetPrintDC()方法得到与数据相关联的打印机的设备上下文,如果还没有内容被创建,那么GetPrintDC()方法返回None。例17.1中的OnPrintSetup()方法显示了实际上对话框是如何被获取的。

使用属性

这个数据对象本身有几个属性,其中的一个是对wx.PrintData类型的一个对象的引用,wx.PrintData有更多的属性。你可以使用构造函数wx.PrintDialogData()来创建你的wx.PrintDialogData对象。这使得你能够在打开对话框之前预设属性。

wx.PrintDialogData对象有四个属性用于控制打印对话框的各个部分的有效性。方法EnableHelp(enable)用于开关帮助性能。至于对话框的其它部分,EnablePageNumbers(enable)与页面数量输入框相关,EnablePrintToFile(enable)管理实际的打印按钮,EnableSelection(enable)在打印所有和仅打印被选项之间作切换。

表17.2显示了对话框数据对象的其它属性,它们使你能够管理有关打印请求的信息。

表17.2 wx.PrintDialogData的属性

GetAllPages()

如果用户选择了打印整个文档这一选项,则返回True

SetCollate(flag)

GetCollate()

如果用户选择了核对打印的页,则返回True

SetFromPage(page)

GetFromPage()

如果用户选择从某一页打印,那么方法返回打印的第一页的整数页码。

SetMaxPage(page)

GetMaxPage()

返回文档中最大的页码。

SetMinPage(page)

GetMinPage()

返回文档中最小的页码。

SetNoCopies()

GetNoCopies()

返回用户选择要打印的副本的数量。

SetPrintData(printData)

GetPrintData()

返回与对话框相关联的wx.PrintData对象。

SetPrintToFile(flag)

GetPrintToFile()

如果用户已经选择了打印到一个文件这一项,那么返回True。“打印到文件”这一机制由wxPython管理。

SetSelection(flag)

GetSelection()

如果用户已经选择了只打印当前的选择这一项,那么返回True

SetToPage(page)

GetToPage()

如果用户指定了一个范围,那么返回打印的最后一页的页码。

GetPrintData()方法返回的wx.PrintData实例提供了有关打印的更进一步的信息。通常这些信息是在你的打印对话框的打印设置子对话框中的。表17.3列出了wx.PrintData对象的属性。

表17.3 wx.PrintData的属性

SetColour(flag)

GetColour()

如果当前的打印是用于颜色打印的,那么返回True

SetDuplex(mode)

GetDuplex()

返回当前关于双面打印的设置。值可以是wx.DUPLEX_SIMPLE(非双面打印),wx.DUPLEX_HORIZONTAL(横向双面打印),wx.DUPLEX_VERTICAL(纵向双面打印)。

SetOrientation(orientation)

GetOrientation()

返回纸张的打印定位(肖像或风景)。值可以是wx.LANDSCAPEwx.PORTRAIT

SetPaperId(paperId)

GetPaperId()

返回匹配纸张类型的标识符。通常的值有wx.PAPER_LETTER, wx.PAPER_LEGAL, wx.PAPER_A4。完整的页面(纸张)ID的列表见wxWidgets文档。

SetPrinterName(printerName)

GetPrinterName()

返回被系统引用的当前打印机的名字。如果该值为空字符串,那么默认打印机被使用。

SetQuality(quality)

GetQuality()

返回打印机的当前品质值。set*方法仅接受如下取值

wx.PRINT_QUALITY_DRAFT, wx.PRINT_QUALITY_HIGH, wx.PRINT_QUALITY_MEDIUM, wx.PRINT_QUALITY_LOWget*方法将返回上面的这些值之一,或一个代表每英寸点数设置的正整数。

3. 如何显示页面设置对话框?

图17.4显示了页面设置对话框是如何让用户来设置与页面尺寸相关的数据的。

图17.4

3.1. 创建页面设置对话框

你可以通过实例化一个wx.PageSetupDialog类来创建一个页面设置对话框。

wx.PageSetupDialog(parent, data=None)

参数parent是新的对话框的父窗口。参数datawx.PageSetupDialogData的一个实例默认为None。一旦页面设置对话框被创建了,那么这个对话框的行为就和其它任何模式对话框一样,并且你可以使用ShowModal()来显示它。通常,返回值表明了用户是否是使用wx.ID_OKwx.ID_CANCEL按钮关闭的对话框窗口。在对话框关闭后,你可以通过调用GetPageSetupDialogData()来取得对数据对象的访问, GetPageSetupDialogData()返回类wx.PageSetupDialogData的一个实例。

3.2. 使用页面设置属性工作

wx.PageSetupDialogData类有几个必须与页面设置一起使用的属性。表17.4展示了控制对话框自身显示的属性。除非有其它的指定,否则所有这些属性都默认为True

表17.4 wx.PageSetupDialogData的对话框控制属性

GetDefaultMinMargins()

SetDefaultMinMargins(flag)

如果这个属性为True,并且你是在微软的Windows系统上,那么页面设置将使用默认打印机的当前属性作为默认认的最小化页边距。否则,它将使用系统默认值。

GetDefaultInfo()

SetDefaultInfo(flag)

如果这个属性为True,并且你是在微软的Windows系统上,那么这个页面设置对话框不会被显示。替而代之,当前打印机的所有默认值都将被放入数据对象。

EnableHelp(flag)

GetEnableHelp()

如果为True,那么对话框的帮助部分是有效的。

EnableMargins(flag)

GetEnableMargins()

如果为True,那么对话框的用于调整页边距的部分是有效的。

EnableOrientation(flag)

GetEnableOrientation()

如果为True,那么对话框的用于改变页面定位的部分是有效的。

EnablePaper(flag)

GetEnablePaper()

如果为True,那么对话框的用于允许用户改变页面(纸张)类型的部分是效的。

EnablePrinter(flag)

GetEnablePrinter()

如果为True,那么允许用户设置打印机的按钮是有效的。

表17.5显示了wx.PageSetupDialogData类的附加的属性,这些属性用于控制页面的边距和尺寸。

表17.5 wx.PageSetupDialogData的页边距和尺寸属性

GetMarginTopLeft()

SetMarginTopLeft(pt)

get*方法返回一个wx.Point,其中的值x是当前的左边距,y是当前的上边距。set*方法允许你使用一个wx.Point或一个Python元组来改变这些值。

GetMarginBottomRight()

SetMarginBottomRight(pt)

get*方法返回一个wx.Point,其中的值x是当前的右边距,y是当前的下边距。set*方法允许你使用一个wx.Point或一个Python元组来改变这些值。

GetMinMarginTopLeft()

SetMinMarginTopLeft(pt)

GetMarginTopLeft()中的一样,只是值是所允许的最小左边距和上边距。

GetMinMarginBottomRight()

SetMinMarginBottomRight(pt)

GetMarginBottomRight()中的一样,只是值是所允许的最小右边距和下边距。

GetPaperId()

SetPaperId(id)

返回关于当前页面类型的wxPython标识符。同wx.PrinterData的属性。

GetPaperSize()

SetPaperSize(size)

get*方法返回包含页面的水平和坚直方向尺寸的一个wx.Size实例。单位是毫米。

GetPrintData()

SetPrintData(printData)

get*方法返回与当前打印会话相关的wx.PrintData实例。

到目前为止,我们已经讨论了所有关于数据对话框的整改,下面我们将重点放在打印上面。

4. 如何打印?

到目前为止,我们已经见过了打印构架的所有部分,现是我们打印一些东西的时候了。实际的打印部分是由wx.Printer类的一个实例来控制的。与已经说明的其它部分相比,打印并不更简单。接下来,我们将对在例17.1中的OnPrint()中的步骤作介绍。

第一步 按顺序得到你的所有数据

这至少应该包括带有打印机命令的wx.Printout对象,通常也要包括一个wx.PrintDialogData实例。

第二步 创建一个wx.Printer实例

创建该实例,要使用构造器wx.Printer(data=None)。可选参数data是一个wx.PrintDialogData实例。该数据控制打印,通常,你会想使用它。

第三步 使用wx.PrinterPrint ()方法打印

Print()方法如下:

   1 Print(parent, printout, prompt=True)

其中参数parent是当打印时所触发的对话框的父窗口。printout是用于打印的wx.Printout对象。如果参数promptTrue,那么在打印之前显示打印对话框,否则将立即;启动打印。

如果打印成功,则Print()方法返回True。你能够调用GetLastError()方法来得到下列常量之一:wx.PRINTER_CANCELLED(如果失败是由于用户取消了打印所引起的),wx.PRINTER_ERROR(如果失败在打印期间由打印自身所引起的),或wx.PRINTER_NO_ERROR(如果Print()返回True且没有错误发生)。

这儿还有另外两个你可以使用一个wx.Printer实例做的事:

* 你可以使用CreateAbortWindow(parent,printout)来显示中止对话框,其中参数parentprintoutPrint()方法中的。如果用户已经中止打印任务,你能够通过调用Abort()来发现,该方法在这种情况下返回True

* 你可以使用PrintDialog(parent)来显式地显示打印对话框,并且你可以使用GetPrintDialogData()来得到活动的打印数据对象。

5. 如何实现一个打印预览?

使用设备上下文的一个好处就是很容易管理打印预览,你可以使用一个屏幕设备上下文来代替打印机设备上下文。接下来的三个部分将讨论打印预览的过程。

第一步 创建预览实例

在一个打印预览中的第一步是创建类wx.PrintPreview的一个实例,wx.PrintPreview类似wx.Printer。构造器如下:

   1 wx.PrintPreview(printout, printoutForPrinting, data=None)

其中参数printout是一个wx.Printout对象,用于管理预览。参数printoutForPrinting是另一个wx.Printout对象。如果它不是None,那么当显示的时候,该打印预览窗口包含一Print按钮,该按钮启动打印。printoutForPrinting用于实际的打印。如果参数printoutForPrintingNone,那么Print按钮不显示。当然,你可以传递同一个实例或你的自定义打印输出类的相同版本的两个实例给参数printoutprintoutForPrinting。参数data可以是一个wx.PrintData对象或一个wx.PrintDialogData对象。如果参数data指定了的话,那么它被用于控制该打印预览。在例17.1中,我们显示了一个在OnPrintPreview()方法中使用打印预览的例子。

第二步 创建预览框架

一旦你有了你的wx.PrintPreview,你就需要一框架以在其中观看你的wx.PrintPreview。该框架由类wx.PreviewFrame提供,wx.PreviewFramewx.Frame的一个子类,wx.Frame为预览提供基本的用户交互控件。wx.PreviewFrame的构造器如下:

   1 wx.PreviewFrame(preview, parent, title, pos=wx.DefaultPosition,
   2         size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,
   3         name="frame")

其中真正有意义的参数是preview,它是要被预览的wx.PrintPreview实例。其它的参数都是标准的wx.Frame中的。wx.PreviewFrame不定义任何自定义的样式或事件。

第三步 初始化框架

在你显示你的wx.PreviewFrame之前,你需要调用Initialize()方法,该方法创建窗口的内部的部件并做其它的内部的计算。一旦你Show()了该框架,那么如果你想再改变预览窗口的感观,你可以使用考虑CreateControlBar()CreateCanvas()方法,它们分别创建类wx.PreviewControlBarwx.PreviewCanvas的对象。覆盖这些方法以创建你自己的画布(canvas)和/或控制栏对象,使得你能够定制你的打印预览窗口的感观。

6. 本章小结

1、这是wxPython中的一个通用的打印构架,它不仅可以打印HTML,还可以打印任何能够被绘制到设备上下文的东西。这个架构中的主要的类是wx.Printout,但是wx.Printerwx.PrintPreview也是重要的。

2、wx.Printout类管理图形打印的细节,并且它包含几个可以被覆盖来定制打印会话期间的行为和使用的数据的方法。打印发生在OnPrintPage()方法期间。

3、用于打印机设置和页面设置的标准的对话框是可以从wxPython来访问的。打印机设置对话框是wx.PrintDialog的一个实例,页面设置对话框是wx.PageSetupDialog的一个实例。这两个对话框都有相关的数据类,数据类使你的程序可以处理所有显示在对话框中的值。

4、一旦有了数据,那么实际将数据传送给打印机则是wx.Printer类的相对简单的应用。你可以使用wx.PrintPreview类来管理一个打印预览会话,该类包括一个打印预览框架,和根据该框架指定通常打印行为的选项。