第17章 wxPython的打印构架
本章内容
用wxPython打印
- 创建和显示打印对话框
- 创建和显示页面设置对话框
- 在你的程序中执行打印
- 执行一个打印预览
在第16章中,我们已经关注了wxPython的一打印方法:使用wx.HtmlEasyPrinting。如果你用该方法打印HTML(或某些容易转换为HTML的文件)的话,这个方法将会工作的很好,但是要作为一个完善打印办法还是不够的。在wxPython中还有一个更为通用的打印构架,你可以用它来打印你想打印的任何东西。基本上,该构架使你能够使用设备上下文和绘制操作来执行打印。你也可以创建打印预览。
本章将讨论该构架中最重要的类:wx.Printout,它管理实际的图片部分。打印输出实例可以由一个代表打印机的wx.Printer对象或用于打印预览的wx.PrintPreview对象来管理。多们也将讨论几个管理与打印相关的数据的类,以及用来显示信息给用户的对话框。
如何用wxPython打印?
我们将以类wx.Printout作为开始。首先你要创建你自定义的wx.Printout的子类。接着你要覆盖wx.Printout的方法以定义你自定义的打印行为。wx.Printout有7个你可以覆盖以自定义打印行为的方法。这些方法在一个打印会话过程期间被wxPython自动调用。图17.1其中的六个方法,它们被特定的事件触发。在大多数情况下,你不需要全部覆盖它们。
图17.1
理解打印输出的生命周期
你通过创建一个你的打印输出对象的实例和一个类wx.Printer的实例启动一个打印会话:
wx.Printer(data=None)
可选的data参数是wx.PrintDialogData的一个实例。要开始实际的打印,需要调用wx.Printer的Print(parent, printout, prompt=True)方法。参数parent是父窗口(它被用作对话框的窗口中)。参数printout是你的wx.Printout实例。如果参数prompt为True,那么在打印之前,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。
实战打印构架
下面我们将通过一个例子来展示打印构架实际上是如何工作的。这个例子由一个简单的用于打印文本文件的构架组成,并且应用程序让你能够键入简单的文本。图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) \
209 and printer.GetLastError() == wx.PRINTER_ERROR:
210 wx.MessageBox(
211 "There was a problem printing.\n"
212 "Perhaps your current printer is not set correctly?",
213 "Printing Error", wx.OK)
214 else:
215 data = printer.GetPrintDialogData()
216 self.pdata = wx.PrintData(data.GetPrintData()) # force a copy
217 printout.Destroy()
218
219
220 app = wx.PySimpleApp()
221 frm = PrintFrameworkSample()
222 frm.Show()
223 app.MainLoop()
例17.2中的打印输出类能够打印简单的文本文档,但是不能处理页码或标题,并且它创假设了行的宽度没有超过页面的宽度。对于例子的完善就留给读者作为一个练习。
上面最重要的代码片断是在构架的OnPreparePrinting()和OnPrintPage()以及示例窗口的OnPrint()方法中。
使用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() |
返回打印输出的标题。 |
在后面的几节中,我们将讨论如何呈现打印对话框给用户。
如何显示打印对话框?
诸如要打印那些面面,要打印多少副本这些关于打印工作的数据是由标准的打印对话框来管理的。打印对话框是与字体和颜色对话框类似的,wxPython中的打印对话框实例仅仅是对本地控件和一个储存了对话框数据的分离的数据对象的简单封装。
创建一个打印对话框
图17.3显示了打印设置对话框的样例。
图17.3
这里的对话框是类wx.PrintDialog的一个实例,你可以使用下面的构造函数来得到:
wx.PrintDialog(parent, data=None)
其中,参数parent是对话框的父框架,参数data是一个预先存在的wx.PrintDialogData实例,它用于对话框的初始数据。
使用方法
一旦你有了打印对话框,你就可以使用标准的ShowModal()方法来显示它,ShowModal()方法将根据用户关闭对话框的方式而返回wx.ID_OK或wx.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.LANDSCAPE和wx.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_LOW。get*方法将返回上面的这些值之一,或一个代表每英寸点数设置的正整数。 |
如何显示页面设置对话框?
图17.4显示了页面设置对话框是如何让用户来设置与页面尺寸相关的数据的。
图17.4
创建页面设置对话框
你可以通过实例化一个wx.PageSetupDialog类来创建一个页面设置对话框。
wx.PageSetupDialog(parent, data=None)
参数parent是新的对话框的父窗口。参数data是wx.PageSetupDialogData的一个实例默认为None。一旦页面设置对话框被创建了,那么这个对话框的行为就和其它任何模式对话框一样,并且你可以使用ShowModal()来显示它。通常,返回值表明了用户是否是使用wx.ID_OK或wx.ID_CANCEL按钮关闭的对话框窗口。在对话框关闭后,你可以通过调用GetPageSetupDialogData()来取得对数据对象的访问, GetPageSetupDialogData()返回类wx.PageSetupDialogData的一个实例。
使用页面设置属性工作
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实例。 |
到目前为止,我们已经讨论了所有关于数据对话框的整改,下面我们将重点放在打印上面。
如何打印?
到目前为止,我们已经见过了打印构架的所有部分,现是我们打印一些东西的时候了。实际的打印部分是由wx.Printer类的一个实例来控制的。与已经说明的其它部分相比,打印并不更简单。接下来,我们将对在例17.1中的OnPrint()中的步骤作介绍。
第一步 按顺序得到你的所有数据
这至少应该包括带有打印机命令的wx.Printout对象,通常也要包括一个wx.PrintDialogData实例。
第二步 创建一个wx.Printer实例
创建该实例,要使用构造器wx.Printer(data=None)。可选参数data是一个wx.PrintDialogData实例。该数据控制打印,通常,你会想使用它。
第三步 使用wx.Printer的Print ()方法打印
Print()方法如下:
1 Print(parent, printout, prompt=True)
其中参数parent是当打印时所触发的对话框的父窗口。printout是用于打印的wx.Printout对象。如果参数prompt为True,那么在打印之前显示打印对话框,否则将立即;启动打印。
如果打印成功,则Print()方法返回True。你能够调用GetLastError()方法来得到下列常量之一:wx.PRINTER_CANCELLED(如果失败是由于用户取消了打印所引起的),wx.PRINTER_ERROR(如果失败在打印期间由打印自身所引起的),或wx.PRINTER_NO_ERROR(如果Print()返回True且没有错误发生)。
这儿还有另外两个你可以使用一个wx.Printer实例做的事:
* 你可以使用CreateAbortWindow(parent,printout)来显示中止对话框,其中参数parent和printout同Print()方法中的。如果用户已经中止打印任务,你能够通过调用Abort()来发现,该方法在这种情况下返回True。
* 你可以使用PrintDialog(parent)来显式地显示打印对话框,并且你可以使用GetPrintDialogData()来得到活动的打印数据对象。
如何实现一个打印预览?
使用设备上下文的一个好处就是很容易管理打印预览,你可以使用一个屏幕设备上下文来代替打印机设备上下文。接下来的三个部分将讨论打印预览的过程。
第一步 创建预览实例
在一个打印预览中的第一步是创建类wx.PrintPreview的一个实例,wx.PrintPreview类似wx.Printer。构造器如下:
1 wx.PrintPreview(printout, printoutForPrinting, data=None)
其中参数printout是一个wx.Printout对象,用于管理预览。参数printoutForPrinting是另一个wx.Printout对象。如果它不是None,那么当显示的时候,该打印预览窗口包含一Print按钮,该按钮启动打印。printoutForPrinting用于实际的打印。如果参数printoutForPrinting为None,那么Print按钮不显示。当然,你可以传递同一个实例或你的自定义打印输出类的相同版本的两个实例给参数printout和printoutForPrinting。参数data可以是一个wx.PrintData对象或一个wx.PrintDialogData对象。如果参数data指定了的话,那么它被用于控制该打印预览。在例17.1中,我们显示了一个在OnPrintPreview()方法中使用打印预览的例子。
第二步 创建预览框架
一旦你有了你的wx.PrintPreview,你就需要一框架以在其中观看你的wx.PrintPreview。该框架由类wx.PreviewFrame提供,wx.PreviewFrame是wx.Frame的一个子类,wx.Frame为预览提供基本的用户交互控件。wx.PreviewFrame的构造器如下:
其中真正有意义的参数是preview,它是要被预览的wx.PrintPreview实例。其它的参数都是标准的wx.Frame中的。wx.PreviewFrame不定义任何自定义的样式或事件。
第三步 初始化框架
在你显示你的wx.PreviewFrame之前,你需要调用Initialize()方法,该方法创建窗口的内部的部件并做其它的内部的计算。一旦你Show()了该框架,那么如果你想再改变预览窗口的感观,你可以使用考虑CreateControlBar()和CreateCanvas()方法,它们分别创建类wx.PreviewControlBar和wx.PreviewCanvas的对象。覆盖这些方法以创建你自己的画布(canvas)和/或控制栏对象,使得你能够定制你的打印预览窗口的感观。
本章小结
1、这是wxPython中的一个通用的打印构架,它不仅可以打印HTML,还可以打印任何能够被绘制到设备上下文的东西。这个架构中的主要的类是wx.Printout,但是wx.Printer和wx.PrintPreview也是重要的。
2、wx.Printout类管理图形打印的细节,并且它包含几个可以被覆盖来定制打印会话期间的行为和使用的数据的方法。打印发生在OnPrintPage()方法期间。
3、用于打印机设置和页面设置的标准的对话框是可以从wxPython来访问的。打印机设置对话框是wx.PrintDialog的一个实例,页面设置对话框是wx.PageSetupDialog的一个实例。这两个对话框都有相关的数据类,数据类使你的程序可以处理所有显示在对话框中的值。
4、一旦有了数据,那么实际将数据传送给打印机则是wx.Printer类的相对简单的应用。你可以使用wx.PrintPreview类来管理一个打印预览会话,该类包括一个打印预览框架,和根据该框架指定通常打印行为的选项。