Printing framework (Phoenix)
Keywords : Printing, Printout, Preview, Printer, PrintData, PrintDialogData, PageSetupDialogData, PageSetupDialog, PrintPreview, PreviewFrame, Canvas, Grid, HtmlEasyPrinting, PDFViewer, PDFWindow, ReportLab.
Contents
- Printing framework (Phoenix)
- Introduction
- What Objects are Involved
- Demonstrating :
- Download source
- Additional Information
- Thanks to
- About this page
- Comments
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:
wx.HtmlEasyPrinting -- The simple way to print
wx.Printout -- Base printing class that will be inherited from. Various control functions handling printing events are defined here.
wx.PrintData -- Printer / page configuration data
wx.PrintDialogData -- (same as (wx.PrintData) except what is used by Page Setup window??)
wx.Printer -- Software interface to the printer
wx.MessageBox -- Used for alerting the user to any problems
wx.PrintPreview -- Used for print preview
wx.PrintDialog -- Window that pops up, asking how many pages to print, etc..
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
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 self.SetTitle("Printing test...")
55
56
57 def CreateMenu(self):
58 """
59 Make the frame menus.
60 """
61
62 menub = wx.MenuBar()
63
64 fmenu = wx.Menu()
65 fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
66 fmenu.AppendSeparator()
67 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
68 menub.Append(fmenu, "&File")
69
70 self.SetMenuBar(menub)
71
72
73 def CreateCtrls(self):
74 """
75 Make widgets for my application.
76 """
77
78 boldFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
79 boldFont.SetWeight(wx.BOLD)
80 boldFont.SetPointSize(10)
81
82 #------------
83
84 # First create the controls.
85 self.panel = wx.Panel(self,
86 id=-1,
87 style=wx.BORDER_THEME|
88 wx.TAB_TRAVERSAL)
89
90 self.text = wx.StaticText(self.panel,
91 id=-1,
92 label="Demonstrating :")
93 self.text.SetFont(boldFont)
94
95 self.info = wx.StaticText(self.panel,
96 id=-1,
97 label="> Direct printing.")
98 self.info.SetForegroundColour("red")
99
100 self.tc = wx.TextCtrl(self.panel,
101 id=-1,
102 size=(200, -1),
103 value="Hello, World ! A sample text.")
104
105 self.btnPrint = wx.Button(self.panel,
106 id=wx.ID_PRINT,
107 label="")
108 self.btnPrint.SetFocus()
109
110 self.btnClose = wx.Button(self.panel,
111 id=wx.ID_CLOSE,
112 label="E&xit")
113
114
115 def BindEvents(self):
116 """
117 Bind all the events related to my application.
118 """
119
120 # Bind some menu events to an events handler.
121 self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
122 self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
123
124 # Bind the close event to an event handler.
125 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
126
127 # Bind some buttons events to an events handler.
128 self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
129 self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
130
131
132 def DoLayout(self):
133 """
134 Manage widgets Layout.
135 """
136
137 # MainSizer is the top-level one that manages everything.
138 mainSizer = wx.BoxSizer(wx.VERTICAL)
139
140 #------------
141
142 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
143 hBox1.Add(self.info, 0, wx.ALL, 15)
144
145 #------------
146
147 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
148 hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
149 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
150
151 #------------
152
153 mainSizer.Add(self.text, 0, wx.ALL, 10)
154 mainSizer.Add(wx.StaticLine(self.panel),
155 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
156 mainSizer.Add(self.tc, 0, wx.ALL, 15)
157 mainSizer.Add(hBox1, 0, wx.ALL, 5)
158 mainSizer.Add(hBox2, 0, wx.ALL, 5)
159
160 #------------
161
162 # Finally, tell the panel to use the mainSizer for layout.
163 self.panel.SetSizer(mainSizer)
164
165
166 def OnBtnPrint(self, event):
167 """
168 Print the document.
169 """
170
171 text = self.tc.GetValue()
172
173 #------------
174
175 pd = wx.PrintData()
176
177 pd.SetPrinterName("")
178 pd.SetOrientation(wx.PORTRAIT)
179 pd.SetPaperId(wx.PAPER_A4)
180 pd.SetQuality(wx.PRINT_QUALITY_DRAFT)
181 # Black and white printing if False.
182 pd.SetColour(True)
183 pd.SetNoCopies(1)
184 pd.SetCollate(True)
185
186 #------------
187
188 pdd = wx.PrintDialogData()
189
190 pdd.SetPrintData(pd)
191 pdd.SetMinPage(1)
192 pdd.SetMaxPage(1)
193 pdd.SetFromPage(1)
194 pdd.SetToPage(1)
195 pdd.SetPrintToFile(False)
196 # pdd.SetSetupDialog(False)
197 # pdd.EnableSelection(True)
198 # pdd.EnablePrintToFile(True)
199 # pdd.EnablePageNumbers(True)
200 # pdd.SetAllPages(True)
201
202 #------------
203
204 dlg = wx.PrintDialog(self, pdd)
205
206 if dlg.ShowModal() == wx.ID_OK:
207 dc = dlg.GetPrintDC()
208
209 dc.StartDoc("My document title")
210 dc.StartPage()
211
212 # (wx.MM_METRIC) ---> Each logical unit is 1 mm.
213 # (wx.MM_POINTS) ---> Each logical unit is a "printer point" i.e.
214 dc.SetMapMode(wx.MM_POINTS)
215
216 dc.SetTextForeground("red")
217 dc.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.BOLD))
218 dc.DrawText(text, 50, 100)
219
220 dc.EndPage()
221 dc.EndDoc()
222 del dc
223
224 else :
225 dlg.Destroy()
226
227
228 def OnBtnClose(self, event):
229 """
230 ...
231 """
232
233 self.Close(True)
234
235
236 def OnCloseWindow(self, event):
237 """
238 ...
239 """
240
241 self.Destroy()
242
243 #-------------------------------------------------------------------------------
244
245 class My_App(wx.App):
246 """
247 ...
248 """
249 def OnInit(self):
250
251 #------------
252
253 frame = My_Frame(None, id=-1)
254 self.SetTopWindow(frame)
255 frame.Show(True)
256
257 return True
258
259 #-------------------------------------------------------------------------------
260
261 def main():
262 app = My_App(False)
263 app.MainLoop()
264
265 #-------------------------------------------------------------------------------
266
267 if __name__ == "__main__" :
268 main()
Printout class
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 self.SetTitle("Printing test...")
156
157
158 def CreateMenu(self):
159 """
160 Make the frame menus.
161 """
162
163 menub = wx.MenuBar()
164
165 fmenu = wx.Menu()
166 fmenu.Append(wx.ID_PAGE_SETUP, "Page set&up\tCtrl+U")
167 fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
168 fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
169 fmenu.AppendSeparator()
170 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
171 menub.Append(fmenu, "&File")
172
173 self.SetMenuBar(menub)
174
175
176 def CreateCtrls(self):
177 """
178 Make widgets for my app.
179 """
180
181 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
182 font.SetWeight(wx.BOLD)
183 font.SetPointSize(10)
184
185 #------------
186
187 # First create the controls.
188 self.panel = wx.Panel(self,
189 id=-1,
190 style=wx.BORDER_THEME|
191 wx.TAB_TRAVERSAL)
192
193 self.text = wx.StaticText(self.panel,
194 id=-1,
195 label="Demonstrating :")
196 self.text.SetFont(font)
197
198 self.info = wx.StaticText(self.panel,
199 id=-1,
200 label="1) Direct printing,\n"
201 "2) Printout class,\n"
202 "3) Preview,\n"
203 "4) Menu,\n"
204 "5) Page setup.")
205 self.info.SetForegroundColour("red")
206 font.SetWeight(wx.NORMAL)
207 self.info.SetFont(font)
208
209 self.tc = wx.TextCtrl(self.panel,
210 id=-1,
211 size=(200, -1),
212 value="Hello, World ! A sample text.")
213
214 self.btnSetup = wx.Button(self.panel,
215 id=wx.ID_PAGE_SETUP,
216 label="Page set&up")
217
218 self.btnPreview = wx.Button(self.panel,
219 id=wx.ID_PREVIEW,
220 label="Print pre&view")
221 self.btnPreview.SetFocus()
222
223 self.btnPrint = wx.Button(self.panel,
224 id=wx.ID_PRINT,
225 label="&Print")
226
227 self.btnClose = wx.Button(self.panel,
228 id=wx.ID_CLOSE,
229 label="E&xit")
230
231
232 def CreatePrintData(self):
233 """
234 Create printing data.
235 """
236
237 self.printdata = wx.PrintData()
238
239 self.printdata.SetPrinterName('')
240 self.printdata.SetOrientation(wx.PORTRAIT)
241 self.printdata.SetPaperId(wx.PAPER_A4)
242 self.printdata.SetQuality(wx.PRINT_QUALITY_DRAFT)
243 # Black and white printing if False.
244 self.printdata.SetColour(True)
245 self.printdata.SetNoCopies(1)
246 self.printdata.SetCollate(True)
247 # self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
248
249
250 def BindEvents(self):
251 """
252 Bind all the events related to my application.
253 """
254
255 # Bind some menu events to an events handler.
256 self.Bind(wx.EVT_MENU, self.OnBtnPageSetup, id=wx.ID_PAGE_SETUP)
257 self.Bind(wx.EVT_MENU, self.OnBtnPreview, id=wx.ID_PREVIEW)
258 self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
259 self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
260
261 # Bind the close event to an event handler.
262 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
263
264 # Bind some buttons events to an events handler.
265 self.Bind(wx.EVT_BUTTON, self.OnBtnPageSetup, self.btnSetup)
266 self.Bind(wx.EVT_BUTTON, self.OnBtnPreview, self.btnPreview)
267 self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
268 self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
269
270
271 def DoLayout(self):
272 """
273 Manage widgets Layout.
274 """
275
276 # MainSizer is the top-level one that manages everything.
277 mainSizer = wx.BoxSizer(wx.VERTICAL)
278
279 #------------
280
281 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
282 hBox1.Add(self.info, 0, wx.ALL, 15)
283
284 #------------
285
286 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
287 hBox2.Add(self.btnSetup, 0, wx.ALL, 10)
288 hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
289 hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
290 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
291
292 #------------
293
294 mainSizer.Add(self.text, 0, wx.ALL, 10)
295 mainSizer.Add(wx.StaticLine(self.panel),
296 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
297 mainSizer.Add(self.tc, 0, wx.ALL, 15)
298 mainSizer.Add(hBox1, 0, wx.ALL, 5)
299 mainSizer.Add(hBox2, 0, wx.ALL, 5)
300
301 #------------
302
303 # Finally, tell the panel to use the mainSizer for layout.
304 self.panel.SetSizer(mainSizer)
305
306
307 def OnBtnPageSetup(self, event):
308 """
309 Show the PrinterSetup dialog.
310 """
311
312 psdd = wx.PageSetupDialogData(self.printdata)
313
314 psdd.EnablePrinter(True)
315 # psdd.CalculatePaperSizeFromId()
316
317 #------------
318
319 dlg = wx.PageSetupDialog(self, psdd)
320 dlg.ShowModal()
321
322 #------------
323
324 # This makes a copy of the wx.PrintData instead of just saving
325 # a reference to the one inside the PrintDialogData that will
326 # be destroyed when the dialog is destroyed
327 self.printdata = wx.PrintData(dlg.GetPageSetupData().GetPrintData())
328
329 dlg.Destroy()
330
331
332 def OnBtnPreview(self, event):
333 """
334 Show the print preview.
335 """
336
337 text = self.tc.GetValue()
338
339 #------------
340
341 data = wx.PrintDialogData(self.printdata)
342
343 printout1 = My_Printout(text, "- My printing object")
344 printout2 = My_Printout(text, "- My printing object")
345
346 printPreview = wx.PrintPreview(printout1, printout2, data)
347
348 # Initial zoom value.
349 if "__WXMAC__" in wx.PlatformInfo:
350 printPreview.SetZoom(50)
351 else:
352 printPreview.SetZoom(35)
353
354 if not printPreview.IsOk():
355 wx.MessageBox(("There was a problem printing.\nPerhaps "\
356 "your current printer is \nnot "\
357 "set correctly ?"),
358 ("Printing"),
359 wx.OK)
360 return
361
362 else:
363 previewFrame = wx.PreviewFrame(printPreview, None, "Print preview")
364 previewFrame.Initialize()
365 previewFrame.SetPosition(self.GetPosition())
366 previewFrame.SetSize(self.GetSize())
367 # Or full screen :
368 # previewFrame.Maximize()
369 previewFrame.Show(True)
370 previewFrame.Layout()
371
372
373 def OnBtnPrint(self, event):
374 """
375 Prints the document.
376 """
377
378 text = self.tc.GetValue()
379
380 #------------
381
382 pdd = wx.PrintDialogData(self.printdata)
383 pdd.SetPrintData(self.printdata)
384 pdd.SetMinPage(1)
385 pdd.SetMaxPage(1)
386 pdd.SetFromPage(1)
387 pdd.SetToPage(1)
388 pdd.SetPrintToFile(False)
389 # pdd.SetSetupDialog(False)
390 # pdd.EnableSelection(True)
391 # pdd.EnablePrintToFile(True)
392 # pdd.EnablePageNumbers(True)
393 # pdd.SetAllPages(True)
394
395 #------------
396
397 printer = wx.Printer(pdd)
398
399 myPrintout = My_Printout(text, "- My printing object")
400
401 if not printer.Print(self, myPrintout, True):
402 wx.MessageBox(("There was a problem printing.\nPerhaps "\
403 "your current printer is \nnot "\
404 "set correctly ?"),
405 ("Printing"),
406 wx.OK)
407 return
408
409 else:
410 self.printData = wx.PrintData(printer.GetPrintDialogData().GetPrintData())
411 myPrintout.Destroy()
412
413
414 def OnBtnClose(self, event):
415 """
416 ...
417 """
418
419 self.Close(True)
420
421
422 def OnCloseWindow(self, event):
423 """
424 ...
425 """
426
427 self.Destroy()
428
429 #-------------------------------------------------------------------------------
430
431 class My_App(wx.App):
432 """
433 ...
434 """
435 def OnInit(self):
436
437 #------------
438
439 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
440
441 #------------
442
443 frame = My_Frame(None, id=-1)
444 self.SetTopWindow(frame)
445 frame.Show(True)
446
447 return True
448
449
450 #-------------------------------------------------------------------------------
451
452 def main():
453 app = My_App(False)
454 app.MainLoop()
455
456 #-------------------------------------------------------------------------------
457
458 if __name__ == "__main__" :
459 main()
Canvas and printout class
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 self.SetTitle("Printing test...")
339
340
341 def CreateMenu(self):
342 """
343 Make the frame menus.
344 """
345
346 menub = wx.MenuBar()
347
348 fmenu = wx.Menu()
349 fmenu.Append(wx.ID_PAGE_SETUP, "Page set&up\tCtrl+U")
350 fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
351 fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
352 fmenu.AppendSeparator()
353 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
354 menub.Append(fmenu, "&File")
355
356 self.SetMenuBar(menub)
357
358
359 def CreateCtrls(self):
360 """
361 Make widgets for my app.
362 """
363
364 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
365 font.SetWeight(wx.BOLD)
366 font.SetPointSize(10)
367
368 #------------
369
370 # First create the controls.
371 self.panel = wx.Panel(self,
372 id=-1,
373 style=wx.BORDER_THEME|
374 wx.TAB_TRAVERSAL)
375
376 self.text = wx.StaticText(self.panel,
377 id=-1,
378 label="Demonstrating :")
379 self.text.SetFont(font)
380
381 self.info = wx.StaticText(self.panel,
382 id=-1,
383 label="1) Direct printing,\n"
384 "2) Printout class,\n"
385 "3) Canvas class,\n"
386 "4) Preview,\n"
387 "5) Menu,\n"
388 "6) Page setup.")
389 self.info.SetForegroundColour("red")
390 font.SetWeight(wx.NORMAL)
391 self.info.SetFont(font)
392
393 self.tc = wx.TextCtrl(self.panel,
394 id=-1,
395 size=(200, -1),
396 value="Hello, World ! A sample text.")
397
398 self.canvas = My_Canvas(self.panel, size=(0, 0))
399
400 self.btnSetup = wx.Button(self.panel,
401 id=wx.ID_PAGE_SETUP,
402 label="Page set&up")
403
404 self.btnPreview = wx.Button(self.panel,
405 id=wx.ID_PREVIEW,
406 label="Print pre&view")
407 self.btnPreview.SetFocus()
408
409 self.btnPrint = wx.Button(self.panel,
410 id=wx.ID_PRINT,
411 label="&Print")
412
413 self.btnClose = wx.Button(self.panel,
414 id=wx.ID_CLOSE,
415 label="E&xit")
416
417
418 def CreatePrintData(self):
419 """
420 Create printing data.
421 """
422
423 self.printdata = wx.PrintData()
424
425 self.printdata.SetPrinterName('')
426 self.printdata.SetOrientation(wx.PORTRAIT)
427 self.printdata.SetPaperId(wx.PAPER_A4)
428 self.printdata.SetQuality(wx.PRINT_QUALITY_DRAFT)
429 # Black and white printing if False.
430 self.printdata.SetColour(True)
431 self.printdata.SetNoCopies(1)
432 self.printdata.SetCollate(True)
433 # self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
434
435
436 def BindEvents(self):
437 """
438 Bind all the events related to my application.
439 """
440
441 # Bind some menu events to an events handler.
442 self.Bind(wx.EVT_MENU, self.OnBtnPageSetup, id=wx.ID_PAGE_SETUP)
443 self.Bind(wx.EVT_MENU, self.OnBtnPreview, id=wx.ID_PREVIEW)
444 self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
445 self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
446
447 # Bind the close event to an event handler.
448 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
449
450 # Bind some buttons events to an events handler.
451 self.Bind(wx.EVT_BUTTON, self.OnBtnPageSetup, self.btnSetup)
452 self.Bind(wx.EVT_BUTTON, self.OnBtnPreview, self.btnPreview)
453 self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
454 self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
455
456
457 def DoLayout(self):
458 """
459 Manage widgets Layout.
460 """
461
462 # MainSizer is the top-level one that manages everything.
463 mainSizer = wx.BoxSizer(wx.VERTICAL)
464
465 #------------
466
467 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
468 hBox1.Add(self.info, 0, wx.ALL, 15)
469
470 #------------
471
472 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
473 hBox2.Add(self.btnSetup, 0, wx.ALL, 10)
474 hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
475 hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
476 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
477
478 #------------
479
480 mainSizer.Add(self.text, 0, wx.ALL, 10)
481 mainSizer.Add(wx.StaticLine(self.panel),
482 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
483 mainSizer.Add(self.tc, 0, wx.ALL, 15)
484 mainSizer.Add(hBox1, 0, wx.ALL, 5)
485 mainSizer.Add(hBox2, 0, wx.ALL, 5)
486
487 #------------
488
489 # Finally, tell the panel to use the mainSizer for layout.
490 self.panel.SetSizer(mainSizer)
491
492
493 def OnBtnPageSetup(self, event):
494 """
495 Show the PrinterSetup dialog.
496 """
497
498 psdd = wx.PageSetupDialogData(self.printdata)
499
500 psdd.EnablePrinter(True)
501 # psdd.CalculatePaperSizeFromId()
502
503 #------------
504
505 dlg = wx.PageSetupDialog(self, psdd)
506 dlg.ShowModal()
507
508 #------------
509
510 # This makes a copy of the wx.PrintData instead of just saving
511 # a reference to the one inside the PrintDialogData that will
512 # be destroyed when the dialog is destroyed
513 self.printdata = wx.PrintData(dlg.GetPageSetupData().GetPrintData())
514
515 dlg.Destroy()
516
517
518 def OnBtnPreview(self, event):
519 """
520 Show the print preview.
521 """
522
523 text = self.tc.GetValue()
524
525 #------------
526
527 data = wx.PrintDialogData(self.printdata)
528
529 printout1 = My_Printout(self.canvas, text, "- My printing object")
530 printout2 = My_Printout(self.canvas, text, "- My printing object")
531
532 printPreview = wx.PrintPreview(printout1, printout2, data)
533
534 # Initial zoom value.
535 if "__WXMAC__" in wx.PlatformInfo:
536 printPreview.SetZoom(50)
537 else:
538 printPreview.SetZoom(35)
539
540 if not printPreview.IsOk():
541 wx.MessageBox(("There was a problem printing.\nPerhaps "\
542 "your current printer is \nnot "\
543 "set correctly ?"),
544 ("Printing"),
545 wx.OK)
546 return
547
548 else:
549 previewFrame = wx.PreviewFrame(printPreview, None, "Print preview")
550 previewFrame.Initialize()
551 previewFrame.SetPosition(self.GetPosition())
552 previewFrame.SetSize(self.GetSize())
553 # Or full screen :
554 # previewFrame.Maximize()
555 previewFrame.Show(True)
556 previewFrame.Layout()
557
558
559 def OnBtnPrint(self, event):
560 """
561 Prints the document.
562 """
563
564 text = self.tc.GetValue()
565
566 #------------
567
568 pdd = wx.PrintDialogData(self.printdata)
569 pdd.SetPrintData(self.printdata)
570 pdd.SetMinPage(1)
571 pdd.SetMaxPage(1)
572 pdd.SetFromPage(1)
573 pdd.SetToPage(1)
574 pdd.SetPrintToFile(False)
575 # pdd.SetSetupDialog(False)
576 # pdd.EnableSelection(True)
577 # pdd.EnablePrintToFile(True)
578 # pdd.EnablePageNumbers(True)
579 # pdd.SetAllPages(True)
580
581 #------------
582
583 printer = wx.Printer(pdd)
584
585 myPrintout = My_Printout(self.canvas, text, "- My printing object")
586
587 if not printer.Print(self, myPrintout, True):
588 wx.MessageBox(("There was a problem printing.\nPerhaps "\
589 "your current printer is \nnot "\
590 "set correctly ?"),
591 ("Printing"),
592 wx.OK)
593 return
594
595 else:
596 self.printData = wx.PrintData(printer.GetPrintDialogData().GetPrintData())
597 myPrintout.Destroy()
598
599
600 def OnBtnClose(self, event):
601 """
602 ...
603 """
604
605 self.Close(True)
606
607
608 def OnCloseWindow(self, event):
609 """
610 ...
611 """
612
613 self.Destroy()
614
615 #-------------------------------------------------------------------------------
616
617 class My_App(wx.App):
618 """
619 ...
620 """
621 def OnInit(self):
622
623 #------------
624
625 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
626
627 #------------
628
629 frame = My_Frame(None, id=-1)
630 self.SetTopWindow(frame)
631 frame.Show(True)
632
633 return True
634
635 #-------------------------------------------------------------------------------
636
637 def main():
638 app = My_App(False)
639 app.MainLoop()
640
641 #-------------------------------------------------------------------------------
642
643 if __name__ == "__main__" :
644 main()
Multiline printing
1 # sample_four.py
2
3 #-------------------------------------------------------------------------------
4 # Name: printout.py
5 # Purpose: preview and printing class -> table/grid printing
6 #
7 # Author: Lorne White (email: lorne.white@telusplanet.net)
8 #
9 # Created:
10 # Version: 0.75
11 # Date: May 15, 2002
12 # Licence: wxWindows license
13 #-------------------------------------------------------------------------------
14 # Link:
15 # https://raw.githubusercontent.com/wxWidgets/wxPython/master/wx/lib/printout.py
16 #-------------------------------------------------------------------------------
17 # Release Notes :
18 # fixed bug for string wider than print region
19 # add index to data list after parsing total pages for paging
20 #-------------------------------------------------------------------------------
21 # 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
22 # o 2.5 compatability update.
23 #-------------------------------------------------------------------------------
24 # 11/23/2004 - Vernon Cole (wnvcole@peppermillcas.com)
25 # o Generalize for non-2-dimensional sequences and non-text data
26 # (can use as a simple text printer by supplying a list of strings.)
27 # o Add a small _main_ for self test
28 #-------------------------------------------------------------------------------
29
30 import os
31 import copy
32 import wx
33
34 # class PrintBase
35 # class PrintTableDraw
36 # class PrintTable
37 # class PrintGrid
38 # class SetPrintout
39 # class Frame
40 # class App
41
42 #-------------------------------------------------------------------------------
43
44 if os.name == "posix":
45 print("\nPlatform : UNIX - Linux")
46 elif os.name in ['nt', 'dos', 'ce']:
47 print("\nPlatform : Windows")
48 else:
49 print("\nPlatform : ", platform.system())
50
51 #-------------------------------------------------------------------------------
52
53 class PrintBase(object):
54 """
55 ...
56 """
57 def SetPrintFont(self, font): # set the DC font parameters
58 fattr = font["Attr"]
59 if fattr[0] == 1:
60 weight = wx.BOLD
61 else:
62 weight = wx.NORMAL
63
64 if fattr[1] == 1:
65 set_style = wx.ITALIC
66 else:
67 set_style = wx.NORMAL
68
69 underline = fattr[2]
70 fcolour = self.GetFontColour(font)
71 self.DC.SetTextForeground(fcolour)
72
73 setfont = wx.Font(font["Size"], wx.SWISS, set_style, weight, underline)
74 setfont.SetFaceName(font["Name"])
75 self.DC.SetFont(setfont)
76
77 #---------------------------------------------------------------------------
78
79 def GetFontColour(self, font):
80 fcolour = font["Colour"]
81 return wx.Colour(fcolour[0], fcolour[1], fcolour[2])
82
83
84 def OutTextRegion(self, textout, txtdraw = True):
85 textlines = textout.split('\n')
86 y = copy.copy(self.y) + self.pt_space_before
87 for text in textlines:
88 remain = 'X'
89 while remain != "":
90 vout, remain = self.SetFlow(text, self.region)
91 if self.draw == True and txtdraw == True:
92 test_out = self.TestFull(vout)
93 if self.align == wx.ALIGN_LEFT:
94 self.DC.DrawText(test_out, int(self.indent+self.pcell_left_margin), int(y))
95
96 elif self.align == wx.ALIGN_CENTRE:
97 diff = self.GetCellDiff(test_out, self.region)
98 self.DC.DrawText(test_out, int(self.indent+diff/2), y)
99
100 elif self.align == wx.ALIGN_RIGHT:
101 diff = self.GetCellDiff(test_out, self.region)
102 self.DC.DrawText(test_out, int(self.indent+diff), y)
103
104 else:
105 self.DC.DrawText(test_out, int(self.indent+self.pcell_left_margin), int(y))
106 text = remain
107 y = y + self.space
108 return y - self.space + self.pt_space_after
109
110
111 def GetCellDiff(self, text, width): # get the remaining cell size for adjustment
112 w, h = self.DC.GetTextExtent(text)
113 diff = width - w
114 if diff < 0:
115 diff = 0
116 return diff
117
118
119 def TestFull(self, text_test):
120 w, h = self.DC.GetTextExtent(text_test)
121 if w > self.region: # trouble fitting into cell
122 return self.SetChar(text_test, self.region) # fit the text to the cell size
123 else:
124 return text_test
125
126
127 def SetFlow(self, ln_text, width):
128 width = width - self.pcell_right_margin
129 text = ""
130 split = ln_text.split()
131 if len(split) == 1:
132 return ln_text, ""
133
134 try:
135 w, h = self.DC.GetTextExtent(" " + split[0])
136 if w >= width:
137 return ln_text, ""
138 except:
139 pass
140
141 cnt = 0
142 for word in split:
143 bword = " " + word # blank + word
144 length = len(bword)
145
146 w, h = self.DC.GetTextExtent(text + bword)
147 if w < width:
148 text = text + bword
149 cnt = cnt + 1
150 else:
151 remain = ' '.join(split[cnt:])
152 text = text.strip()
153 return text, remain
154
155 remain = ' '.join(split[cnt:])
156 vout = text.strip()
157 return vout, remain
158
159
160 def SetChar(self, ln_text, width): # truncate string to fit into width
161 width = width - self.pcell_right_margin - self.pcell_left_margin
162 text = ""
163 for val in ln_text:
164 w, h = self.DC.GetTextExtent(text + val)
165 if w > width:
166 text = text + ".."
167 return text # fitted text value
168 text = text + val
169 return text
170
171
172 def OutTextPageWidth(self, textout, y_out, align, indent, txtdraw = True):
173 textlines = textout.split('\n')
174 y = copy.copy(y_out)
175
176 pagew = self.parent.page_width * self.pwidth # full page width
177 w, h = self.DC.GetTextExtent(textout)
178 y_line = h
179
180 for text in textlines:
181 remain = 'X'
182 while remain != "":
183 vout, remain = self.SetFlow(text, pagew)
184 if self.draw == True and txtdraw == True:
185 test_out = vout
186 if align == wx.ALIGN_LEFT:
187 self.DC.DrawText(test_out, indent, y)
188
189 elif align == wx.ALIGN_CENTRE:
190 diff = self.GetCellDiff(test_out, pagew)
191 self.DC.DrawText(test_out, int(indent+diff/2), int(y))
192
193 elif align == wx.ALIGN_RIGHT:
194 diff = self.GetCellDiff(test_out, pagew)
195 self.DC.DrawText(test_out, int(indent+diff), int(y))
196
197 else:
198 self.DC.DrawText(test_out, indent, y_out)
199 text = remain
200 y = y + y_line
201 return y - y_line
202
203
204 def GetDate(self):
205 date, time = self.GetNow()
206 return date
207
208
209 def GetDateTime(self):
210 date, time = self.GetNow()
211 return date + ' ' + time
212
213
214 def GetNow(self):
215 now = wx.DateTime.Now()
216 date = now.FormatDate()
217 time = now.FormatTime()
218 return date, time
219
220
221 def SetPreview(self, preview):
222 self.preview = preview
223
224
225 def SetPSize(self, width, height):
226 self.pwidth = width/self.scale
227 self.pheight = height/self.scale
228
229
230 def SetScale(self, scale):
231 self.scale = scale
232
233
234 def SetPTSize(self, width, height):
235 self.ptwidth = width
236 self.ptheight = height
237
238
239 def getWidth(self):
240 return self.sizew
241
242
243 def getHeight(self):
244 return self.sizeh
245
246 #-------------------------------------------------------------------------------
247
248 class PrintTableDraw(wx.ScrolledWindow, PrintBase):
249 """
250 ...
251 """
252 def __init__(self, parent, DC, size):
253 self.parent = parent
254 self.DC = DC
255 self.scale = parent.scale
256 self.width = size[0]
257 self.height = size[1]
258 self.SetDefaults()
259
260 #---------------------------------------------------------------------------
261
262 def SetDefaults(self):
263 self.page = 1
264 self.total_pages = None
265
266 self.page_width = self.parent.page_width
267 self.page_height = self.parent.page_height
268
269 self.left_margin = self.parent.left_margin
270 self.right_margin = self.parent.right_margin
271
272 self.top_margin = self.parent.top_margin
273 self.bottom_margin = self.parent.bottom_margin
274 self.cell_left_margin = self.parent.cell_left_margin
275 self.cell_right_margin = self.parent.cell_right_margin
276
277 self.label_colour = self.parent.label_colour
278
279 self.row_line_colour = self.parent.row_line_colour
280 self.row_line_size = self.parent.row_line_size
281
282 self.row_def_line_colour = self.parent.row_def_line_colour
283 self.row_def_line_size = self.parent.row_def_line_size
284
285 self.column_line_colour = self.parent.column_line_colour
286 self.column_line_size = self.parent.column_line_size
287
288 self.column_def_line_size = self.parent.column_def_line_size
289 self.column_def_line_colour = self.parent.column_def_line_colour
290
291 self.text_font = self.parent.text_font
292
293 self.label_font = self.parent.label_font
294
295
296 def AdjustValues(self):
297 self.vertical_offset = self.pheight * self.parent.vertical_offset
298 self.horizontal_offset = self.pheight * self.parent.horizontal_offset
299
300 self.pcell_left_margin = self.pwidth * self.cell_left_margin
301 self.pcell_right_margin = self.pwidth * self.cell_right_margin
302 self.ptop_margin = self.pheight * self.top_margin
303 self.pbottom_margin = self.pheight * self.bottom_margin
304
305 self.pheader_margin = self.pheight * self.parent.header_margin
306 self.pfooter_margin = self.pheight * self.parent.footer_margin
307
308 self.cell_colour = self.parent.set_cell_colour
309 self.cell_text = self.parent.set_cell_text
310
311 self.column = []
312 self.column_align = []
313 self.column_bgcolour = []
314 self.column_txtcolour = []
315
316 set_column_align = self.parent.set_column_align
317 set_column_bgcolour = self.parent.set_column_bgcolour
318 set_column_txtcolour = self.parent.set_column_txtcolour
319
320 pos_x = self.left_margin * self.pwidth + self.horizontal_offset # left margin
321 self.column.append(pos_x)
322
323 # Module logic expects two dimensional data -- fix input if needed
324 if isinstance(self.data, str):
325 self.data = [[copy.copy(self.data)]] # a string becomes a single cell
326 try:
327 rows = len(self.data)
328 except TypeError:
329 self.data = [[str(self.data)]] # a non-iterable becomes a single cell
330 rows = 1
331 first_value = self.data[0]
332
333 if isinstance(first_value, str): # A sequence of strings
334 if self.label == [] and self.set_column == []:
335 data = []
336 for x in self.data: # Becomes one column
337 data.append([x])
338 else:
339 data = [self.data] # Becames one row
340 self.data = data
341 first_value = data[0]
342 try:
343 column_total = len(first_value)
344 except TypeError: # A sequence of non-iterables
345 if self.label == [] and self.set_column == []:
346 data = [] # Becomes one column
347 for x in self.data:
348 data.append([str(x)])
349 column_total = 1
350 else:
351 data = [self.data] # Becomes one row
352 column_total = len(self.data)
353 self.data = data
354 first_value = data[0]
355
356 if self.set_column == []:
357 table_width = self.page_width - self.left_margin - self.right_margin
358 if self.label == []:
359 temp = first_value
360 else:
361 temp = self.label
362 width = table_width/(len(temp))
363 for val in temp:
364 column_width = width * self.pwidth
365 pos_x = pos_x + column_width
366 self.column.append(pos_x) # position of each column
367 else:
368 for val in self.set_column:
369 column_width = val * self.pwidth
370 pos_x = pos_x + column_width
371 self.column.append(pos_x) # position of each column
372
373 if pos_x > self.page_width * self.pwidth: # check if it fits in page
374 print("Warning, Too Wide for Page")
375 return
376
377 if self.label != []:
378 if len(self.column) -1 != len(self.label):
379 print("Column Settings Incorrect", "\nColumn Value: " + str(self.column), "\nLabel Value: " + str(self.label))
380 return
381
382 if column_total != len(self.column) -1:
383 print("Cannot fit", first_value, 'in', len(self.column)-1, 'columns.')
384 return
385
386 for col in range(column_total):
387 try:
388 align = set_column_align[col] # check if custom column alignment
389 except:
390 align = wx.ALIGN_LEFT
391 self.column_align.append(align)
392
393 try:
394 colour = set_column_bgcolour[col] # check if custom column background colour
395 except:
396 colour = self.parent.column_colour
397 self.column_bgcolour.append(colour)
398
399 try:
400 colour = set_column_txtcolour[col] # check if custom column text colour
401 except:
402 colour = self.GetFontColour(self.parent.text_font)
403 self.column_txtcolour.append(colour)
404
405
406 def SetPointAdjust(self):
407 f = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL) # setup using 10 point
408 self.DC.SetFont(f)
409 f.SetFaceName(self.text_font["Name"])
410 x, y = self.DC.GetTextExtent("W")
411
412 self.label_pt_space_before = self.parent.label_pt_adj_before * y/10 # extra spacing for label per point value
413 self.label_pt_space_after = self.parent.label_pt_adj_after * y/10
414
415 self.text_pt_space_before = self.parent.text_pt_adj_before * y/10 # extra spacing for row text per point value
416 self.text_pt_space_after = self.parent.text_pt_adj_after * y/10
417
418
419 def SetPage(self, page):
420 self.page = page
421
422
423 def SetColumns(self, col):
424 self.column = col
425
426
427 def OutCanvas(self):
428 self.AdjustValues()
429 self.SetPointAdjust()
430
431 self.y_start = self.ptop_margin + self.vertical_offset
432 self.y_end = self.parent.page_height * self.pheight - self.pbottom_margin + self.vertical_offset
433
434 self.SetPrintFont(self.label_font)
435
436 x, y = self.DC.GetTextExtent("W")
437 self.label_space = y
438
439 self.SetPrintFont(self.text_font)
440
441 x, y = self.DC.GetTextExtent("W")
442 self.space = y
443
444 if self.total_pages is None:
445 self.GetTotalPages() # total pages for display/printing
446
447 self.data_cnt = self.page_index[self.page-1]
448
449 self.draw = True
450 self.PrintHeader()
451 self.PrintFooter()
452 self.OutPage()
453
454
455 def GetTotalPages(self):
456 self.data_cnt = 0
457 self.draw = False
458 self.page_index = [0]
459
460 cnt = 0
461 while 1:
462 test = self.OutPage()
463 self.page_index.append(self.data_cnt)
464 if test == False:
465 break
466 cnt = cnt + 1
467
468 self.total_pages = cnt + 1
469
470
471 def OutPage(self):
472 self.y = self.y_start
473 self.end_x = self.column[-1]
474
475 if self.data_cnt < len(self.data): # if there data for display on the page
476 if self.label != []: # check if header defined
477 self.PrintLabel()
478 else:
479 return False
480
481 for val in self.data:
482 try:
483 row_val = self.data[self.data_cnt]
484 except:
485 self.FinishDraw()
486 return False
487
488 max_y = self.PrintRow(row_val, False) # test to see if row will fit in remaining space
489 test = max_y + self.space
490
491 if test > self.y_end:
492 break
493
494 self.ColourRowCells(max_y-self.y+self.space) # colour the row/column
495 max_y = self.PrintRow(row_val, True) # row fits - print text
496 self.DrawGridLine() # top line of cell
497 self.y = max_y + self.space
498
499 if self.y > self.y_end:
500 break
501
502 self.data_cnt = self.data_cnt + 1
503
504 self.FinishDraw()
505
506 if self.data_cnt == len(self.data): # last value in list
507 return False
508
509 return True
510
511
512 def PrintLabel(self):
513 self.pt_space_before = self.label_pt_space_before # set the point spacing
514 self.pt_space_after = self.label_pt_space_after
515
516 self.LabelColorRow(self.label_colour)
517 self.SetPrintFont(self.label_font)
518
519 self.col = 0
520 max_y = 0
521 for vtxt in self.label:
522 self.region = self.column[self.col+1] - self.column[self.col]
523 self.indent = self.column[self.col]
524
525 self.align = wx.ALIGN_LEFT
526
527 max_out = self.OutTextRegion(vtxt, True)
528 if max_out > max_y:
529 max_y = max_out
530 self.col = self.col + 1
531
532 self.DrawGridLine() # top line of label
533 self.y = max_y + self.label_space
534
535
536 def PrintHeader(self): # print the header array
537 if self.draw == False:
538 return
539
540 for val in self.parent.header:
541 self.SetPrintFont(val["Font"])
542
543 header_indent = val["Indent"] * self.pwidth
544 text = val["Text"]
545
546 htype = val["Type"]
547 if htype == "Date":
548 addtext = self.GetDate()
549 elif htype == "Date & Time":
550 addtext = self.GetDateTime()
551 else:
552 addtext = ""
553
554 self.OutTextPageWidth(text+addtext, self.pheader_margin, val["Align"], header_indent, True)
555
556
557 def PrintFooter(self): # print the header array
558 if self.draw == False:
559 return
560
561 footer_pos = self.parent.page_height * self.pheight - self.pfooter_margin + self.vertical_offset
562 for val in self.parent.footer:
563 self.SetPrintFont(val["Font"])
564
565 footer_indent = val["Indent"] * self.pwidth
566 text = val["Text"]
567
568 ftype = val["Type"]
569 if ftype == "Pageof":
570 addtext = "Page " + str(self.page) + " of " + str(self.total_pages)
571 elif ftype == "Page":
572 addtext = "Page " + str(self.page)
573 elif ftype == "Num":
574 addtext = str(self.page)
575 elif ftype == "Date":
576 addtext = self.GetDate()
577 elif ftype == "Date & Time":
578 addtext = self.GetDateTime()
579 else:
580 addtext = ""
581
582 self.OutTextPageWidth(text+addtext, footer_pos, val["Align"], footer_indent, True)
583
584
585 def LabelColorRow(self, colour):
586 brush = wx.Brush(colour, wx.SOLID)
587 self.DC.SetBrush(brush)
588 height = self.label_space + self.label_pt_space_before + self.label_pt_space_after
589 self.DC.DrawRectangle(self.column[0], self.y,
590 self.end_x-self.column[0]+1, height)
591
592
593 def ColourRowCells(self, height):
594 if self.draw == False:
595 return
596
597 col = 0
598 for colour in self.column_bgcolour:
599 cellcolour = self.GetCellColour(self.data_cnt, col)
600 if cellcolour is not None:
601 colour = cellcolour
602
603 brush = wx.Brush(colour, wx.SOLID)
604 self.DC.SetBrush(brush)
605 self.DC.SetPen(wx.Pen(wx.Colour('WHITE'), 0))
606
607 start_x = self.column[col]
608 width = self.column[col+1] - start_x + 2
609 self.DC.DrawRectangle(int(start_x), int(self.y), int(width), int(height))
610 col = col + 1
611
612
613 def PrintRow(self, row_val, draw = True, align = wx.ALIGN_LEFT):
614 self.SetPrintFont(self.text_font)
615
616 self.pt_space_before = self.text_pt_space_before # set the point spacing
617 self.pt_space_after = self.text_pt_space_after
618
619 self.col = 0
620 max_y = 0
621 for vtxt in row_val:
622 if not isinstance(vtxt, str):
623 vtxt = str(vtxt)
624 self.region = self.column[self.col+1] - self.column[self.col]
625 self.indent = self.column[self.col]
626 self.align = self.column_align[self.col]
627
628 fcolour = self.column_txtcolour[self.col] # set font colour
629 celltext = self.GetCellTextColour(self.data_cnt, self.col)
630 if celltext is not None:
631 fcolour = celltext # override the column colour
632
633 self.DC.SetTextForeground(fcolour)
634
635 max_out = self.OutTextRegion(vtxt, draw)
636 if max_out > max_y:
637 max_y = max_out
638 self.col = self.col + 1
639 return max_y
640
641
642 def GetCellColour(self, row, col): # check if custom colour defined for the cell background
643 try:
644 set = self.cell_colour[row]
645 except:
646 return None
647 try:
648 colour = set[col]
649 return colour
650 except:
651 return None
652
653
654 def GetCellTextColour(self, row, col): # check if custom colour defined for the cell text
655 try:
656 set = self.cell_text[row]
657 except:
658 return None
659 try:
660 colour = set[col]
661 return colour
662 except:
663 return None
664
665
666 def FinishDraw(self):
667 self.DrawGridLine() # draw last row line
668 self.DrawColumns() # draw all vertical lines
669
670
671 def DrawGridLine(self):
672 if self.draw == True \
673 and len(self.column) > 2: #supress grid lines if only one column
674 try:
675 size = self.row_line_size[self.data_cnt]
676 except:
677 size = self.row_def_line_size
678
679 if size < 1: return
680
681 try:
682 colour = self.row_line_colour[self.data_cnt]
683 except:
684 colour = self.row_def_line_colour
685
686 self.DC.SetPen(wx.Pen(colour, size))
687
688 y_out = self.y
689 #y_out = self.y + self.pt_space_before + self.pt_space_after # adjust for extra spacing
690 self.DC.DrawLine(self.column[0], y_out, self.end_x, y_out)
691
692
693 def DrawColumns(self):
694 if self.draw == True \
695 and len(self.column) > 2: #surpress grid line if only one column
696 col = 0
697 for val in self.column:
698 try:
699 size = self.column_line_size[col]
700 except:
701 size = self.column_def_line_size
702
703 if size < 1: continue
704
705 try:
706 colour = self.column_line_colour[col]
707 except:
708 colour = self.column_def_line_colour
709
710 indent = val
711
712 self.DC.SetPen(wx.Pen(colour, size))
713 self.DC.DrawLine(indent, self.y_start, indent, self.y)
714 col = col + 1
715
716
717 def DrawText(self):
718 self.DoRefresh()
719
720
721 def DoDrawing(self, DC):
722 size = DC.GetSize()
723 self.DC = DC
724
725 self.DrawText()
726
727 self.sizew = DC.MaxY()
728 self.sizeh = DC.MaxX()
729
730 #-------------------------------------------------------------------------------
731
732 class PrintTable(object):
733 """
734 ...
735 """
736 def __init__(self, parentFrame=None):
737 self.data = []
738 self.set_column = []
739 self.label = []
740 self.header = []
741 self.footer = []
742
743 self.set_column_align = {}
744 self.set_column_bgcolour = {}
745 self.set_column_txtcolour = {}
746 self.set_cell_colour = {}
747 self.set_cell_text = {}
748 self.column_line_size = {}
749 self.column_line_colour = {}
750 self.row_line_size = {}
751 self.row_line_colour = {}
752
753 self.parentFrame = parentFrame
754 self.SetPreviewSize()
755
756 self.printData = wx.PrintData()
757 self.scale = 1.0
758
759 self.SetParms()
760 self.SetColors()
761 self.SetFonts()
762 self.TextSpacing()
763
764 self.SetPrinterOffset()
765 self.SetHeaderValue()
766 self.SetFooterValue()
767 self.SetMargins()
768 self.SetPortrait()
769
770 #---------------------------------------------------------------------------
771
772 def SetPreviewSize(self, position = wx.Point(0, 0), size="Full"):
773 if size == "Full":
774 r = wx.GetClientDisplayRect()
775 self.preview_frame_size = r.GetSize()
776 self.preview_frame_pos = r.GetPosition()
777 else:
778 self.preview_frame_size = size
779 self.preview_frame_pos = position
780
781
782 def SetPaperId(self, paper):
783 self.printData.SetPaperId(paper)
784
785
786 def SetOrientation(self, orient):
787 self.printData.SetOrientation(orient)
788
789
790 def SetColors(self):
791 self.row_def_line_colour = wx.Colour('BLACK')
792 self.row_def_line_size = 1
793
794 self.column_def_line_colour = wx.Colour('BLACK')
795 self.column_def_line_size = 1
796 self.column_colour = wx.Colour('WHITE')
797
798 self.label_colour = wx.Colour('LIGHT GREY')
799
800
801 def SetFonts(self):
802 self.label_font = { "Name": self.default_font_name, "Size": 12, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
803 self.text_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
804
805
806 def TextSpacing(self):
807 self.label_pt_adj_before = 0 # point adjustment before and after the label text
808 self.label_pt_adj_after = 0
809
810 self.text_pt_adj_before = 0 # point adjustment before and after the row text
811 self.text_pt_adj_after = 0
812
813
814 def SetLabelSpacing(self, before, after): # method to set the label space adjustment
815 self.label_pt_adj_before = before
816 self.label_pt_adj_after = after
817
818
819 def SetRowSpacing(self, before, after): # method to set the row space adjustment
820 self.text_pt_adj_before = before
821 self.text_pt_adj_after = after
822
823
824 def SetPrinterOffset(self): # offset to adjust for printer
825 self.vertical_offset = -0.1
826 self.horizontal_offset = -0.1
827
828
829 def SetHeaderValue(self):
830 self.header_margin = 0.25
831 self.header_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
832 self.header_align = wx.ALIGN_CENTRE
833 self.header_indent = 0
834 self.header_type = "Text"
835
836
837 def SetFooterValue(self):
838 self.footer_margin = 0.7
839 self.footer_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
840 self.footer_align = wx.ALIGN_CENTRE
841 self.footer_indent = 0
842 self.footer_type = "Pageof"
843
844
845 def SetMargins(self):
846 self.left_margin = 0.5
847 self.right_margin = 0.5 # only used if no column sizes
848
849 self.top_margin = 0.8
850 self.bottom_margin = 1.0
851 self.cell_left_margin = 0.1
852 self.cell_right_margin = 0.1
853
854
855 def SetPortrait(self):
856 self.printData.SetPaperId(wx.PAPER_LETTER)
857 self.printData.SetOrientation(wx.PORTRAIT)
858 self.page_width = 8.5
859 self.page_height = 11.0
860
861
862 def SetLandscape(self):
863 self.printData.SetOrientation(wx.LANDSCAPE)
864 self.page_width = 11.0
865 self.page_height = 8.5
866
867
868 def SetParms(self):
869 self.ymax = 1
870 self.xmax = 1
871 self.page = 1
872 self.total_pg = 100
873
874 self.preview = None
875 self.page = 0
876
877 self.default_font_name = "Arial"
878 self.default_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
879
880
881 def SetColAlignment(self, col, align=wx.ALIGN_LEFT):
882 self.set_column_align[col] = align
883
884
885 def SetColBackgroundColour(self, col, colour):
886 self.set_column_bgcolour[col] = colour
887
888
889 def SetColTextColour(self, col, colour):
890 self.set_column_txtcolour[col] = colour
891
892
893 def SetCellColour(self, row, col, colour): # cell background colour
894 try:
895 set = self.set_cell_colour[row] # test if row already exists
896 try:
897 set[col] = colour # test if column already exists
898 except:
899 set = { col: colour } # create the column value
900 except:
901 set = { col: colour } # create the column value
902
903 self.set_cell_colour[row] = set # create dictionary item for colour settings
904
905
906 def SetCellText(self, row, col, colour): # font colour for custom cells
907 try:
908 set = self.set_cell_text[row] # test if row already exists
909 try:
910 set[col] = colour # test if column already exists
911 except:
912 set = { col: colour } # create the column value
913 except:
914 set = { col: colour } # create the column value
915
916 self.set_cell_text[row] = set # create dictionary item for colour settings
917
918
919 def SetColumnLineSize(self, col, size): # column line size
920 self.column_line_size[col] = size # create dictionary item for column line settings
921
922
923 def SetColumnLineColour(self, col, colour):
924 self.column_line_colour[col] = colour
925
926
927 def SetRowLineSize(self, row, size):
928 self.row_line_size[row] = size
929
930
931 def SetRowLineColour(self, row, colour):
932 self.row_line_colour[row] = colour
933
934
935 def GetColour(self, colour): # returns colours based from wxColour value
936 red = colour.Red()
937 blue = colour.Blue()
938 green = colour.Green()
939 return [red, green, blue ]
940
941
942 def SetHeader(self, text = "", type = "Text", font=None, align = None, indent = None, colour = None, size = None):
943 set = { "Text": text }
944
945 if font is None:
946 set["Font"] = copy.copy(self.default_font)
947 else:
948 set["Font"] = font
949
950 if colour is not None:
951 setfont = set["Font"]
952 setfont["Colour"] = self.GetColour(colour)
953
954 if size is not None:
955 setfont = set["Font"]
956 setfont["Size"] = size
957
958 if align is None:
959 set["Align"] = self.header_align
960 else:
961 set["Align"] = align
962
963 if indent is None:
964 set["Indent"] = self.header_indent
965 else:
966 set["Indent"] = indent
967
968 if type is None:
969 set["Type"] = self.header_type
970 else:
971 set["Type"] = type
972
973 self.header.append(set)
974
975
976 def SetFooter(self, text = "", type = None, font=None, align = None, indent = None, colour = None, size = None):
977 set = { "Text": text }
978
979 if font is None:
980 set["Font"] = copy.copy(self.default_font)
981 else:
982 set["Font"] = font
983
984 if colour is not None:
985 setfont = set["Font"]
986 setfont["Colour"] = self.GetColour(colour)
987
988 if size is not None:
989 setfont = set["Font"]
990 setfont["Size"] = size
991
992 if align is None:
993 set["Align"] = self.footer_align
994 else:
995 set["Align"] = align
996
997 if indent is None:
998 set["Indent"] = self.footer_indent
999 else:
1000 set["Indent"] = indent
1001
1002 if type is None:
1003 set["Type"] = self.footer_type
1004 else:
1005 set["Type"] = type
1006
1007 self.footer.append(set)
1008
1009
1010 def Preview(self):
1011 data = wx.PrintDialogData(self.printData)
1012
1013 text = self.parentFrame.tc.GetValue()
1014
1015 printout = SetPrintout(self, text)
1016 printout2 = SetPrintout(self, text)
1017 self.preview = wx.PrintPreview(printout, printout2, data)
1018 if not self.preview.IsOk():
1019 wx.MessageBox("There was a problem printing!", "Printing", wx.OK)
1020 return
1021
1022 self.preview.SetZoom(60) # initial zoom value
1023 frame = wx.PreviewFrame(self.preview, self.parentFrame, "Print preview")
1024
1025 frame.Initialize()
1026 if self.parentFrame:
1027 frame.SetPosition(self.preview_frame_pos)
1028 frame.SetSize(self.preview_frame_size)
1029 frame.Show(True)
1030
1031
1032 def Print(self):
1033 pdd = wx.PrintDialogData(self.printData)
1034 printer = wx.Printer(pdd)
1035
1036 text = self.parentFrame.tc.GetValue()
1037
1038 printout = SetPrintout(self, text)
1039 if not printer.Print(self.parentFrame, printout):
1040 if wx.Printer.GetLastError() == wx.PRINTER_ERROR:
1041 wx.MessageBox("There was a problem printing.\n"
1042 "Perhaps your current printer is not set correctly?",
1043 "Printing", wx.OK)
1044 else:
1045 self.printData = wx.PrintData( printer.GetPrintDialogData().GetPrintData() )
1046 printout.Destroy()
1047
1048
1049 def DoDrawing(self, DC):
1050 size = DC.GetSize()
1051
1052 table = PrintTableDraw(self, DC, size)
1053 table.data = self.data
1054 table.set_column = self.set_column
1055 table.label = self.label
1056 table.SetPage(self.page)
1057
1058 if self.preview is None:
1059 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
1060 table.SetPTSize(size[0], size[1])
1061 table.SetPreview(False)
1062 else:
1063 if self.preview == 1:
1064 table.scale = self.scale
1065 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
1066 else:
1067 table.SetPSize(self.pwidth, self.pheight)
1068
1069 table.SetPTSize(self.ptwidth, self.ptheight)
1070 table.SetPreview(self.preview)
1071
1072 table.OutCanvas()
1073 self.page_total = table.total_pages # total display pages
1074
1075 self.ymax = DC.MaxY()
1076 self.xmax = DC.MaxX()
1077
1078 self.sizeh = size[0]
1079 self.sizew = size[1]
1080
1081
1082 def GetTotalPages(self):
1083 self.page_total = 100
1084 return self.page_total
1085
1086
1087 def HasPage(self, page):
1088 if page <= self.page_total:
1089 return True
1090 else:
1091 return False
1092
1093
1094 def SetPage(self, page):
1095 self.page = page
1096
1097
1098 def SetPageSize(self, width, height):
1099 self.pwidth, self.pheight = width, height
1100
1101
1102 def SetTotalSize(self, width, height):
1103 self.ptwidth, self.ptheight = width, height
1104
1105
1106 def SetPreview(self, preview, scale):
1107 self.preview = preview
1108 self.scale = scale
1109
1110
1111 def SetTotalSize(self, width, height):
1112 self.ptwidth = width
1113 self.ptheight = height
1114
1115 #-------------------------------------------------------------------------------
1116
1117 class PrintGrid(object):
1118 """
1119 ...
1120 """
1121 def __init__(self, parent, grid, format = [], total_col = None, total_row = None):
1122 if total_row is None:
1123 total_row = grid.GetNumberRows()
1124 if total_col is None:
1125 total_col = grid.GetNumberCols()
1126
1127 self.total_row = total_row
1128 self.total_col = total_col
1129 self.grid = grid
1130
1131 data = []
1132 for row in range(total_row):
1133 row_val = []
1134 value = grid.GetRowLabelValue(row)
1135 row_val.append(value)
1136
1137 for col in range(total_col):
1138 value = grid.GetCellValue(row, col)
1139 row_val.append(value)
1140 data.append(row_val)
1141
1142 label = [""]
1143 for col in range(total_col):
1144 value = grid.GetColLabelValue(col)
1145 label.append(value)
1146
1147 self.table = PrintTable(parent)
1148 self.table.cell_left_margin = 0.0
1149 self.table.cell_right_margin = 0.0
1150
1151 self.table.label = label
1152 self.table.set_column = format
1153 self.table.data = data
1154
1155 #---------------------------------------------------------------------------
1156
1157 def GetTable(self):
1158 return self.table
1159
1160
1161 def SetAttributes(self):
1162 for row in range(self.total_row):
1163 for col in range(self.total_col):
1164 colour = self.grid.GetCellTextColour(row, col-1)
1165 self.table.SetCellText(row, col, colour)
1166
1167 colour = self.grid.GetCellBackgroundColour(row, col-1)
1168 self.table.SetCellColour(row, col, colour)
1169
1170
1171 def Preview(self):
1172 self.table.Preview()
1173
1174
1175 def Print(self):
1176 self.table.Print()
1177
1178 #-------------------------------------------------------------------------------
1179
1180 class SetPrintout(wx.Printout):
1181 """
1182 ...
1183 """
1184 def __init__(self, canvas, text):
1185 wx.Printout.__init__(self)
1186
1187 self.canvas = canvas
1188 self.end_pg = 1000
1189 self.lines = text
1190
1191 #---------------------------------------------------------------------------
1192
1193 def OnBeginDocument(self, start, end):
1194 return super(SetPrintout, self).OnBeginDocument(start, end)
1195
1196
1197 def OnEndDocument(self):
1198 super(SetPrintout, self).OnEndDocument()
1199
1200
1201 def HasPage(self, page):
1202 try:
1203 end = self.canvas.HasPage(page)
1204 return end
1205 except:
1206 return True
1207
1208
1209 def GetPageInfo(self):
1210 try:
1211 self.end_pg = self.canvas.GetTotalPages()
1212 except:
1213 pass
1214
1215 end_pg = self.end_pg
1216 str_pg = 1
1217 return (str_pg, end_pg, str_pg, end_pg)
1218
1219
1220 def OnPreparePrinting(self):
1221 super(SetPrintout, self).OnPreparePrinting()
1222
1223
1224 def OnBeginPrinting(self):
1225 dc = self.GetDC()
1226
1227 self.preview = self.IsPreview()
1228 if (self.preview):
1229 self.pixelsPerInch = self.GetPPIScreen()
1230 else:
1231 self.pixelsPerInch = self.GetPPIPrinter()
1232
1233 (w, h) = dc.GetSize()
1234 scaleX = float(w) / 1000
1235 scaleY = float(h) / 1000
1236 self.printUserScale = min(scaleX, scaleY)
1237
1238 super(SetPrintout, self).OnBeginPrinting()
1239
1240
1241 def GetSize(self):
1242 self.psizew, self.psizeh = self.GetPPIPrinter()
1243 return self.psizew, self.psizeh
1244
1245
1246 def GetTotalSize(self):
1247 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1248 return self.ptsizew, self.ptsizeh
1249
1250
1251 def OnPrintPage(self, page):
1252 dc = self.GetDC()
1253 (w, h) = dc.GetSize()
1254 scaleX = float(w) / 1000
1255 scaleY = float(h) / 1000
1256 self.printUserScale = min(scaleX, scaleY)
1257 dc.SetUserScale(self.printUserScale, self.printUserScale)
1258
1259 self.preview = self.IsPreview()
1260
1261 self.canvas.SetPreview(self.preview, self.printUserScale)
1262 self.canvas.SetPage(page)
1263
1264 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1265 self.canvas.SetTotalSize(self.ptsizew, self.ptsizeh)
1266
1267 self.psizew, self.psizeh = self.GetPPIPrinter()
1268 self.canvas.SetPageSize(self.psizew, self.psizeh)
1269
1270 self.canvas.DoDrawing(dc)
1271 return True
1272
1273 #-------------------------------------------------------------------------------
1274
1275 class Frame(wx.Frame):
1276 """
1277 ...
1278 """
1279 def __init__(self, parent, id, title=""):
1280 wx.Frame.__init__(self,
1281 parent,
1282 id,
1283 title,
1284 size=(600, 450),
1285 style=wx.DEFAULT_FRAME_STYLE)
1286
1287 #------------
1288
1289 # Simplified init method.
1290 self.SetProperties()
1291 self.CreateMenu()
1292 self.CreateCtrls()
1293 self.CreatePrintData()
1294 self.BindEvents()
1295 self.DoLayout()
1296
1297 #------------
1298
1299 self.CenterOnScreen()
1300
1301 #---------------------------------------------------------------------------
1302
1303 def SetProperties(self):
1304 """
1305 Set the main frame properties (title, icon...).
1306 """
1307
1308 self.SetTitle("Dummy wx frame for testing printout.py")
1309
1310
1311 def CreateMenu(self):
1312 """
1313 ...
1314 """
1315
1316 menub = wx.MenuBar()
1317
1318 fmenu = wx.Menu()
1319 fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
1320 fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
1321 fmenu.AppendSeparator()
1322 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
1323 menub.Append(fmenu, "&File")
1324
1325 self.SetMenuBar(menub)
1326
1327
1328 def CreateCtrls(self):
1329 """
1330 ...
1331 """
1332
1333 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
1334 font.SetWeight(wx.BOLD)
1335 font.SetPointSize(10)
1336
1337 #------------
1338
1339 # First create the controls.
1340 self.panel = wx.Panel(self, -1,
1341 style=wx.BORDER_THEME|
1342 wx.TAB_TRAVERSAL)
1343
1344 self.demo = wx.StaticText(self.panel,
1345 id=-1,
1346 label="Demonstrating :")
1347 self.demo.SetFont(font)
1348
1349 self.info = wx.StaticText(self.panel,
1350 id=-1,
1351 label="1) Direct printing,\n"
1352 "2) Printout class,\n"
1353 "3) PrintTable class,\n"
1354 "4) Preview,\n"
1355 "5) Menu")
1356 self.info.SetForegroundColour("red")
1357 font.SetWeight(wx.NORMAL)
1358 self.info.SetFont(font)
1359
1360 text = ('This the first line of text.\n'\
1361 'This is the second line\nand the third. The fourth will be the number 4.0.\n'\
1362 '4.0\n'\
1363 'This is the fifth line, but by design it is too long to fit in the width of a standard'\
1364 'page, so it will be forced to wrap around in order to fit without having'\
1365 'some of its verbose verbage truncated.\n'\
1366 'Here we have the final line.')
1367
1368 self.tc = wx.TextCtrl(self.panel,
1369 id=-1,
1370 size=(200, -1),
1371 value=text,
1372 style=wx.TE_MULTILINE|wx.TE_DONTWRAP)
1373
1374 self.btnPreview = wx.Button(self.panel,
1375 id=wx.ID_PREVIEW,
1376 label="Print pre&view")
1377 self.btnPreview.SetFocus()
1378
1379 self.btnPrint = wx.Button(self.panel,
1380 id=wx.ID_PRINT,
1381 label="&Print")
1382
1383 self.btnClose = wx.Button(self.panel,
1384 id=wx.ID_CLOSE,
1385 label="E&xit")
1386
1387
1388 def CreatePrintData(self):
1389 """
1390 Create printing data.
1391 """
1392
1393 self.ptbl = PrintTable(self)
1394 self.ptbl.SetHeader('This is the test HEADER')
1395 self.ptbl.SetFooter()
1396
1397 #------------
1398
1399 # a single sequence will print out as a single column with no borders ...
1400 self.ptbl.data = (self.tc.GetValue())
1401
1402
1403 def BindEvents(self):
1404 """
1405 Bind all the events related to my application.
1406 """
1407
1408 # Bind some menu events to an events handler.
1409 self.Bind(wx.EVT_MENU, self.OnPrintPreview, id=wx.ID_PREVIEW)
1410 self.Bind(wx.EVT_MENU, self.OnPrint, id=wx.ID_PRINT)
1411 self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_EXIT)
1412
1413 # Bind the close event to an event handler.
1414 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
1415
1416 # Bind some buttons events to an events handler.
1417 self.Bind(wx.EVT_BUTTON, self.OnPrintPreview, self.btnPreview)
1418 self.Bind(wx.EVT_BUTTON, self.OnPrint, self.btnPrint)
1419 self.Bind(wx.EVT_BUTTON, self.OnClose, self.btnClose)
1420
1421
1422 def DoLayout(self):
1423 """
1424 Manage widgets Layout.
1425 """
1426
1427 # MainSizer is the top-level one that manages everything.
1428 mainSizer = wx.BoxSizer(wx.VERTICAL)
1429
1430 #------------
1431
1432 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
1433 hBox1.Add(self.info, 0, wx.ALL, 15)
1434
1435 #------------
1436
1437 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
1438 hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
1439 hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
1440 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
1441
1442 #------------
1443
1444 mainSizer.Add(self.demo, 0, wx.ALL, 10)
1445 mainSizer.Add(wx.StaticLine(self.panel),
1446 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
1447 mainSizer.Add(self.tc, 1, wx.EXPAND | wx.ALL, 15)
1448 mainSizer.Add(hBox1, 0, wx.ALL, 5)
1449 mainSizer.Add(hBox2, 0, wx.ALL, 5)
1450
1451 #------------
1452
1453 # Finally, tell the panel to use the mainSizer for layout.
1454 self.panel.SetSizer(mainSizer)
1455
1456
1457 def OnPrintPreview(self, event):
1458 self.ptbl.data = (self.tc.GetValue())
1459 self.ptbl.Preview()
1460
1461
1462 def OnPrint(self, event):
1463 self.ptbl.data = (self.tc.GetValue())
1464 self.ptbl.Print()
1465
1466
1467 def OnClose(self, evt):
1468 self.Close()
1469
1470
1471 def OnCloseWindow(self, event):
1472 """
1473 ...
1474 """
1475
1476 self.Destroy()
1477
1478 #-------------------------------------------------------------------------------
1479
1480 class App(wx.App):
1481 """
1482 ...
1483 """
1484 def OnInit(self):
1485
1486 #------------
1487
1488 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
1489
1490 #------------
1491
1492 frame = Frame(None, id=-1)
1493 self.SetTopWindow(frame)
1494 frame.Show(True)
1495
1496 return True
1497
1498 #-------------------------------------------------------------------------------
1499
1500 def main():
1501 app = App(False)
1502 app.MainLoop()
1503
1504 #-------------------------------------------------------------------------------
1505
1506 if __name__ == "__main__" :
1507 main()
Grid Printing :
First example
1 # sample_five_a.py
2
3 #-------------------------------------------------------------------------------
4 # Name: printout.py
5 # Purpose: preview and printing class -> table/grid printing
6 #
7 # Author: Lorne White (email: lorne.white@telusplanet.net)
8 #
9 # Created:
10 # Version: 0.75
11 # Date: May 15, 2002
12 # Licence: wxWindows license
13 #-------------------------------------------------------------------------------
14 # Link:
15 # https://raw.githubusercontent.com/wxWidgets/wxPython/master/wx/lib/printout.py
16 #-------------------------------------------------------------------------------
17 # Release Notes :
18 # fixed bug for string wider than print region
19 # add index to data list after parsing total pages for paging
20 #-------------------------------------------------------------------------------
21 # 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
22 # o 2.5 compatability update.
23 #-------------------------------------------------------------------------------
24 # 11/23/2004 - Vernon Cole (wnvcole@peppermillcas.com)
25 # o Generalize for non-2-dimensional sequences and non-text data
26 # (can use as a simple text printer by supplying a list of strings.)
27 # o Add a small _main_ for self test
28 #-------------------------------------------------------------------------------
29
30 import os
31 import copy
32 import wx
33 from wx import grid
34
35 # class PrintBase
36 # class PrintTableDraw
37 # class PrintTable
38 # class PrintGrid
39 # class SetPrintout
40 # class Frame
41 # class App
42
43 #-------------------------------------------------------------------------------
44
45 if os.name == "posix":
46 print("\nPlatform : UNIX - Linux")
47 elif os.name in ['nt', 'dos', 'ce']:
48 print("\nPlatform : Windows")
49 else:
50 print("\nPlatform : ", platform.system())
51
52 #-------------------------------------------------------------------------------
53
54 class PrintBase(object):
55 """
56 ...
57 """
58 def SetPrintFont(self, font): # set the DC font parameters
59 fattr = font["Attr"]
60 if fattr[0] == 1:
61 weight = wx.BOLD
62 else:
63 weight = wx.NORMAL
64
65 if fattr[1] == 1:
66 set_style = wx.ITALIC
67 else:
68 set_style = wx.NORMAL
69
70 underline = fattr[2]
71 fcolour = self.GetFontColour(font)
72 self.DC.SetTextForeground(fcolour)
73
74 setfont = wx.Font(font["Size"], wx.SWISS, set_style, weight, underline)
75 setfont.SetFaceName(font["Name"])
76 self.DC.SetFont(setfont)
77
78 #---------------------------------------------------------------------------
79
80 def GetFontColour(self, font):
81 fcolour = font["Colour"]
82 return wx.Colour(fcolour[0], fcolour[1], fcolour[2])
83
84
85 def OutTextRegion(self, textout, txtdraw = True):
86 textlines = textout.split('\n')
87 y = copy.copy(self.y) + self.pt_space_before
88 for text in textlines:
89 remain = 'X'
90 while remain != "":
91 vout, remain = self.SetFlow(text, self.region)
92 if self.draw == True and txtdraw == True:
93 test_out = self.TestFull(vout)
94 if self.align == wx.ALIGN_LEFT:
95 self.DC.DrawText(test_out, int(self.indent+self.pcell_left_margin), int(y))
96
97 elif self.align == wx.ALIGN_CENTRE:
98 diff = self.GetCellDiff(test_out, self.region)
99 self.DC.DrawText(test_out, self.indent+diff/2, y)
100
101 elif self.align == wx.ALIGN_RIGHT:
102 diff = self.GetCellDiff(test_out, self.region)
103 self.DC.DrawText(test_out, self.indent+diff, y)
104
105 else:
106 self.DC.DrawText(test_out, int(self.indent+self.pcell_left_margin), int(y))
107 text = remain
108 y = y + self.space
109 return y - self.space + self.pt_space_after
110
111
112 def GetCellDiff(self, text, width): # get the remaining cell size for adjustment
113 w, h = self.DC.GetTextExtent(text)
114 diff = width - w
115 if diff < 0:
116 diff = 0
117 return diff
118
119
120 def TestFull(self, text_test):
121 w, h = self.DC.GetTextExtent(text_test)
122 if w > self.region: # trouble fitting into cell
123 return self.SetChar(text_test, self.region) # fit the text to the cell size
124 else:
125 return text_test
126
127
128 def SetFlow(self, ln_text, width):
129 width = width - self.pcell_right_margin
130 text = ""
131 split = ln_text.split()
132 if len(split) == 1:
133 return ln_text, ""
134
135 try:
136 w, h = self.DC.GetTextExtent(" " + split[0])
137 if w >= width:
138 return ln_text, ""
139 except:
140 pass
141
142 cnt = 0
143 for word in split:
144 bword = " " + word # blank + word
145 length = len(bword)
146
147 w, h = self.DC.GetTextExtent(text + bword)
148 if w < width:
149 text = text + bword
150 cnt = cnt + 1
151 else:
152 remain = ' '.join(split[cnt:])
153 text = text.strip()
154 return text, remain
155
156 remain = ' '.join(split[cnt:])
157 vout = text.strip()
158 return vout, remain
159
160
161 def SetChar(self, ln_text, width): # truncate string to fit into width
162 width = width - self.pcell_right_margin - self.pcell_left_margin
163 text = ""
164 for val in ln_text:
165 w, h = self.DC.GetTextExtent(text + val)
166 if w > width:
167 text = text + ".."
168 return text # fitted text value
169 text = text + val
170 return text
171
172
173 def OutTextPageWidth(self, textout, y_out, align, indent, txtdraw = True):
174 textlines = textout.split('\n')
175 y = copy.copy(y_out)
176
177 pagew = self.parent.page_width * self.pwidth # full page width
178 w, h = self.DC.GetTextExtent(textout)
179 y_line = h
180
181 for text in textlines:
182 remain = 'X'
183 while remain != "":
184 vout, remain = self.SetFlow(text, pagew)
185 if self.draw == True and txtdraw == True:
186 test_out = vout
187 if align == wx.ALIGN_LEFT:
188 self.DC.DrawText(test_out, indent, y)
189
190 elif align == wx.ALIGN_CENTRE:
191 diff = self.GetCellDiff(test_out, pagew)
192 self.DC.DrawText(test_out, int(indent+diff/2), int(y))
193
194 elif align == wx.ALIGN_RIGHT:
195 diff = self.GetCellDiff(test_out, pagew)
196 self.DC.DrawText(test_out, int(indent+diff), int(y))
197
198 else:
199 self.DC.DrawText(test_out, indent, y_out)
200 text = remain
201 y = y + y_line
202 return y - y_line
203
204
205 def GetDate(self):
206 date, time = self.GetNow()
207 return date
208
209
210 def GetDateTime(self):
211 date, time = self.GetNow()
212 return '%s %s' % (date, time)
213
214
215 def GetNow(self):
216 now = wx.DateTime.Now()
217 date = now.FormatDate()
218 time = now.FormatTime()
219 return date, time
220
221
222 def SetPreview(self, preview):
223 self.preview = preview
224
225
226 def SetPSize(self, width, height):
227 self.pwidth = width/self.scale
228 self.pheight = height/self.scale
229
230
231 def SetScale(self, scale):
232 self.scale = scale
233
234
235 def SetPTSize(self, width, height):
236 self.ptwidth = width
237 self.ptheight = height
238
239
240 def getWidth(self):
241 return self.sizew
242
243
244 def getHeight(self):
245 return self.sizeh
246
247 #-------------------------------------------------------------------------------
248
249 class PrintTableDraw(wx.ScrolledWindow, PrintBase):
250 """
251 ...
252 """
253 def __init__(self, parent, DC, size, colLabels=True):
254 self.parent = parent
255 self.DC = DC
256 self.scale = parent.scale
257 self.width = size[0]
258 self.height = size[1]
259 self.colLabels = colLabels
260 self.SetDefaults()
261
262 #---------------------------------------------------------------------------
263
264 def SetDefaults(self):
265 self.page = 1
266 self.total_pages = None
267
268 self.page_width = self.parent.page_width
269 self.page_height = self.parent.page_height
270
271 self.left_margin = self.parent.left_margin
272 self.right_margin = self.parent.right_margin
273
274 self.top_margin = self.parent.top_margin
275 self.bottom_margin = self.parent.bottom_margin
276 self.cell_left_margin = self.parent.cell_left_margin
277 self.cell_right_margin = self.parent.cell_right_margin
278
279 self.label_colour = self.parent.label_colour
280
281 self.row_line_colour = self.parent.row_line_colour
282 self.row_line_size = self.parent.row_line_size
283
284 self.row_def_line_colour = self.parent.row_def_line_colour
285 self.row_def_line_size = self.parent.row_def_line_size
286
287 self.column_line_colour = self.parent.column_line_colour
288 self.column_line_size = self.parent.column_line_size
289
290 self.column_def_line_size = self.parent.column_def_line_size
291 self.column_def_line_colour = self.parent.column_def_line_colour
292
293 self.text_font = self.parent.text_font
294
295 self.label_font = self.parent.label_font
296
297
298 def AdjustValues(self):
299 self.vertical_offset = self.pheight * self.parent.vertical_offset
300 self.horizontal_offset = self.pheight * self.parent.horizontal_offset
301
302 self.pcell_left_margin = self.pwidth * self.cell_left_margin
303 self.pcell_right_margin = self.pwidth * self.cell_right_margin
304 self.ptop_margin = self.pheight * self.top_margin
305 self.pbottom_margin = self.pheight * self.bottom_margin
306
307 self.pheader_margin = self.pheight * self.parent.header_margin
308 self.pfooter_margin = self.pheight * self.parent.footer_margin
309
310 self.cell_colour = self.parent.set_cell_colour
311 self.cell_text = self.parent.set_cell_text
312
313 self.column = []
314 self.column_align = []
315 self.column_bgcolour = []
316 self.column_txtcolour = []
317
318 set_column_align = self.parent.set_column_align
319 set_column_bgcolour = self.parent.set_column_bgcolour
320 set_column_txtcolour = self.parent.set_column_txtcolour
321
322 pos_x = self.left_margin * self.pwidth + self.horizontal_offset # left margin
323 self.column.append(pos_x)
324
325 # Module logic expects two dimensional data -- fix input if needed
326 if isinstance(self.data, str):
327 self.data = [[copy.copy(self.data)]] # a string becomes a single cell
328 try:
329 rows = len(self.data)
330 except TypeError:
331 self.data = [[str(self.data)]] # a non-iterable becomes a single cell
332 rows = 1
333 first_value = self.data[0]
334
335 if isinstance(first_value, str): # A sequence of strings
336 if self.label == [] and self.set_column == []:
337 data = []
338 for x in self.data: # Becomes one column
339 data.append([x])
340 else:
341 data = [self.data] # Becames one row
342 self.data = data
343 first_value = data[0]
344 try:
345 column_total = len(first_value)
346 except TypeError: # a sequence of non-iterables
347 if self.label == [] and self.set_column == []:
348 data = [] #becomes one column
349 for x in self.data:
350 data.append([str(x)])
351 column_total = 1
352 else:
353 data = [self.data] #becomes one row
354 column_total = len(self.data)
355 self.data = data
356 first_value = data[0]
357
358 if self.set_column == []:
359 table_width = self.page_width - self.left_margin - self.right_margin
360 if self.label == []:
361 temp = first_value
362 else:
363 temp = self.label
364 width = table_width/(len(temp))
365 for val in temp:
366 column_width = width * self.pwidth
367 pos_x = pos_x + column_width
368 self.column.append(pos_x) # position of each column
369 else:
370 for val in self.set_column:
371 column_width = val
372 pos_x = pos_x + column_width
373 self.column.append(pos_x) # position of each column
374
375 if pos_x > self.page_width * self.pwidth: # check if it fits in page
376 print("Warning, Too Wide for Page")
377 print(pos_x, self.page_width * self.pwidth)
378 return
379
380 if self.label != []:
381 if len(self.column) -1 != len(self.label):
382 print("Column Settings Incorrect", "\nColumn Value: " + str(self.column), "\nLabel Value: " + str(self.label))
383 return
384
385 if column_total != len(self.column) -1:
386 print("Cannot fit", first_value, 'in', len(self.column)-1, 'columns.')
387 return
388
389 for col in range(column_total):
390 try:
391 align = set_column_align[col] # check if custom column alignment
392 except:
393 align = wx.ALIGN_LEFT
394 self.column_align.append(align)
395
396 try:
397 colour = set_column_bgcolour[col] # check if custom column background colour
398 except:
399 colour = self.parent.column_colour
400 self.column_bgcolour.append(colour)
401
402 try:
403 colour = set_column_txtcolour[col] # check if custom column text colour
404 except:
405 colour = self.GetFontColour(self.parent.text_font)
406 self.column_txtcolour.append(colour)
407
408
409 def SetPointAdjust(self):
410 f = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL) # setup using 10 point
411 self.DC.SetFont(f)
412 f.SetFaceName(self.text_font["Name"])
413 x, y = self.DC.GetTextExtent("W")
414
415 self.label_pt_space_before = self.parent.label_pt_adj_before * y/10 # extra spacing for label per point value
416 self.label_pt_space_after = self.parent.label_pt_adj_after * y/10
417
418 self.text_pt_space_before = self.parent.text_pt_adj_before * y/10 # extra spacing for row text per point value
419 self.text_pt_space_after = self.parent.text_pt_adj_after * y/10
420
421
422 def SetPage(self, page):
423 self.page = page
424
425
426 def SetColumns(self, col):
427 self.column = col
428
429
430 def OutCanvas(self):
431 self.AdjustValues()
432 self.SetPointAdjust()
433
434 self.y_start = self.ptop_margin + self.vertical_offset
435 self.y_end = self.parent.page_height * self.pheight - self.pbottom_margin + self.vertical_offset
436
437 self.SetPrintFont(self.label_font)
438
439 x, y = self.DC.GetTextExtent("W")
440 self.label_space = y
441
442 self.SetPrintFont(self.text_font)
443
444 x, y = self.DC.GetTextExtent("W")
445 self.space = y
446
447 if self.total_pages is None:
448 self.GetTotalPages() # total pages for display/printing
449
450 self.data_cnt = self.page_index[self.page-1]
451
452 self.draw = True
453 self.PrintHeader()
454 self.PrintFooter()
455 self.OutPage()
456
457
458 def GetTotalPages(self):
459 self.data_cnt = 0
460 self.draw = False
461 self.page_index = [0]
462
463 cnt = 0
464 while 1:
465 test = self.OutPage()
466 self.page_index.append(self.data_cnt)
467 if test == False:
468 break
469 cnt = cnt + 1
470
471 self.total_pages = cnt + 1
472
473
474 def OutPage(self):
475 self.y = self.y_start
476 self.end_x = self.column[-1]
477
478 if self.data_cnt < len(self.data): # if there data for display on the page
479 if self.colLabels and self.label != []: # check if header defined
480 self.PrintLabel()
481 else:
482 return False
483
484 for val in self.data:
485 try:
486 row_val = self.data[self.data_cnt]
487 except:
488 self.FinishDraw()
489 return False
490
491 max_y = self.PrintRow(row_val, False) # test to see if row will fit in remaining space
492 test = max_y + self.space
493
494 if test > self.y_end:
495 break
496
497 self.ColourRowCells(max_y-self.y+self.space) # colour the row/column
498 max_y = self.PrintRow(row_val, True) # row fits - print text
499 self.DrawGridLine() # top line of cell
500 self.y = max_y + self.space
501
502 if self.y > self.y_end:
503 break
504
505 self.data_cnt = self.data_cnt + 1
506
507 self.FinishDraw()
508
509 if self.data_cnt == len(self.data): # last value in list
510 return False
511
512 return True
513
514
515 def PrintLabel(self):
516 self.pt_space_before = self.label_pt_space_before # set the point spacing
517 self.pt_space_after = self.label_pt_space_after
518
519 self.LabelColorRow(self.label_colour)
520 self.SetPrintFont(self.label_font)
521
522 self.col = 0
523 max_y = 0
524 for vtxt in self.label:
525 self.region = self.column[self.col+1] - self.column[self.col]
526 self.indent = self.column[self.col]
527
528 self.align = wx.ALIGN_LEFT
529
530 max_out = self.OutTextRegion(vtxt, True)
531 if max_out > max_y:
532 max_y = max_out
533 self.col = self.col + 1
534
535 self.DrawGridLine() # top line of label
536 self.y = max_y + self.label_space
537
538
539 def PrintHeader(self): # print the header array
540 if self.draw == False:
541 return
542
543 for val in self.parent.header:
544 self.SetPrintFont(val["Font"])
545
546 header_indent = val["Indent"] * self.pwidth
547 text = val["Text"]
548
549 htype = val["Type"]
550 if htype == "Date":
551 addtext = self.GetDate()
552 elif htype == "Date & Time":
553 addtext = self.GetDateTime()
554 else:
555 addtext = ""
556
557 self.OutTextPageWidth(text+addtext, self.pheader_margin, val["Align"], header_indent, True)
558
559
560 def PrintFooter(self): # print the header array
561 if self.draw == False:
562 return
563
564 footer_pos = self.parent.page_height * self.pheight - self.pfooter_margin + self.vertical_offset
565 for val in self.parent.footer:
566 self.SetPrintFont(val["Font"])
567
568 footer_indent = val["Indent"] * self.pwidth
569 text = val["Text"]
570
571 ftype = val["Type"]
572 if ftype == "Pageof":
573 addtext = "Page " + str(self.page) + " of " + str(self.total_pages)
574 elif ftype == "Page":
575 addtext = "Page " + str(self.page)
576 elif ftype == "Num":
577 addtext = str(self.page)
578 elif ftype == "Date":
579 addtext = self.GetDate()
580 elif ftype == "Date & Time":
581 addtext = self.GetDateTime()
582 else:
583 addtext = ""
584
585 self.OutTextPageWidth(text+addtext, footer_pos, val["Align"], footer_indent, True)
586
587
588 def LabelColorRow(self, colour):
589 brush = wx.Brush(colour, wx.SOLID)
590 self.DC.SetBrush(brush)
591 height = self.label_space + self.label_pt_space_before + self.label_pt_space_after
592 self.DC.DrawRectangle(self.column[0], self.y,
593 self.end_x-self.column[0]+1, height)
594
595 def ColourRowCells(self, height):
596 if self.draw == False:
597 return
598
599 col = 0
600 for colour in self.column_bgcolour:
601 cellcolour = self.GetCellColour(self.data_cnt, col)
602 if cellcolour is not None:
603 colour = cellcolour
604
605 brush = wx.Brush(colour, wx.SOLID)
606 self.DC.SetBrush(brush)
607 self.DC.SetPen(wx.Pen(wx.Colour('WHITE'), 0))
608
609 start_x = self.column[col]
610 width = self.column[col+1] - start_x + 2
611 self.DC.DrawRectangle(int(start_x), int(self.y), int(width), int(height))
612 col = col + 1
613
614
615 def PrintRow(self, row_val, draw = True, align = wx.ALIGN_LEFT):
616 self.SetPrintFont(self.text_font)
617
618 self.pt_space_before = self.text_pt_space_before # set the point spacing
619 self.pt_space_after = self.text_pt_space_after
620
621 self.col = 0
622 max_y = 0
623 for vtxt in row_val:
624 if not isinstance(vtxt, str):
625 vtxt = str(vtxt)
626 self.region = self.column[self.col+1] - self.column[self.col]
627 self.indent = self.column[self.col]
628 try:
629 self.align = self.column_align[self.col]
630 except IndexError:
631 self.align = wx.ALIGN_LEFT
632
633 try:
634 fcolour = self.column_txtcolour[self.col] # set font colour
635 except IndexError:
636 fcolour = wx.BLACK
637
638 celltext = self.GetCellTextColour(self.data_cnt, self.col)
639 if celltext is not None:
640 fcolour = celltext # override the column colour
641
642 self.DC.SetTextForeground(fcolour)
643
644 max_out = self.OutTextRegion(vtxt, draw)
645 if max_out > max_y:
646 max_y = max_out
647 self.col = self.col + 1
648 return max_y
649
650
651 def GetCellColour(self, row, col): # check if custom colour defined for the cell background
652 try:
653 set = self.cell_colour[row]
654 except:
655 return None
656 try:
657 colour = set[col]
658 return colour
659 except:
660 return None
661
662
663 def GetCellTextColour(self, row, col): # check if custom colour defined for the cell text
664 try:
665 set = self.cell_text[row]
666 except:
667 return None
668 try:
669 colour = set[col]
670 return colour
671 except:
672 return None
673
674
675 def FinishDraw(self):
676 self.DrawGridLine() # draw last row line
677 self.DrawColumns() # draw all vertical lines
678
679
680 def DrawGridLine(self):
681 if self.draw == True \
682 and len(self.column) > 2: #supress grid lines if only one column
683 try:
684 size = self.row_line_size[self.data_cnt]
685 except:
686 size = self.row_def_line_size
687
688 if size < 1: return
689
690 try:
691 colour = self.row_line_colour[self.data_cnt]
692 except:
693 colour = self.row_def_line_colour
694
695 self.DC.SetPen(wx.Pen(colour, size))
696
697 y_out = self.y
698 #y_out = self.y + self.pt_space_before + self.pt_space_after # adjust for extra spacing
699 self.DC.DrawLine(int(self.column[0]), int(y_out), int(self.end_x), int(y_out))
700
701
702 def DrawColumns(self):
703 if self.draw == True \
704 and len(self.column) > 2: #surpress grid line if only one column
705 col = 0
706 for val in self.column:
707 try:
708 size = self.column_line_size[col]
709 except:
710 size = self.column_def_line_size
711
712 if size < 1: continue
713
714 try:
715 colour = self.column_line_colour[col]
716 except:
717 colour = self.column_def_line_colour
718
719 indent = val
720
721 self.DC.SetPen(wx.Pen(colour, size))
722 self.DC.DrawLine(int(indent), int(self.y_start), int(indent), int(self.y))
723 col = col + 1
724
725
726 def DrawText(self):
727 self.DoRefresh()
728
729
730 def DoDrawing(self, DC):
731 size = DC.GetSize()
732 self.DC = DC
733
734 self.DrawText()
735
736 self.sizew = DC.MaxY()
737 self.sizeh = DC.MaxX()
738
739 #-------------------------------------------------------------------------------
740
741 class PrintTable(object):
742 """
743 ...
744 """
745 def __init__(self, parentFrame=None, rowLabels=True, colLabels=True):
746 self.data = []
747 self.set_column = []
748 self.label = []
749 self.header = []
750 self.footer = []
751 self.rowLabels = rowLabels
752 self.colLabels = colLabels
753
754 self.set_column_align = {}
755 self.set_column_bgcolour = {}
756 self.set_column_txtcolour = {}
757 self.set_cell_colour = {}
758 self.set_cell_text = {}
759 self.column_line_size = {}
760 self.column_line_colour = {}
761 self.row_line_size = {}
762 self.row_line_colour = {}
763
764 self.parentFrame = parentFrame
765 self.SetPreviewSize()
766
767 self.printData = wx.PrintData()
768 self.scale = 1.0
769
770 self.SetParms()
771 self.SetColors()
772 self.SetFonts()
773 self.TextSpacing()
774
775 self.SetPrinterOffset()
776 self.SetHeaderValue()
777 self.SetFooterValue()
778 self.SetMargins()
779 self.SetPortrait()
780
781 #---------------------------------------------------------------------------
782
783 def SetPreviewSize(self, position = wx.Point(0, 0), size="Full"):
784 if size == "Full":
785 r = wx.GetClientDisplayRect()
786 self.preview_frame_size = r.GetSize()
787 self.preview_frame_pos = r.GetPosition()
788 else:
789 self.preview_frame_size = size
790 self.preview_frame_pos = position
791
792
793 def SetPaperId(self, paper):
794 self.printData.SetPaperId(paper)
795
796
797 def SetOrientation(self, orient):
798 self.printData.SetOrientation(orient)
799
800
801 def SetColors(self):
802 self.row_def_line_colour = wx.Colour('BLACK')
803 self.row_def_line_size = 1
804
805 self.column_def_line_colour = wx.Colour('BLACK')
806 self.column_def_line_size = 1
807 self.column_colour = wx.Colour('WHITE')
808
809 self.label_colour = wx.Colour('LIGHT GREY')
810
811
812 def SetFonts(self):
813 self.label_font = {"Name": self.default_font_name,
814 "Size": 12,
815 "Colour": [0, 0, 0],
816 "Attr": [0, 0, 0]
817 }
818 self.text_font = {"Name": self.default_font_name,
819 "Size": 10,
820 "Colour": [0, 0, 0],
821 "Attr": [0, 0, 0]
822 }
823
824
825 def TextSpacing(self):
826 self.label_pt_adj_before = 0 # point adjustment before and after the label text
827 self.label_pt_adj_after = 0
828
829 self.text_pt_adj_before = 0 # point adjustment before and after the row text
830 self.text_pt_adj_after = 0
831
832
833 def SetLabelSpacing(self, before, after): # method to set the label space adjustment
834 self.label_pt_adj_before = before
835 self.label_pt_adj_after = after
836
837
838 def SetRowSpacing(self, before, after): # method to set the row space adjustment
839 self.text_pt_adj_before = before
840 self.text_pt_adj_after = after
841
842
843 def SetPrinterOffset(self): # offset to adjust for printer
844 self.vertical_offset = -0.1
845 self.horizontal_offset = -0.1
846
847
848 def SetHeaderValue(self):
849 self.header_margin = 0.25
850 self.header_font = {"Name": self.default_font_name,
851 "Size": 11,
852 "Colour": [0, 0, 0],
853 "Attr": [0, 0, 0]
854 }
855 self.header_align = wx.ALIGN_CENTRE
856 self.header_indent = 0
857 self.header_type = "Text"
858
859
860 def SetFooterValue(self):
861 self.footer_margin = 0.7
862 self.footer_font = {"Name": self.default_font_name,
863 "Size": 11,
864 "Colour": [0, 0, 0],
865 "Attr": [0, 0, 0]
866 }
867 self.footer_align = wx.ALIGN_CENTRE
868 self.footer_indent = 0
869 self.footer_type = "Pageof"
870
871
872 def SetMargins(self):
873 self.left_margin = 0.5
874 self.right_margin = 0.5 # only used if no column sizes
875
876 self.top_margin = 0.8
877 self.bottom_margin = 1.0
878 self.cell_left_margin = 0.1
879 self.cell_right_margin = 0.1
880
881
882 def SetPortrait(self):
883 self.printData.SetPaperId(wx.PAPER_A4)
884 self.printData.SetOrientation(wx.PORTRAIT)
885 self.page_width = 8.267716535433071
886 self.page_height = 11.69291338582677
887
888
889 def SetLandscape(self):
890 self.printData.SetOrientation(wx.LANDSCAPE)
891 self.page_width = 8.267716535433071
892 self.page_height = 11.69291338582677
893
894
895 def SetParms(self):
896 self.ymax = 1
897 self.xmax = 1
898 self.page = 1
899 self.total_pg = 100
900
901 self.preview = None
902 self.page = 0
903
904 self.default_font_name = "Arial"
905 self.default_font = {"Name": self.default_font_name,
906 "Size": 10,
907 "Colour": [0, 0, 0],
908 "Attr": [0, 0, 0]
909 }
910
911
912 def SetColAlignment(self, col, align=wx.ALIGN_LEFT):
913 self.set_column_align[col] = align
914
915
916 def SetColBackgroundColour(self, col, colour):
917 self.set_column_bgcolour[col] = colour
918
919
920 def SetColTextColour(self, col, colour):
921 self.set_column_txtcolour[col] = colour
922
923
924 def SetCellColour(self, row, col, colour): # cell background colour
925 try:
926 set = self.set_cell_colour[row] # test if row already exists
927 try:
928 set[col] = colour # test if column already exists
929 except:
930 set = { col: colour } # create the column value
931 except:
932 set = { col: colour } # create the column value
933
934 self.set_cell_colour[row] = set # create dictionary item for colour settings
935
936
937 def SetCellText(self, row, col, colour): # font colour for custom cells
938 try:
939 set = self.set_cell_text[row] # test if row already exists
940 try:
941 set[col] = colour # test if column already exists
942 except:
943 set = { col: colour } # create the column value
944 except:
945 set = { col: colour } # create the column value
946
947 self.set_cell_text[row] = set # create dictionary item for colour settings
948
949
950 def SetColumnLineSize(self, col, size): # column line size
951 self.column_line_size[col] = size # create dictionary item for column line settings
952
953
954 def SetColumnLineColour(self, col, colour):
955 self.column_line_colour[col] = colour
956
957
958 def SetRowLineSize(self, row, size):
959 self.row_line_size[row] = size
960
961
962 def SetRowLineColour(self, row, colour):
963 self.row_line_colour[row] = colour
964
965
966 def GetColour(self, colour): # returns colours based from wxColour value
967 red = colour.Red()
968 blue = colour.Blue()
969 green = colour.Green()
970 return [red, green, blue ]
971
972
973 def SetHeader(self, text="", type="Text", font=None, align=None,
974 indent=None, colour=None, size=None):
975 set = {"Text": text}
976
977 if font is None:
978 set["Font"] = copy.copy(self.default_font)
979 else:
980 set["Font"] = font
981
982 if colour is not None:
983 setfont = set["Font"]
984 setfont["Colour"] = self.GetColour(colour)
985
986 if size is not None:
987 setfont = set["Font"]
988 setfont["Size"] = size
989
990 if align is None:
991 set["Align"] = self.header_align
992 else:
993 set["Align"] = align
994
995 if indent is None:
996 set["Indent"] = self.header_indent
997 else:
998 set["Indent"] = indent
999
1000 if type is None:
1001 set["Type"] = self.header_type
1002 else:
1003 set["Type"] = type
1004
1005 self.header.append(set)
1006
1007
1008 def SetFooter(self, text="", type=None, font=None, align=None,
1009 indent=None, colour=None, size=None):
1010 set = { "Text": text }
1011
1012 if font is None:
1013 set["Font"] = copy.copy(self.default_font)
1014 else:
1015 set["Font"] = font
1016
1017 if colour is not None:
1018 setfont = set["Font"]
1019 setfont["Colour"] = self.GetColour(colour)
1020
1021 if size is not None:
1022 setfont = set["Font"]
1023 setfont["Size"] = size
1024
1025 if align is None:
1026 set["Align"] = self.footer_align
1027 else:
1028 set["Align"] = align
1029
1030 if indent is None:
1031 set["Indent"] = self.footer_indent
1032 else:
1033 set["Indent"] = indent
1034
1035 if type is None:
1036 set["Type"] = self.footer_type
1037 else:
1038 set["Type"] = type
1039
1040 self.footer.append(set)
1041
1042
1043 def Preview(self):
1044 data = wx.PrintDialogData(self.printData)
1045 printout = SetPrintout(self)
1046 printout2 = SetPrintout(self)
1047 self.preview = wx.PrintPreview(printout, printout2, data)
1048 if not self.preview.IsOk():
1049 wx.MessageBox("There was a problem printing!", "Printing", wx.OK)
1050 return
1051
1052 self.preview.SetZoom(85) # initial zoom value
1053 frame = wx.PreviewFrame(self.preview, self.parentFrame, "Print preview")
1054
1055 frame.Initialize()
1056 if self.parentFrame:
1057 frame.SetPosition(self.preview_frame_pos)
1058 frame.SetSize(self.preview_frame_size)
1059 frame.Show(True)
1060
1061
1062 def Print(self):
1063 pdd = wx.PrintDialogData(self.printData)
1064 printer = wx.Printer(pdd)
1065 printout = SetPrintout(self)
1066 if not printer.Print(self.parentFrame, printout):
1067 if wx.Printer.GetLastError() == wx.PRINTER_ERROR:
1068 wx.MessageBox("There was a problem printing.\n"
1069 "Perhaps your current printer is not set correctly?",
1070 "Printing", wx.OK)
1071 else:
1072 self.printData = wx.PrintData( printer.GetPrintDialogData().GetPrintData() )
1073 printout.Destroy()
1074
1075
1076 def DoDrawing(self, DC):
1077 size = DC.GetSize()
1078
1079 table = PrintTableDraw(self, DC, size, self.colLabels)
1080 table.data = self.data
1081 table.set_column = self.set_column
1082 table.label = self.label
1083 table.SetPage(self.page)
1084
1085 if self.preview is None:
1086 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
1087 table.SetPTSize(size[0], size[1])
1088 table.SetPreview(False)
1089 else:
1090 if self.preview == 1:
1091 table.scale = self.scale
1092 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
1093 else:
1094 table.SetPSize(self.pwidth, self.pheight)
1095
1096 table.SetPTSize(self.ptwidth, self.ptheight)
1097 table.SetPreview(self.preview)
1098
1099 table.OutCanvas()
1100 self.page_total = table.total_pages # total display pages
1101
1102 self.ymax = DC.MaxY()
1103 self.xmax = DC.MaxX()
1104
1105 self.sizeh = size[0]
1106 self.sizew = size[1]
1107
1108
1109 def GetTotalPages(self):
1110 self.page_total = 100
1111 return self.page_total
1112
1113
1114 def HasPage(self, page):
1115 if page <= self.page_total:
1116 return True
1117 else:
1118 return False
1119
1120
1121 def SetPage(self, page):
1122 self.page = page
1123
1124
1125 def SetPageSize(self, width, height):
1126 self.pwidth, self.pheight = width, height
1127
1128
1129 def SetTotalSize(self, width, height):
1130 self.ptwidth, self.ptheight = width, height
1131
1132
1133 def SetPreview(self, preview, scale):
1134 self.preview = preview
1135 self.scale = scale
1136
1137
1138 def SetTotalSize(self, width, height):
1139 self.ptwidth = width
1140 self.ptheight = height
1141
1142 #-------------------------------------------------------------------------------
1143
1144 class PrintGrid(object):
1145 """
1146 ...
1147 """
1148 def __init__(self, parent, grid, format=[], total_col=None,
1149 total_row=None, rowLabels=True, colLabels=True):
1150 if total_row is None:
1151 total_row = grid.GetNumberRows()
1152 if total_col is None:
1153 total_col = grid.GetNumberCols()
1154
1155 self.total_row = total_row
1156 self.total_col = total_col
1157 self.grid = grid
1158 self.rowLabels = rowLabels
1159 self.colLabels = colLabels
1160
1161 data = []
1162 for row in range(total_row):
1163 row_val = []
1164 if rowLabels:
1165 row_val.append(grid.GetRowLabelValue(row))
1166
1167 for col in range(total_col):
1168 try:
1169 row_val.append(grid.GetCellValueAsString(row, col))
1170 except:
1171 row_val.append(grid.GetCellValue(row, col))
1172 data.append(row_val)
1173
1174
1175 if colLabels:
1176 label = [""] if rowLabels else []
1177 for col in range(total_col):
1178 value = grid.GetColLabelValue(col)
1179 label.append(value)
1180
1181 d = float(grid.GetColSize(0))
1182 if format == []:
1183 if rowLabels:
1184 format.append(grid.GetRowLabelSize())
1185 for col in range(total_col):
1186 col_size = grid.GetColSize(col)
1187 #print("Column size:", col,'\t',col_size)
1188 format.append(col_size)
1189
1190 self.table = PrintTable(parent, rowLabels, colLabels)
1191 if colLabels: self.table.label = label
1192 self.table.cell_left_margin = 0.0
1193 self.table.cell_right_margin = 0.0
1194
1195 self.table.set_column = format
1196 self.table.data = data
1197
1198 #---------------------------------------------------------------------------
1199
1200 def GetTable(self):
1201 return self.table
1202
1203
1204 def SetAttributes(self):
1205 for row in range(self.total_row):
1206 for col in range(self.total_col):
1207 colour = self.grid.GetCellTextColour(row, col)
1208 self.table.SetCellText(row, col+self.rowLabels, colour)
1209
1210 colour = self.grid.GetCellBackgroundColour(row, col)
1211 self.table.SetCellColour(row, col+self.rowLabels, colour)
1212
1213 #self.table.
1214
1215
1216 def Preview(self):
1217 self.table.Preview()
1218
1219
1220 def Print(self):
1221 self.table.Print()
1222
1223 #-------------------------------------------------------------------------------
1224
1225 class SetPrintout(wx.Printout):
1226 """
1227 ...
1228 """
1229 def __init__(self, canvas):
1230 wx.Printout.__init__(self)
1231 self.canvas = canvas
1232 self.end_pg = 1000
1233
1234 #---------------------------------------------------------------------------
1235
1236 def OnBeginDocument(self, start, end):
1237 return super(SetPrintout, self).OnBeginDocument(start, end)
1238
1239
1240 def OnEndDocument(self):
1241 super(SetPrintout, self).OnEndDocument()
1242
1243
1244 def HasPage(self, page):
1245 try:
1246 end = self.canvas.HasPage(page)
1247 return end
1248 except:
1249 return True
1250
1251
1252 def GetPageInfo(self):
1253 try:
1254 self.end_pg = self.canvas.GetTotalPages()
1255 except:
1256 pass
1257
1258 end_pg = self.end_pg
1259 str_pg = 1
1260 return (str_pg, end_pg, str_pg, end_pg)
1261
1262
1263 def OnPreparePrinting(self):
1264 super(SetPrintout, self).OnPreparePrinting()
1265
1266
1267 def OnBeginPrinting(self):
1268 dc = self.GetDC()
1269
1270 self.preview = self.IsPreview()
1271 if self.preview:
1272 self.pixelsPerInch = self.GetPPIScreen()
1273 else:
1274 self.pixelsPerInch = self.GetPPIPrinter()
1275
1276 (w, h) = dc.GetSize()
1277 scaleX = float(w) / 1000
1278 scaleY = float(h) / 1000
1279 self.printUserScale = min(scaleX, scaleY)
1280
1281 super(SetPrintout, self).OnBeginPrinting()
1282
1283
1284 def GetSize(self):
1285 self.psizew, self.psizeh = self.GetPPIPrinter()
1286 return self.psizew, self.psizeh
1287
1288
1289 def GetTotalSize(self):
1290 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1291 return self.ptsizew, self.ptsizeh
1292
1293
1294 def OnPrintPage(self, page):
1295 dc = self.GetDC()
1296 (w, h) = dc.GetSize()
1297 scaleX = float(w) / 1000
1298 scaleY = float(h) / 1000
1299 self.printUserScale = min(scaleX, scaleY)
1300 dc.SetUserScale(self.printUserScale, self.printUserScale)
1301
1302 self.preview = self.IsPreview()
1303
1304 self.canvas.SetPreview(self.preview, self.printUserScale)
1305 self.canvas.SetPage(page)
1306
1307 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1308 self.canvas.SetTotalSize(self.ptsizew, self.ptsizeh)
1309
1310 self.psizew, self.psizeh = self.GetPPIPrinter()
1311 self.canvas.SetPageSize(self.psizew, self.psizeh)
1312
1313 self.canvas.DoDrawing(dc)
1314 return True
1315
1316 #-------------------------------------------------------------------------------
1317
1318 class Frame(wx.Frame):
1319 """
1320 ...
1321 """
1322 def __init__(self, parent, id, title=""):
1323 wx.Frame.__init__(self,
1324 parent,
1325 id,
1326 title,
1327 size=(675, 460),
1328 style=wx.DEFAULT_FRAME_STYLE)
1329
1330 #------------
1331
1332 # Simplified init method.
1333 self.SetProperties()
1334 self.CreateMenu()
1335 self.CreateCtrls()
1336 self.CreatePrintData()
1337 self.BindEvents()
1338 self.DoLayout()
1339
1340 #------------
1341
1342 self.CenterOnScreen()
1343
1344 #---------------------------------------------------------------------------
1345
1346 def SetProperties(self):
1347 """
1348 Set the main frame properties (title, icon...).
1349 """
1350
1351 self.SetTitle("Dummy wx frame for testing printout.py")
1352
1353
1354 def CreateMenu(self):
1355 """
1356 ...
1357 """
1358
1359 menub = wx.MenuBar()
1360
1361 fmenu = wx.Menu()
1362 fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
1363 fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
1364 fmenu.AppendSeparator()
1365 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
1366 menub.Append(fmenu, "&File")
1367
1368 self.SetMenuBar(menub)
1369
1370
1371 def CreateCtrls(self):
1372 """
1373 ...
1374 """
1375
1376 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
1377 font.SetWeight(wx.BOLD)
1378 font.SetPointSize(10)
1379
1380 #------------
1381
1382 # First create the controls.
1383 self.panel = wx.Panel(self, -1,
1384 style=wx.BORDER_THEME|
1385 wx.TAB_TRAVERSAL)
1386
1387 #------------
1388
1389 self.demo = wx.StaticText(self.panel,
1390 id=-1,
1391 label="Demonstrating :")
1392 self.demo.SetFont(font)
1393
1394 self.info = wx.StaticText(self.panel,
1395 id=-1,
1396 label="1) Direct printing,\n"
1397 "2) Printout class,\n"
1398 "3) PrintTable class,\n"
1399 "4) Preview,\n"
1400 "5) Menu")
1401 self.info.SetForegroundColour("red")
1402 font.SetWeight(wx.NORMAL)
1403 self.info.SetFont(font)
1404
1405 #------------
1406
1407 self.testgrid = grid.Grid(self.panel, -1,
1408 style=wx.BORDER_THEME)
1409 self.testgrid.CreateGrid(5, 5)
1410 for i in range(5):
1411 d = i + 1
1412 self.testgrid.SetColLabelValue(i, 'Column %d' % d)
1413 self.testgrid.SetRowLabelValue(i, 'Row %d' % d)
1414 for j in range(5):
1415 e = j + 1
1416 self.testgrid.SetCellValue(i, j, 'Cell %02d.%02d' % (d, e))
1417 self.testgrid.SetCellBackgroundColour(0, 0, wx.RED)
1418 self.testgrid.SetCellBackgroundColour(4, 4, wx.GREEN)
1419 self.testgrid.SetCellBackgroundColour(3, 4, wx.BLUE)
1420 self.testgrid.SetCellBackgroundColour(4, 3, wx.YELLOW)
1421 self.testgrid.SetColSize(0, 71)
1422 self.testgrid.SetColSize(1, 71)
1423 self.testgrid.SetColSize(2, 107)
1424 self.testgrid.SetColSize(3, 130)
1425 self.testgrid.SetColSize(4, 130)
1426
1427 #------------
1428
1429 self.btnPreview = wx.Button(self.panel,
1430 id=wx.ID_PREVIEW,
1431 label="Print pre&view")
1432 self.btnPreview.SetFocus()
1433
1434 self.btnPrint = wx.Button(self.panel,
1435 id=wx.ID_PRINT,
1436 label="&Print")
1437
1438 self.btnClose = wx.Button(self.panel,
1439 id=wx.ID_CLOSE,
1440 label="E&xit")
1441
1442
1443 def CreatePrintData(self):
1444 """
1445 Create printing data.
1446 """
1447
1448 testgrid = self.testgrid
1449
1450 #------------
1451
1452 self.grdprt = PrintGrid(self, testgrid, rowLabels=False, colLabels=False)
1453 self.grdprt.SetAttributes()
1454
1455 #------------
1456
1457 self.table = self.grdprt.GetTable()
1458 self.table.SetPortrait()
1459 self.table.SetHeader('This is the test HEADER')
1460 self.table.SetFooter()
1461
1462
1463 def BindEvents(self):
1464 """
1465 Bind all the events related to my application.
1466 """
1467
1468 # Bind some menu events to an events handler.
1469 self.Bind(wx.EVT_MENU, self.OnPrintPreview, id=wx.ID_PREVIEW)
1470 self.Bind(wx.EVT_MENU, self.OnPrint, id=wx.ID_PRINT)
1471 self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_EXIT)
1472
1473 # Bind the close event to an event handler.
1474 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
1475
1476 # Bind some buttons events to an events handler.
1477 self.Bind(wx.EVT_BUTTON, self.OnPrintPreview, self.btnPreview)
1478 self.Bind(wx.EVT_BUTTON, self.OnPrint, self.btnPrint)
1479 self.Bind(wx.EVT_BUTTON, self.OnClose, self.btnClose)
1480
1481
1482 def DoLayout(self):
1483 """
1484 Manage widgets Layout.
1485 """
1486
1487 # MainSizer is the top-level one that manages everything.
1488 mainSizer = wx.BoxSizer(wx.VERTICAL)
1489
1490 #------------
1491
1492 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
1493 hBox1.Add(self.info, 0, wx.ALL, 15)
1494
1495 #------------
1496
1497 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
1498 hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
1499 hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
1500 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
1501
1502 #------------
1503
1504 mainSizer.Add(self.demo, 0, wx.ALL, 10)
1505 mainSizer.Add(wx.StaticLine(self.panel),
1506 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
1507 mainSizer.Add(self.testgrid, 0, wx.ALL, 15)
1508 mainSizer.Add(hBox1, 0, wx.ALL, 5)
1509 mainSizer.Add(hBox2, 0, wx.ALL, 5)
1510
1511 #------------
1512
1513 # Finally, tell the panel to use the mainSizer for layout.
1514 self.panel.SetSizer(mainSizer)
1515
1516
1517 def OnPrintPreview(self, event):
1518 self.CreatePrintData()
1519 self.grdprt.Preview()
1520
1521
1522 def OnPrint(self, event):
1523 self.CreatePrintData()
1524 self.grdprt.Print()
1525
1526
1527 def OnClose(self, evt):
1528 self.Close()
1529
1530
1531 def OnCloseWindow(self, event):
1532 """
1533 ...
1534 """
1535
1536 self.Destroy()
1537
1538 #-------------------------------------------------------------------------------
1539
1540 class App(wx.App):
1541 """
1542 ...
1543 """
1544 def OnInit(self):
1545
1546 #------------
1547
1548 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
1549
1550 #------------
1551
1552 frame = Frame(None, id=-1)
1553 self.SetTopWindow(frame)
1554 frame.Show(True)
1555
1556 return True
1557
1558 #-------------------------------------------------------------------------------
1559
1560 def main():
1561 app = App(False)
1562 app.MainLoop()
1563
1564 #-------------------------------------------------------------------------------
1565
1566 if __name__ == "__main__" :
1567 main()
Second example
1 # sample_five_b.py
2
3 #-------------------------------------------------------------------------------
4 # Name: printout.py
5 # Purpose: preview and printing class -> table/grid printing
6 #
7 # Author: Lorne White (email: lorne.white@telusplanet.net)
8 #
9 # Created:
10 # Version: 0.75
11 # Date: May 15, 2002
12 # Licence: wxWindows license
13 #-------------------------------------------------------------------------------
14 # Link:
15 # https://raw.githubusercontent.com/wxWidgets/wxPython/master/wx/lib/printout.py
16 #-------------------------------------------------------------------------------
17 # Release Notes :
18 # fixed bug for string wider than print region
19 # add index to data list after parsing total pages for paging
20 #-------------------------------------------------------------------------------
21 # 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
22 # o 2.5 compatability update.
23 #-------------------------------------------------------------------------------
24 # 11/23/2004 - Vernon Cole (wnvcole@peppermillcas.com)
25 # o Generalize for non-2-dimensional sequences and non-text data
26 # (can use as a simple text printer by supplying a list of strings.)
27 # o Add a small _main_ for self test
28 #-------------------------------------------------------------------------------
29
30 import os
31 import copy
32 import wx
33
34 # class PrintBase
35 # class PrintTableDraw
36 # class PrintTable
37 # class PrintGrid
38 # class SetPrintout
39 # class Frame
40 # class App
41
42 #-------------------------------------------------------------------------------
43
44 if os.name == "posix":
45 print("\nPlatform : UNIX - Linux")
46 elif os.name in ['nt', 'dos', 'ce']:
47 print("\nPlatform : Windows")
48 else:
49 print("\nPlatform : ", platform.system())
50
51 #-------------------------------------------------------------------------------
52
53 class PrintBase(object):
54 """
55 ...
56 """
57 def SetPrintFont(self, font): # set the DC font parameters
58 fattr = font["Attr"]
59 if fattr[0] == 1:
60 weight = wx.BOLD
61 else:
62 weight = wx.NORMAL
63
64 if fattr[1] == 1:
65 set_style = wx.ITALIC
66 else:
67 set_style = wx.NORMAL
68
69 underline = fattr[2]
70 fcolour = self.GetFontColour(font)
71 self.DC.SetTextForeground(fcolour)
72
73 setfont = wx.Font(font["Size"], wx.SWISS, set_style, weight, underline)
74 setfont.SetFaceName(font["Name"])
75 self.DC.SetFont(setfont)
76
77 #---------------------------------------------------------------------------
78
79 def GetFontColour(self, font):
80 fcolour = font["Colour"]
81 return wx.Colour(fcolour[0], fcolour[1], fcolour[2])
82
83
84 def OutTextRegion(self, textout, txtdraw = True):
85 textlines = textout.split('\n')
86 y = copy.copy(self.y) + self.pt_space_before
87 for text in textlines:
88 remain = 'X'
89 while remain != "":
90 vout, remain = self.SetFlow(text, self.region)
91 if self.draw == True and txtdraw == True:
92 test_out = self.TestFull(vout)
93 if self.align == wx.ALIGN_LEFT:
94 self.DC.DrawText(test_out, int(self.indent+self.pcell_left_margin), int(y))
95
96 elif self.align == wx.ALIGN_CENTRE:
97 diff = self.GetCellDiff(test_out, self.region)
98 self.DC.DrawText(test_out, self.indent+diff/2, y)
99
100 elif self.align == wx.ALIGN_RIGHT:
101 diff = self.GetCellDiff(test_out, self.region)
102 self.DC.DrawText(test_out, self.indent+diff, y)
103
104 else:
105 self.DC.DrawText(test_out, int(self.indent+self.pcell_left_margin), int(y))
106 text = remain
107 y = y + self.space
108 return y - self.space + self.pt_space_after
109
110
111 def GetCellDiff(self, text, width): # get the remaining cell size for adjustment
112 w, h = self.DC.GetTextExtent(text)
113 diff = width - w
114 if diff < 0:
115 diff = 0
116 return diff
117
118
119 def TestFull(self, text_test):
120 w, h = self.DC.GetTextExtent(text_test)
121 if w > self.region: # trouble fitting into cell
122 return self.SetChar(text_test, self.region) # fit the text to the cell size
123 else:
124 return text_test
125
126
127 def SetFlow(self, ln_text, width):
128 width = width - self.pcell_right_margin
129 text = ""
130 split = ln_text.split()
131 if len(split) == 1:
132 return ln_text, ""
133
134 try:
135 w, h = self.DC.GetTextExtent(" " + split[0])
136 if w >= width:
137 return ln_text, ""
138 except:
139 pass
140
141 cnt = 0
142 for word in split:
143 bword = " " + word # blank + word
144 length = len(bword)
145
146 w, h = self.DC.GetTextExtent(text + bword)
147 if w < width:
148 text = text + bword
149 cnt = cnt + 1
150 else:
151 remain = ' '.join(split[cnt:])
152 text = text.strip()
153 return text, remain
154
155 remain = ' '.join(split[cnt:])
156 vout = text.strip()
157 return vout, remain
158
159
160 def SetChar(self, ln_text, width): # truncate string to fit into width
161 width = width - self.pcell_right_margin - self.pcell_left_margin
162 text = ""
163 for val in ln_text:
164 w, h = self.DC.GetTextExtent(text + val)
165 if w > width:
166 text = text + ".."
167 return text # fitted text value
168 text = text + val
169 return text
170
171
172 def OutTextPageWidth(self, textout, y_out, align, indent, txtdraw = True):
173 textlines = textout.split('\n')
174 y = copy.copy(y_out)
175
176 pagew = self.parent.page_width * self.pwidth # full page width
177 w, h = self.DC.GetTextExtent(textout)
178 y_line = h
179
180 for text in textlines:
181 remain = 'X'
182 while remain != "":
183 vout, remain = self.SetFlow(text, pagew)
184 if self.draw == True and txtdraw == True:
185 test_out = vout
186 if align == wx.ALIGN_LEFT:
187 self.DC.DrawText(test_out, indent, y)
188
189 elif align == wx.ALIGN_CENTRE:
190 diff = self.GetCellDiff(test_out, pagew)
191 self.DC.DrawText(test_out, int(indent+diff/2), int(y))
192
193 elif align == wx.ALIGN_RIGHT:
194 diff = self.GetCellDiff(test_out, pagew)
195 self.DC.DrawText(test_out, int(indent+diff), int(y))
196
197 else:
198 self.DC.DrawText(test_out, indent, y_out)
199 text = remain
200 y = y + y_line
201 return y - y_line
202
203
204 def GetDate(self):
205 date, time = self.GetNow()
206 return date
207
208
209 def GetDateTime(self):
210 date, time = self.GetNow()
211 return date + ' ' + time
212
213
214 def GetNow(self):
215 now = wx.DateTime.Now()
216 date = now.FormatDate()
217 time = now.FormatTime()
218 return date, time
219
220
221 def SetPreview(self, preview):
222 self.preview = preview
223
224
225 def SetPSize(self, width, height):
226 self.pwidth = width/self.scale
227 self.pheight = height/self.scale
228
229
230 def SetScale(self, scale):
231 self.scale = scale
232
233
234 def SetPTSize(self, width, height):
235 self.ptwidth = width
236 self.ptheight = height
237
238
239 def getWidth(self):
240 return self.sizew
241
242
243 def getHeight(self):
244 return self.sizeh
245
246 #-------------------------------------------------------------------------------
247
248 class PrintTableDraw(wx.ScrolledWindow, PrintBase):
249 """
250 ...
251 """
252 def __init__(self, parent, DC, size):
253 self.parent = parent
254 self.DC = DC
255 self.scale = parent.scale
256 self.width = size[0]
257 self.height = size[1]
258 self.SetDefaults()
259
260 #---------------------------------------------------------------------------
261
262 def SetDefaults(self):
263 self.page = 1
264 self.total_pages = None
265
266 self.page_width = self.parent.page_width
267 self.page_height = self.parent.page_height
268
269 self.left_margin = self.parent.left_margin
270 self.right_margin = self.parent.right_margin
271
272 self.top_margin = self.parent.top_margin
273 self.bottom_margin = self.parent.bottom_margin
274 self.cell_left_margin = self.parent.cell_left_margin
275 self.cell_right_margin = self.parent.cell_right_margin
276
277 self.label_colour = self.parent.label_colour
278
279 self.row_line_colour = self.parent.row_line_colour
280 self.row_line_size = self.parent.row_line_size
281
282 self.row_def_line_colour = self.parent.row_def_line_colour
283 self.row_def_line_size = self.parent.row_def_line_size
284
285 self.column_line_colour = self.parent.column_line_colour
286 self.column_line_size = self.parent.column_line_size
287
288 self.column_def_line_size = self.parent.column_def_line_size
289 self.column_def_line_colour = self.parent.column_def_line_colour
290
291 self.text_font = self.parent.text_font
292
293 self.label_font = self.parent.label_font
294
295
296 def AdjustValues(self):
297 self.vertical_offset = self.pheight * self.parent.vertical_offset
298 self.horizontal_offset = self.pheight * self.parent.horizontal_offset
299
300 self.pcell_left_margin = self.pwidth * self.cell_left_margin
301 self.pcell_right_margin = self.pwidth * self.cell_right_margin
302 self.ptop_margin = self.pheight * self.top_margin
303 self.pbottom_margin = self.pheight * self.bottom_margin
304
305 self.pheader_margin = self.pheight * self.parent.header_margin
306 self.pfooter_margin = self.pheight * self.parent.footer_margin
307
308 self.cell_colour = self.parent.set_cell_colour
309 self.cell_text = self.parent.set_cell_text
310
311 self.column = []
312 self.column_align = []
313 self.column_bgcolour = []
314 self.column_txtcolour = []
315
316 set_column_align = self.parent.set_column_align
317 set_column_bgcolour = self.parent.set_column_bgcolour
318 set_column_txtcolour = self.parent.set_column_txtcolour
319
320 pos_x = self.left_margin * self.pwidth + self.horizontal_offset # left margin
321 self.column.append(pos_x)
322
323 # Module logic expects two dimensional data -- fix input if needed
324 if isinstance(self.data, str):
325 self.data = [[copy.copy(self.data)]] # a string becomes a single cell
326 try:
327 rows = len(self.data)
328 except TypeError:
329 self.data = [[str(self.data)]] # a non-iterable becomes a single cell
330 rows = 1
331 first_value = self.data[0]
332
333 if isinstance(first_value, str): # A sequence of strings
334 if self.label == [] and self.set_column == []:
335 data = []
336 for x in self.data: # Becomes one column
337 data.append([x])
338 else:
339 data = [self.data] # Becames one row
340 self.data = data
341 first_value = data[0]
342 try:
343 column_total = len(first_value)
344 except TypeError: # A sequence of non-iterables
345 if self.label == [] and self.set_column == []:
346 data = [] # Becomes one column
347 for x in self.data:
348 data.append([str(x)])
349 column_total = 1
350 else:
351 data = [self.data] # Becomes one row
352 column_total = len(self.data)
353 self.data = data
354 first_value = data[0]
355
356 if self.set_column == []:
357 table_width = self.page_width - self.left_margin - self.right_margin
358 if self.label == []:
359 temp = first_value
360 else:
361 temp = self.label
362 width = table_width/(len(temp))
363 for val in temp:
364 column_width = width * self.pwidth
365 pos_x = pos_x + column_width
366 self.column.append(pos_x) # position of each column
367 else:
368 for val in self.set_column:
369 column_width = val * self.pwidth
370 pos_x = pos_x + column_width
371 self.column.append(pos_x) # position of each column
372
373 if pos_x > self.page_width * self.pwidth: # check if it fits in page
374 print("Warning, Too Wide for Page")
375 return
376
377 if self.label != []:
378 if len(self.column) -1 != len(self.label):
379 print("Column Settings Incorrect", "\nColumn Value: " + str(self.column), "\nLabel Value: " + str(self.label))
380 return
381
382 if column_total != len(self.column) -1:
383 print("Cannot fit", first_value, 'in', len(self.column)-1, 'columns.')
384 return
385
386 for col in range(column_total):
387 try:
388 align = set_column_align[col] # check if custom column alignment
389 except:
390 align = wx.ALIGN_LEFT
391 self.column_align.append(align)
392
393 try:
394 colour = set_column_bgcolour[col] # check if custom column background colour
395 except:
396 colour = self.parent.column_colour
397 self.column_bgcolour.append(colour)
398
399 try:
400 colour = set_column_txtcolour[col] # check if custom column text colour
401 except:
402 colour = self.GetFontColour(self.parent.text_font)
403 self.column_txtcolour.append(colour)
404
405
406 def SetPointAdjust(self):
407 f = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL) # setup using 10 point
408 self.DC.SetFont(f)
409 f.SetFaceName(self.text_font["Name"])
410 x, y = self.DC.GetTextExtent("W")
411
412 self.label_pt_space_before = self.parent.label_pt_adj_before * y/10 # extra spacing for label per point value
413 self.label_pt_space_after = self.parent.label_pt_adj_after * y/10
414
415 self.text_pt_space_before = self.parent.text_pt_adj_before * y/10 # extra spacing for row text per point value
416 self.text_pt_space_after = self.parent.text_pt_adj_after * y/10
417
418
419 def SetPage(self, page):
420 self.page = page
421
422
423 def SetColumns(self, col):
424 self.column = col
425
426
427 def OutCanvas(self):
428 self.AdjustValues()
429 self.SetPointAdjust()
430
431 self.y_start = self.ptop_margin + self.vertical_offset
432 self.y_end = self.parent.page_height * self.pheight - self.pbottom_margin + self.vertical_offset
433
434 self.SetPrintFont(self.label_font)
435
436 x, y = self.DC.GetTextExtent("W")
437 self.label_space = y
438
439 self.SetPrintFont(self.text_font)
440
441 x, y = self.DC.GetTextExtent("W")
442 self.space = y
443
444 if self.total_pages is None:
445 self.GetTotalPages() # total pages for display/printing
446
447 self.data_cnt = self.page_index[self.page-1]
448
449 self.draw = True
450 self.PrintHeader()
451 self.PrintFooter()
452 self.OutPage()
453
454
455 def GetTotalPages(self):
456 self.data_cnt = 0
457 self.draw = False
458 self.page_index = [0]
459
460 cnt = 0
461 while 1:
462 test = self.OutPage()
463 self.page_index.append(self.data_cnt)
464 if test == False:
465 break
466 cnt = cnt + 1
467
468 self.total_pages = cnt + 1
469
470
471 def OutPage(self):
472 self.y = self.y_start
473 self.end_x = self.column[-1]
474
475 if self.data_cnt < len(self.data): # if there data for display on the page
476 if self.label != []: # check if header defined
477 self.PrintLabel()
478 else:
479 return False
480
481 for val in self.data:
482 try:
483 row_val = self.data[self.data_cnt]
484 except:
485 self.FinishDraw()
486 return False
487
488 max_y = self.PrintRow(row_val, False) # test to see if row will fit in remaining space
489 test = max_y + self.space
490
491 if test > self.y_end:
492 break
493
494 self.ColourRowCells(max_y-self.y+self.space) # colour the row/column
495 max_y = self.PrintRow(row_val, True) # row fits - print text
496 self.DrawGridLine() # top line of cell
497 self.y = max_y + self.space
498
499 if self.y > self.y_end:
500 break
501
502 self.data_cnt = self.data_cnt + 1
503
504 self.FinishDraw()
505
506 if self.data_cnt == len(self.data): # last value in list
507 return False
508
509 return True
510
511
512 def PrintLabel(self):
513 self.pt_space_before = self.label_pt_space_before # set the point spacing
514 self.pt_space_after = self.label_pt_space_after
515
516 self.LabelColorRow(self.label_colour)
517 self.SetPrintFont(self.label_font)
518
519 self.col = 0
520 max_y = 0
521 for vtxt in self.label:
522 self.region = self.column[self.col+1] - self.column[self.col]
523 self.indent = self.column[self.col]
524
525 self.align = wx.ALIGN_LEFT
526
527 max_out = self.OutTextRegion(vtxt, True)
528 if max_out > max_y:
529 max_y = max_out
530 self.col = self.col + 1
531
532 self.DrawGridLine() # top line of label
533 self.y = max_y + self.label_space
534
535
536 def PrintHeader(self): # print the header array
537 if self.draw == False:
538 return
539
540 for val in self.parent.header:
541 self.SetPrintFont(val["Font"])
542
543 header_indent = val["Indent"] * self.pwidth
544 text = val["Text"]
545
546 htype = val["Type"]
547 if htype == "Date":
548 addtext = self.GetDate()
549 elif htype == "Date & Time":
550 addtext = self.GetDateTime()
551 else:
552 addtext = ""
553
554 self.OutTextPageWidth(text+addtext, self.pheader_margin, val["Align"], header_indent, True)
555
556
557 def PrintFooter(self): # print the header array
558 if self.draw == False:
559 return
560
561 footer_pos = self.parent.page_height * self.pheight - self.pfooter_margin + self.vertical_offset
562 for val in self.parent.footer:
563 self.SetPrintFont(val["Font"])
564
565 footer_indent = val["Indent"] * self.pwidth
566 text = val["Text"]
567
568 ftype = val["Type"]
569 if ftype == "Pageof":
570 addtext = "Page " + str(self.page) + " of " + str(self.total_pages)
571 elif ftype == "Page":
572 addtext = "Page " + str(self.page)
573 elif ftype == "Num":
574 addtext = str(self.page)
575 elif ftype == "Date":
576 addtext = self.GetDate()
577 elif ftype == "Date & Time":
578 addtext = self.GetDateTime()
579 else:
580 addtext = ""
581
582 self.OutTextPageWidth(text+addtext, footer_pos, val["Align"], footer_indent, True)
583
584
585 def LabelColorRow(self, colour):
586 brush = wx.Brush(colour, wx.SOLID)
587 self.DC.SetBrush(brush)
588 height = self.label_space + self.label_pt_space_before + self.label_pt_space_after
589 self.DC.DrawRectangle(int(self.column[0]), int(self.y),
590 int(self.end_x-self.column[0]+1), int(height))
591
592
593 def ColourRowCells(self, height):
594 if self.draw == False:
595 return
596
597 col = 0
598 for colour in self.column_bgcolour:
599 cellcolour = self.GetCellColour(self.data_cnt, col)
600 if cellcolour is not None:
601 colour = cellcolour
602
603 brush = wx.Brush(colour, wx.SOLID)
604 self.DC.SetBrush(brush)
605 self.DC.SetPen(wx.Pen(wx.Colour('WHITE'), 0))
606
607 start_x = self.column[col]
608 width = self.column[col+1] - start_x + 2
609 self.DC.DrawRectangle(int(start_x), int(self.y), int(width), int(height))
610 col = col + 1
611
612
613 def PrintRow(self, row_val, draw = True, align = wx.ALIGN_LEFT):
614 self.SetPrintFont(self.text_font)
615
616 self.pt_space_before = self.text_pt_space_before # set the point spacing
617 self.pt_space_after = self.text_pt_space_after
618
619 self.col = 0
620 max_y = 0
621 for vtxt in row_val:
622 if not isinstance(vtxt, str):
623 vtxt = str(vtxt)
624 self.region = self.column[self.col+1] - self.column[self.col]
625 self.indent = self.column[self.col]
626 self.align = self.column_align[self.col]
627
628 fcolour = self.column_txtcolour[self.col] # set font colour
629 celltext = self.GetCellTextColour(self.data_cnt, self.col)
630 if celltext is not None:
631 fcolour = celltext # override the column colour
632
633 self.DC.SetTextForeground(fcolour)
634
635 max_out = self.OutTextRegion(vtxt, draw)
636 if max_out > max_y:
637 max_y = max_out
638 self.col = self.col + 1
639 return max_y
640
641
642 def GetCellColour(self, row, col): # check if custom colour defined for the cell background
643 try:
644 set = self.cell_colour[row]
645 except:
646 return None
647 try:
648 colour = set[col]
649 return colour
650 except:
651 return None
652
653
654 def GetCellTextColour(self, row, col): # check if custom colour defined for the cell text
655 try:
656 set = self.cell_text[row]
657 except:
658 return None
659 try:
660 colour = set[col]
661 return colour
662 except:
663 return None
664
665
666 def FinishDraw(self):
667 self.DrawGridLine() # draw last row line
668 self.DrawColumns() # draw all vertical lines
669
670
671 def DrawGridLine(self):
672 if self.draw == True \
673 and len(self.column) > 2: #supress grid lines if only one column
674 try:
675 size = self.row_line_size[self.data_cnt]
676 except:
677 size = self.row_def_line_size
678
679 if size < 1: return
680
681 try:
682 colour = self.row_line_colour[self.data_cnt]
683 except:
684 colour = self.row_def_line_colour
685
686 self.DC.SetPen(wx.Pen(colour, size))
687
688 y_out = self.y
689 #y_out = self.y + self.pt_space_before + self.pt_space_after # adjust for extra spacing
690 self.DC.DrawLine(int(self.column[0]), int(y_out), int(self.end_x), int(y_out))
691
692
693 def DrawColumns(self):
694 if self.draw == True \
695 and len(self.column) > 2: #surpress grid line if only one column
696 col = 0
697 for val in self.column:
698 try:
699 size = self.column_line_size[col]
700 except:
701 size = self.column_def_line_size
702
703 if size < 1: continue
704
705 try:
706 colour = self.column_line_colour[col]
707 except:
708 colour = self.column_def_line_colour
709
710 indent = val
711
712 self.DC.SetPen(wx.Pen(colour, size))
713 self.DC.DrawLine(int(indent), int(self.y_start), int(indent), int(self.y))
714 col = col + 1
715
716
717 def DrawText(self):
718 self.DoRefresh()
719
720
721 def DoDrawing(self, DC):
722 size = DC.GetSize()
723 self.DC = DC
724
725 self.DrawText()
726
727 self.sizew = DC.MaxY()
728 self.sizeh = DC.MaxX()
729
730 #-------------------------------------------------------------------------------
731
732 class PrintTable(object):
733 """
734 ...
735 """
736 def __init__(self, parentFrame=None):
737 self.data = []
738 self.set_column = []
739 self.label = []
740 self.header = []
741 self.footer = []
742
743 self.set_column_align = {}
744 self.set_column_bgcolour = {}
745 self.set_column_txtcolour = {}
746 self.set_cell_colour = {}
747 self.set_cell_text = {}
748 self.column_line_size = {}
749 self.column_line_colour = {}
750 self.row_line_size = {}
751 self.row_line_colour = {}
752
753 self.parentFrame = parentFrame
754 self.SetPreviewSize()
755
756 self.printData = wx.PrintData()
757 self.scale = 1.0
758
759 self.SetParms()
760 self.SetColors()
761 self.SetFonts()
762 self.TextSpacing()
763
764 self.SetPrinterOffset()
765 self.SetHeaderValue()
766 self.SetFooterValue()
767 self.SetMargins()
768 self.SetPortrait()
769
770 #---------------------------------------------------------------------------
771
772 def SetPreviewSize(self, position = wx.Point(0, 0), size="Full"):
773 if size == "Full":
774 r = wx.GetClientDisplayRect()
775 self.preview_frame_size = r.GetSize()
776 self.preview_frame_pos = r.GetPosition()
777 else:
778 self.preview_frame_size = size
779 self.preview_frame_pos = position
780
781
782 def SetPaperId(self, paper):
783 self.printData.SetPaperId(paper)
784
785
786 def SetOrientation(self, orient):
787 self.printData.SetOrientation(orient)
788
789
790 def SetColors(self):
791 self.row_def_line_colour = wx.Colour('BLACK')
792 self.row_def_line_size = 1
793
794 self.column_def_line_colour = wx.Colour('BLACK')
795 self.column_def_line_size = 1
796 self.column_colour = wx.Colour('WHITE')
797
798 self.label_colour = wx.Colour('LIGHT GREY')
799
800
801 def SetFonts(self):
802 self.label_font = { "Name": self.default_font_name, "Size": 12, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
803 self.text_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
804
805
806 def TextSpacing(self):
807 self.label_pt_adj_before = 0 # point adjustment before and after the label text
808 self.label_pt_adj_after = 0
809
810 self.text_pt_adj_before = 0 # point adjustment before and after the row text
811 self.text_pt_adj_after = 0
812
813
814 def SetLabelSpacing(self, before, after): # method to set the label space adjustment
815 self.label_pt_adj_before = before
816 self.label_pt_adj_after = after
817
818
819 def SetRowSpacing(self, before, after): # method to set the row space adjustment
820 self.text_pt_adj_before = before
821 self.text_pt_adj_after = after
822
823
824 def SetPrinterOffset(self): # offset to adjust for printer
825 self.vertical_offset = -0.1
826 self.horizontal_offset = -0.1
827
828
829 def SetHeaderValue(self):
830 self.header_margin = 0.25
831 self.header_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
832 self.header_align = wx.ALIGN_CENTRE
833 self.header_indent = 0
834 self.header_type = "Text"
835
836
837 def SetFooterValue(self):
838 self.footer_margin = 0.7
839 self.footer_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
840 self.footer_align = wx.ALIGN_CENTRE
841 self.footer_indent = 0
842 self.footer_type = "Pageof"
843
844
845 def SetMargins(self):
846 self.left_margin = 0.5
847 self.right_margin = 0.5 # only used if no column sizes
848
849 self.top_margin = 0.8
850 self.bottom_margin = 1.0
851 self.cell_left_margin = 0.1
852 self.cell_right_margin = 0.1
853
854
855 def SetPortrait(self):
856 self.printData.SetPaperId(wx.PAPER_LETTER)
857 self.printData.SetOrientation(wx.PORTRAIT)
858 self.page_width = 8.5
859 self.page_height = 11.0
860
861
862 def SetLandscape(self):
863 self.printData.SetOrientation(wx.LANDSCAPE)
864 self.page_width = 11.0
865 self.page_height = 8.5
866
867
868 def SetParms(self):
869 self.ymax = 1
870 self.xmax = 1
871 self.page = 1
872 self.total_pg = 100
873
874 self.preview = None
875 self.page = 0
876
877 self.default_font_name = "Arial"
878 self.default_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
879
880
881 def SetColAlignment(self, col, align=wx.ALIGN_LEFT):
882 self.set_column_align[col] = align
883
884
885 def SetColBackgroundColour(self, col, colour):
886 self.set_column_bgcolour[col] = colour
887
888
889 def SetColTextColour(self, col, colour):
890 self.set_column_txtcolour[col] = colour
891
892
893 def SetCellColour(self, row, col, colour): # cell background colour
894 try:
895 set = self.set_cell_colour[row] # test if row already exists
896 try:
897 set[col] = colour # test if column already exists
898 except:
899 set = { col: colour } # create the column value
900 except:
901 set = { col: colour } # create the column value
902
903 self.set_cell_colour[row] = set # create dictionary item for colour settings
904
905
906 def SetCellText(self, row, col, colour): # font colour for custom cells
907 try:
908 set = self.set_cell_text[row] # test if row already exists
909 try:
910 set[col] = colour # test if column already exists
911 except:
912 set = { col: colour } # create the column value
913 except:
914 set = { col: colour } # create the column value
915
916 self.set_cell_text[row] = set # create dictionary item for colour settings
917
918
919 def SetColumnLineSize(self, col, size): # column line size
920 self.column_line_size[col] = size # create dictionary item for column line settings
921
922
923 def SetColumnLineColour(self, col, colour):
924 self.column_line_colour[col] = colour
925
926
927 def SetRowLineSize(self, row, size):
928 self.row_line_size[row] = size
929
930
931 def SetRowLineColour(self, row, colour):
932 self.row_line_colour[row] = colour
933
934
935 def GetColour(self, colour): # returns colours based from wxColour value
936 red = colour.Red()
937 blue = colour.Blue()
938 green = colour.Green()
939 return [red, green, blue ]
940
941
942 def SetHeader(self, text = "", type = "Text", font=None, align = None, indent = None, colour = None, size = None):
943 set = { "Text": text }
944
945 if font is None:
946 set["Font"] = copy.copy(self.default_font)
947 else:
948 set["Font"] = font
949
950 if colour is not None:
951 setfont = set["Font"]
952 setfont["Colour"] = self.GetColour(colour)
953
954 if size is not None:
955 setfont = set["Font"]
956 setfont["Size"] = size
957
958 if align is None:
959 set["Align"] = self.header_align
960 else:
961 set["Align"] = align
962
963 if indent is None:
964 set["Indent"] = self.header_indent
965 else:
966 set["Indent"] = indent
967
968 if type is None:
969 set["Type"] = self.header_type
970 else:
971 set["Type"] = type
972
973 self.header.append(set)
974
975
976 def SetFooter(self, text = "", type = None, font=None, align = None, indent = None, colour = None, size = None):
977 set = { "Text": text }
978
979 if font is None:
980 set["Font"] = copy.copy(self.default_font)
981 else:
982 set["Font"] = font
983
984 if colour is not None:
985 setfont = set["Font"]
986 setfont["Colour"] = self.GetColour(colour)
987
988 if size is not None:
989 setfont = set["Font"]
990 setfont["Size"] = size
991
992 if align is None:
993 set["Align"] = self.footer_align
994 else:
995 set["Align"] = align
996
997 if indent is None:
998 set["Indent"] = self.footer_indent
999 else:
1000 set["Indent"] = indent
1001
1002 if type is None:
1003 set["Type"] = self.footer_type
1004 else:
1005 set["Type"] = type
1006
1007 self.footer.append(set)
1008
1009
1010 def Preview(self):
1011 data = wx.PrintDialogData(self.printData)
1012
1013 text = self.parentFrame.tc.GetValue()
1014
1015 printout = SetPrintout(self, text)
1016 printout2 = SetPrintout(self, text)
1017 self.preview = wx.PrintPreview(printout, printout2, data)
1018 if not self.preview.IsOk():
1019 wx.MessageBox("There was a problem printing!", "Printing", wx.OK)
1020 return
1021
1022 self.preview.SetZoom(60) # initial zoom value
1023 frame = wx.PreviewFrame(self.preview, self.parentFrame, "Print preview")
1024
1025 frame.Initialize()
1026 if self.parentFrame:
1027 frame.SetPosition(self.preview_frame_pos)
1028 frame.SetSize(self.preview_frame_size)
1029 frame.Show(True)
1030
1031
1032 def Print(self):
1033 pdd = wx.PrintDialogData(self.printData)
1034 printer = wx.Printer(pdd)
1035
1036 text = self.parentFrame.tc.GetValue()
1037
1038 printout = SetPrintout(self, text)
1039 if not printer.Print(self.parentFrame, printout):
1040 if wx.Printer.GetLastError() == wx.PRINTER_ERROR:
1041 wx.MessageBox("There was a problem printing.\n"
1042 "Perhaps your current printer is not set correctly?",
1043 "Printing", wx.OK)
1044 else:
1045 self.printData = wx.PrintData( printer.GetPrintDialogData().GetPrintData() )
1046 printout.Destroy()
1047
1048
1049 def DoDrawing(self, DC):
1050 size = DC.GetSize()
1051
1052 table = PrintTableDraw(self, DC, size)
1053 table.data = self.data
1054 table.set_column = self.set_column
1055 table.label = self.label
1056 table.SetPage(self.page)
1057
1058 if self.preview is None:
1059 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
1060 table.SetPTSize(size[0], size[1])
1061 table.SetPreview(False)
1062 else:
1063 if self.preview == 1:
1064 table.scale = self.scale
1065 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
1066 else:
1067 table.SetPSize(self.pwidth, self.pheight)
1068
1069 table.SetPTSize(self.ptwidth, self.ptheight)
1070 table.SetPreview(self.preview)
1071
1072 table.OutCanvas()
1073 self.page_total = table.total_pages # total display pages
1074
1075 self.ymax = DC.MaxY()
1076 self.xmax = DC.MaxX()
1077
1078 self.sizeh = size[0]
1079 self.sizew = size[1]
1080
1081
1082 def GetTotalPages(self):
1083 self.page_total = 100
1084 return self.page_total
1085
1086
1087 def HasPage(self, page):
1088 if page <= self.page_total:
1089 return True
1090 else:
1091 return False
1092
1093
1094 def SetPage(self, page):
1095 self.page = page
1096
1097
1098 def SetPageSize(self, width, height):
1099 self.pwidth, self.pheight = width, height
1100
1101
1102 def SetTotalSize(self, width, height):
1103 self.ptwidth, self.ptheight = width, height
1104
1105
1106 def SetPreview(self, preview, scale):
1107 self.preview = preview
1108 self.scale = scale
1109
1110
1111 def SetTotalSize(self, width, height):
1112 self.ptwidth = width
1113 self.ptheight = height
1114
1115 #-------------------------------------------------------------------------------
1116
1117 class PrintGrid(object):
1118 """
1119 ...
1120 """
1121 def __init__(self, parent, grid, format = [], total_col = None, total_row = None):
1122 if total_row is None:
1123 total_row = grid.GetNumberRows()
1124 if total_col is None:
1125 total_col = grid.GetNumberCols()
1126
1127 self.total_row = total_row
1128 self.total_col = total_col
1129 self.grid = grid
1130
1131 data = []
1132 for row in range(total_row):
1133 row_val = []
1134 value = grid.GetRowLabelValue(row)
1135 row_val.append(value)
1136
1137 for col in range(total_col):
1138 value = grid.GetCellValue(row, col)
1139 row_val.append(value)
1140 data.append(row_val)
1141
1142 label = [""]
1143 for col in range(total_col):
1144 value = grid.GetColLabelValue(col)
1145 label.append(value)
1146
1147 self.table = PrintTable(parent)
1148 self.table.cell_left_margin = 0.0
1149 self.table.cell_right_margin = 0.0
1150
1151 self.table.label = label
1152 self.table.set_column = format
1153 self.table.data = data
1154
1155 #---------------------------------------------------------------------------
1156
1157 def GetTable(self):
1158 return self.table
1159
1160
1161 def SetAttributes(self):
1162 for row in range(self.total_row):
1163 for col in range(self.total_col):
1164 colour = self.grid.GetCellTextColour(row, col-1)
1165 self.table.SetCellText(row, col, colour)
1166
1167 colour = self.grid.GetCellBackgroundColour(row, col-1)
1168 self.table.SetCellColour(row, col, colour)
1169
1170
1171 def Preview(self):
1172 self.table.Preview()
1173
1174
1175 def Print(self):
1176 self.table.Print()
1177
1178 #-------------------------------------------------------------------------------
1179
1180 class SetPrintout(wx.Printout):
1181 """
1182 ...
1183 """
1184 def __init__(self, canvas, text):
1185 wx.Printout.__init__(self)
1186
1187 self.canvas = canvas
1188 self.end_pg = 1000
1189 self.lines = text
1190
1191 #---------------------------------------------------------------------------
1192
1193 def OnBeginDocument(self, start, end):
1194 return super(SetPrintout, self).OnBeginDocument(start, end)
1195
1196
1197 def OnEndDocument(self):
1198 super(SetPrintout, self).OnEndDocument()
1199
1200
1201 def HasPage(self, page):
1202 try:
1203 end = self.canvas.HasPage(page)
1204 return end
1205 except:
1206 return True
1207
1208
1209 def GetPageInfo(self):
1210 try:
1211 self.end_pg = self.canvas.GetTotalPages()
1212 except:
1213 pass
1214
1215 end_pg = self.end_pg
1216 str_pg = 1
1217 return (str_pg, end_pg, str_pg, end_pg)
1218
1219
1220 def OnPreparePrinting(self):
1221 super(SetPrintout, self).OnPreparePrinting()
1222
1223
1224 def OnBeginPrinting(self):
1225 dc = self.GetDC()
1226
1227 self.preview = self.IsPreview()
1228 if (self.preview):
1229 self.pixelsPerInch = self.GetPPIScreen()
1230 else:
1231 self.pixelsPerInch = self.GetPPIPrinter()
1232
1233 (w, h) = dc.GetSize()
1234 scaleX = float(w) / 1000
1235 scaleY = float(h) / 1000
1236 self.printUserScale = min(scaleX, scaleY)
1237
1238 super(SetPrintout, self).OnBeginPrinting()
1239
1240
1241 def GetSize(self):
1242 self.psizew, self.psizeh = self.GetPPIPrinter()
1243 return self.psizew, self.psizeh
1244
1245
1246 def GetTotalSize(self):
1247 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1248 return self.ptsizew, self.ptsizeh
1249
1250
1251 def OnPrintPage(self, page):
1252 dc = self.GetDC()
1253 (w, h) = dc.GetSize()
1254 scaleX = float(w) / 1000
1255 scaleY = float(h) / 1000
1256 self.printUserScale = min(scaleX, scaleY)
1257 dc.SetUserScale(self.printUserScale, self.printUserScale)
1258
1259 self.preview = self.IsPreview()
1260
1261 self.canvas.SetPreview(self.preview, self.printUserScale)
1262 self.canvas.SetPage(page)
1263
1264 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1265 self.canvas.SetTotalSize(self.ptsizew, self.ptsizeh)
1266
1267 self.psizew, self.psizeh = self.GetPPIPrinter()
1268 self.canvas.SetPageSize(self.psizew, self.psizeh)
1269
1270 self.canvas.DoDrawing(dc)
1271 return True
1272
1273 #-------------------------------------------------------------------------------
1274
1275 class Frame(wx.Frame):
1276 """
1277 ...
1278 """
1279 def __init__(self, parent, id, title=""):
1280 wx.Frame.__init__(self,
1281 parent,
1282 id,
1283 title,
1284 size=(600, 450),
1285 style=wx.DEFAULT_FRAME_STYLE)
1286
1287 #------------
1288
1289 # Simplified init method.
1290 self.SetProperties()
1291 self.CreateMenu()
1292 self.CreateCtrls()
1293 self.CreatePrintData()
1294 self.BindEvents()
1295 self.DoLayout()
1296
1297 #------------
1298
1299 self.CenterOnScreen()
1300
1301 #---------------------------------------------------------------------------
1302
1303 def SetProperties(self):
1304 """
1305 Set the main frame properties (title, icon...).
1306 """
1307
1308 self.SetTitle("Dummy wx frame for testing printout.py")
1309
1310
1311 def CreateMenu(self):
1312 """
1313 ...
1314 """
1315
1316 menub = wx.MenuBar()
1317
1318 fmenu = wx.Menu()
1319 fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
1320 fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
1321 fmenu.AppendSeparator()
1322 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
1323 menub.Append(fmenu, "&File")
1324
1325 self.SetMenuBar(menub)
1326
1327
1328 def CreateCtrls(self):
1329 """
1330 ...
1331 """
1332
1333 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
1334 font.SetWeight(wx.BOLD)
1335 font.SetPointSize(10)
1336
1337 #------------
1338
1339 # First create the controls.
1340 self.panel = wx.Panel(self, -1,
1341 style=wx.BORDER_THEME|
1342 wx.TAB_TRAVERSAL)
1343
1344 self.demo = wx.StaticText(self.panel,
1345 id=-1,
1346 label="Demonstrating :")
1347 self.demo.SetFont(font)
1348
1349 self.info = wx.StaticText(self.panel,
1350 id=-1,
1351 label="1) Direct printing,\n"
1352 "2) Printout class,\n"
1353 "3) PrintTable class,\n"
1354 "4) Preview,\n"
1355 "5) Menu")
1356 self.info.SetForegroundColour("red")
1357 font.SetWeight(wx.NORMAL)
1358 self.info.SetFont(font)
1359
1360 text = ('This the first line of text.\n'\
1361 'This is the second line and the third. The fourth will be the number 4.0.\n'\
1362 '4.0\n'\
1363 'This is the fifth line, but by design it is too long to fit in the width of a standard'\
1364 'page, so it will be forced to wrap around in order to fit without having'\
1365 'some of its verbose verbage truncated.\n'
1366 'Here we have the final line.')
1367
1368 self.tc = wx.TextCtrl(self.panel,
1369 id=-1,
1370 size=(200, -1),
1371 value=text,
1372 style=wx.TE_MULTILINE|wx.TE_DONTWRAP)
1373
1374 self.btnPreview = wx.Button(self.panel,
1375 id=wx.ID_PREVIEW,
1376 label="Print pre&view")
1377 self.btnPreview.SetFocus()
1378
1379 self.btnPrint = wx.Button(self.panel,
1380 id=wx.ID_PRINT,
1381 label="&Print")
1382
1383 self.btnClose = wx.Button(self.panel,
1384 id=wx.ID_CLOSE,
1385 label="E&xit")
1386
1387
1388 def CreatePrintData(self):
1389 """
1390 Create printing data.
1391 """
1392
1393 self.ptbl = PrintTable(self)
1394 self.ptbl.SetHeader('This is the test HEADER')
1395 self.ptbl.SetFooter()
1396
1397 #... but, if labels or columns are defined, a single sequence will print out as a single row
1398 self.ptbl.label = ('One','Two','Three','Four','5')
1399
1400
1401 def BindEvents(self):
1402 """
1403 Bind all the events related to my application.
1404 """
1405
1406 # Bind some menu events to an events handler.
1407 self.Bind(wx.EVT_MENU, self.OnPrintPreview, id=wx.ID_PREVIEW)
1408 self.Bind(wx.EVT_MENU, self.OnPrint, id=wx.ID_PRINT)
1409 self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_EXIT)
1410
1411 # Bind the close event to an event handler.
1412 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
1413
1414 # Bind some buttons events to an events handler.
1415 self.Bind(wx.EVT_BUTTON, self.OnPrintPreview, self.btnPreview)
1416 self.Bind(wx.EVT_BUTTON, self.OnPrint, self.btnPrint)
1417 self.Bind(wx.EVT_BUTTON, self.OnClose, self.btnClose)
1418
1419
1420 def DoLayout(self):
1421 """
1422 Manage widgets Layout.
1423 """
1424
1425 # MainSizer is the top-level one that manages everything.
1426 mainSizer = wx.BoxSizer(wx.VERTICAL)
1427
1428 #------------
1429
1430 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
1431 hBox1.Add(self.info, 0, wx.ALL, 15)
1432
1433 #------------
1434
1435 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
1436 hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
1437 hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
1438 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
1439
1440 #------------
1441
1442 mainSizer.Add(self.demo, 0, wx.ALL, 10)
1443 mainSizer.Add(wx.StaticLine(self.panel),
1444 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
1445 mainSizer.Add(self.tc, 1, wx.EXPAND | wx.ALL, 15)
1446 mainSizer.Add(hBox1, 0, wx.ALL, 5)
1447 mainSizer.Add(hBox2, 0, wx.ALL, 5)
1448
1449 #------------
1450
1451 # Finally, tell the panel to use the mainSizer for layout.
1452 self.panel.SetSizer(mainSizer)
1453
1454
1455 def OnPrintPreview(self, event):
1456 text = self.tc.GetValue()
1457 resultat = text.splitlines()
1458 self.ptbl.data = (resultat)
1459 self.ptbl.Preview()
1460
1461
1462 def OnPrint(self, event):
1463 text = self.tc.GetValue()
1464 resultat = text.splitlines()
1465 self.ptbl.data = (resultat)
1466 self.ptbl.Print()
1467
1468
1469 def OnClose(self, evt):
1470 self.Close()
1471
1472
1473 def OnCloseWindow(self, event):
1474 """
1475 ...
1476 """
1477
1478 self.Destroy()
1479
1480 #-------------------------------------------------------------------------------
1481
1482 class App(wx.App):
1483 """
1484 ...
1485 """
1486 def OnInit(self):
1487
1488 #------------
1489
1490 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
1491
1492 #------------
1493
1494 frame = Frame(None, id=-1)
1495 self.SetTopWindow(frame)
1496 frame.Show(True)
1497
1498 return True
1499
1500 #-------------------------------------------------------------------------------
1501
1502 def main():
1503 app = App(False)
1504 app.MainLoop()
1505
1506 #-------------------------------------------------------------------------------
1507
1508 if __name__ == "__main__" :
1509 main()
Note : you should create the printing data structures only for printing and destroy them after printing again. There is no point in storing them permanently as self.grdprt.
Thanks to Dietmar Schwertberger for this info.
Special concerns or comments about the Easy Printing approach :
- Very simple to use.
- As powerful as HTML
- Seems to be limited around the capabilities of HTML (e.g. seems to have less control over printing configuration. Please correct me if I'm wrong).
Change the GetHtmlText code to be more appropriate with the kind of text you will be using.
Easy html direct printing
1 # sample_six.py
2
3 import os
4 import wx
5 from wx.html import HtmlEasyPrinting
6 from wx.html import HtmlWindow
7
8 # class MyHtmlPrinter
9 # class MyFrame
10 # class MyApp
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 # Sample html.
24 sample_html = """<html>
25 <body>
26 <h2><FONT COLOR=\"blue\">Sample printing </FONT></h2>
27 <p><B>Vestibulum</B> in tellus non nunc mollis sagittis sit amet ac purus.
28 Nam convallis vulputate tortor nec elementum. Nunc dictum accumsan
29 arcu ut lacinia. Nullam enim neque, consequat quis bibendum vitae,
30 gravida nec arcu. Nullam molestie dapibus sapien quis consectetur.
31 Donec lacinia, ante non faucibus ornare, purus sapien venenatis
32 turpis, ut eleifend lorem purus eu nisl. Pellentesque eget leo a augue
33 ullamcorper interdum at et nibh. Sed aliquet convallis dui, id
34 condimentum orci viverra ac. Morbi quis mauris nisl, vel malesuada
35 libero. Nam eleifend odio velit. Nulla vulputate facilisis mi
36 tincidunt tempus. Nam eu metus elit. <B>Vestibulum</B> ante ipsum primis in
37 faucibus orci luctus et ultrices posuere cubilia Curae; <B>Vestibulum</B> eu
38 risus accumsan leo egestas rutrum vitae in urna. Morbi diam orci,
39 eleifend a tempor sit amet, cursus sit amet est.</p>
40 <p><FONT COLOR=\"red\">WxPython </FONT><B>HtmlEasyPrinting </B>test.</p>
41 </body>
42 </html>"""
43
44 #-------------------------------------------------------------------------------
45
46 class MyHtmlPrinter(HtmlEasyPrinting):
47 """
48 ...
49 """
50 def __init__(self, parent):
51
52 # Get the window name.
53 name = "My document"
54
55 # Init the HtmlEasyPrinting.
56 HtmlEasyPrinting.__init__(self, name, parent)
57
58 # Get the current script directory.
59 self.current_dir = os.path.normpath(os.path.dirname(__file__))
60
61 # Set some default printer and page options.
62 self.GetPrintData().SetPaperId(wx.PAPER_LETTER) # wx.PAPER_A4
63 self.GetPrintData().SetOrientation(wx.LANDSCAPE) # wx.PORTRAIT
64 # Black and white printing if False.
65 self.GetPrintData().SetColour(True)
66 self.GetPageSetupData().SetMarginTopLeft((20, 20))
67 self.GetPageSetupData().SetMarginBottomRight((20, 20))
68
69 #---------------------------------------------------------------------------
70
71 def page_setup(self):
72 """
73 Show page setup.
74 """
75
76 self.PageSetup()
77
78
79 def print_text(self, text):
80 """
81 Print the text.
82 """
83
84 return self.PrintText(text, basepath=self.current_dir)
85
86
87 def preview_text(self, text):
88 """
89 Preview html text.
90 """
91
92 # @DATE @ is replaced by the current date in default format.
93 # @PAGENUM@ is replaced by page number.
94 # @PAGESCNT@ is replaced by total number of pages.
95 # @TIME @ is replaced by the current time in default format.
96 # @TITLE@ is replaced with the title of the document.
97
98 header = "My document"
99 footer = "Page @PAGENUM@ of @PAGESCNT@"
100
101 self.SetHeader(header)
102 self.SetFooter(footer)
103
104 return self.PreviewText(text, basepath=self.current_dir)
105
106
107 def print_file(self, file):
108 """
109 Print the text.
110 """
111
112 return self.PrintFile(file)
113
114
115 def preview_file(self, file):
116 """
117 Preview html file.
118 """
119
120 return self.PreviewFile(file)
121
122 #-------------------------------------------------------------------------------
123
124 class MyFrame(wx.Frame):
125 """
126 Create a main frame for my application.
127 """
128 def __init__ (self, parent, id, title=""):
129 wx.Frame.__init__(self,
130 parent,
131 id,
132 title,
133 size=(600, 610),
134 style=wx.DEFAULT_FRAME_STYLE)
135
136 #------------
137
138 # Simplified init method.
139 self.SetProperties()
140 self.CreateMenu()
141 self.CreateCtrls()
142 self.CreatePrinter()
143 self.BindEvents()
144 self.DoLayout()
145
146 #------------
147
148 self.CenterOnScreen()
149
150 #---------------------------------------------------------------------------
151
152 def SetProperties(self):
153 """
154 Set the main frame properties (title, icon...).
155 """
156
157 self.SetTitle("Html easy printing...")
158
159
160 def CreateMenu(self):
161 """
162 Make the frame menus.
163 """
164
165 menub = wx.MenuBar()
166
167 fmenu = wx.Menu()
168 fmenu.Append(wx.ID_PAGE_SETUP, "Page set&up\tCtrl+U")
169 fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
170 fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
171 fmenu.AppendSeparator()
172 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
173 menub.Append(fmenu, "&File")
174
175 self.SetMenuBar(menub)
176
177
178 def CreateCtrls(self):
179 """
180 Make widgets for my application.
181 """
182
183 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
184 font.SetWeight(wx.BOLD)
185 font.SetPointSize(10)
186
187 #------------
188
189 # First create the controls.
190 self.panel = wx.Panel(self,
191 id=-1,
192 style=wx.BORDER_THEME|
193 wx.TAB_TRAVERSAL)
194
195 self.demo = wx.StaticText(self.panel,
196 id=-1,
197 label="Demonstrating :")
198 self.demo.SetFont(font)
199
200 self.winHtml = HtmlWindow(self.panel,
201 id=-1,
202 style=wx.BORDER_THEME|
203 wx.NO_FULL_REPAINT_ON_RESIZE)
204 self.winHtml.SetPage(sample_html)
205
206 self.info = wx.StaticText(self.panel,
207 id=-1,
208 label="1) Direct printing,\n"
209 "2) HtmlWindow,\n"
210 "3) HtmlEasyPrinting class,\n"
211 "4) Preview,\n"
212 "5) Menu,\n"
213 "6) Page setup.")
214 self.info.SetForegroundColour("red")
215 font.SetWeight(wx.NORMAL)
216 self.info.SetFont(font)
217
218 self.btnSetup = wx.Button(self.panel,
219 id=wx.ID_PAGE_SETUP,
220 label="Page set&up")
221
222 self.btnPreview = wx.Button(self.panel,
223 wx.ID_PREVIEW,
224 label="Pre&view text")
225 self.btnPreview.SetFocus()
226
227 self.btnPrint = wx.Button(self.panel,
228 id=wx.ID_PRINT,
229 label="&Print")
230
231 self.btnClose = wx.Button(self.panel,
232 id=wx.ID_CLOSE,
233 label="E&xit")
234
235
236 def CreatePrinter(self):
237 """
238 Create the printer.
239 """
240
241 self.printer = MyHtmlPrinter(self)
242
243
244 def BindEvents(self):
245 """
246 Bind all the events related to my application.
247 """
248
249 # Bind some menu events to an events handler.
250 self.Bind(wx.EVT_MENU, self.OnBtnPageSetup, id=wx.ID_PAGE_SETUP)
251 self.Bind(wx.EVT_MENU, self.OnBtnPreview, id=wx.ID_PREVIEW)
252 self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
253 self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
254
255 # Bind some buttons events to an events handler.
256 self.Bind(wx.EVT_BUTTON, self.OnBtnPageSetup, self.btnSetup)
257 self.Bind(wx.EVT_BUTTON, self.OnBtnPreview, self.btnPreview)
258 self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
259 self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
260
261 # Bind the close event to an event handler.
262 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
263
264
265 def DoLayout(self):
266 """
267 Manage widgets Layout.
268 """
269
270 # MainSizer is the top-level one that manages everything.
271 mainSizer = wx.BoxSizer(wx.VERTICAL)
272
273 #------------
274
275 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
276 hBox1.Add(self.info, 0, wx.ALL, 15)
277
278 #------------
279
280 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
281 hBox2.Add(self.btnSetup, 0, wx.ALL, 10)
282 hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
283 hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
284 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
285
286 #------------
287
288 mainSizer.Add(self.demo, 0, wx.ALL, 10)
289 mainSizer.Add(wx.StaticLine(self.panel),
290 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
291 mainSizer.Add(self.winHtml, 1, wx.EXPAND | wx.ALL, 15)
292 mainSizer.Add(hBox1, 0, wx.ALL, 5)
293 mainSizer.Add(hBox2, 0, wx.ALL, 5)
294
295 #------------
296
297 # Finally, tell the panel to use the mainSizer for layout.
298 self.panel.SetSizer(mainSizer)
299
300
301 def OnBtnPageSetup(self, event):
302 """
303 Page setup click.
304 """
305
306 # Page setup dialog.
307 self.printer.page_setup()
308
309
310 def OnBtnPreview(self, event):
311 """
312 Print preview click.
313 """
314
315 # Preview html text.
316 print("Preview result :", self.printer.preview_text(sample_html))
317
318
319 def OnBtnPrint(self, event):
320 """
321 Print click.
322 """
323
324 # Print html text.
325 print("Print result :", self.printer.print_text(sample_html))
326
327
328 def OnBtnClose(self, event):
329 """
330 Close application.
331 """
332
333 self.Close(True)
334
335
336 def OnCloseWindow(self, event):
337 """
338 Destroy application.
339 """
340
341 self.Destroy()
342
343 #-------------------------------------------------------------------------------
344
345 class MyApp(wx.App):
346 """
347 wx.App sub-class that is the example application.
348 """
349 def OnInit(self):
350 """
351 Init MyApp instance.
352 """
353
354 #------------
355
356 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
357
358 #------------
359
360 frame = MyFrame(None, id=-1)
361 self.SetTopWindow(frame)
362 frame.Show(True)
363
364 return True
365
366 #-------------------------------------------------------------------------------
367
368 def main():
369 app = MyApp(False)
370 app.MainLoop()
371
372 #-------------------------------------------------------------------------------
373
374 if __name__ == "__main__" :
375 main()
Easy html multilines printing
1 # sample_seven.py
2
3 import os
4 import wx
5 from wx.html import HtmlEasyPrinting
6
7 # class MyHtmlPrinter
8 # class MyFrame
9 # class MyApp
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 MyHtmlPrinter(HtmlEasyPrinting):
23 """
24 ...
25 """
26 def __init__(self, parent):
27
28 # Get the window name.
29 name = "My document"
30
31 # Init the HtmlEasyPrinting.
32 HtmlEasyPrinting.__init__(self, name, parent)
33
34 # Get the current script directory.
35 self.current_dir = os.path.normpath(os.path.dirname(__file__))
36
37 # Set some default printer and page options.
38 self.GetPrintData().SetPaperId(wx.PAPER_LETTER) # wx.PAPER_A4
39 self.GetPrintData().SetOrientation(wx.LANDSCAPE) # wx.PORTRAIT
40 # Black and white printing if False.
41 self.GetPrintData().SetColour(True)
42 self.GetPageSetupData().SetMarginTopLeft((20, 20))
43 self.GetPageSetupData().SetMarginBottomRight((20, 20))
44
45 #---------------------------------------------------------------------------
46
47 def GetHtmlText(self, text):
48 """
49 Simple conversion of text.
50 Use a more powerful version.
51 """
52
53 html_text = text.replace("\n\n", "<P>")
54 html_text = text.replace("\n", "<BR>")
55
56 return html_text
57
58
59 def page_setup(self):
60 """
61 Show page setup.
62 """
63
64 self.PageSetup()
65
66
67 def print_text(self, text):
68 """
69 Print the text.
70 """
71
72 return self.PrintText(self.GetHtmlText(text), basepath=self.current_dir)
73
74
75 def preview_text(self, text):
76 """
77 Preview html text.
78 """
79
80 # @DATE @ is replaced by the current date in default format.
81 # @PAGENUM@ is replaced by page number.
82 # @PAGESCNT@ is replaced by total number of pages.
83 # @TIME @ is replaced by the current time in default format.
84 # @TITLE@ is replaced with the title of the document.
85
86 header = "My document"
87 footer = "Page @PAGENUM@ of @PAGESCNT@"
88
89 self.SetHeader(header)
90 self.SetFooter(footer)
91
92 return self.PreviewText(self.GetHtmlText(text), basepath=self.current_dir)
93
94
95 def print_file(self, file):
96 """
97 Print the text.
98 """
99
100 return self.PrintFile(file)
101
102
103 def preview_file(self, file):
104 """
105 Preview html file.
106 """
107
108 return self.PreviewFile(file)
109
110 #-------------------------------------------------------------------------------
111
112 class MyFrame(wx.Frame):
113 """
114 Create a main frame for my application.
115 """
116 def __init__ (self, parent, id, title=""):
117 wx.Frame.__init__(self,
118 parent,
119 id,
120 title,
121 size=(600, 450),
122 style=wx.DEFAULT_FRAME_STYLE)
123
124 #------------
125
126 # Simplified init method.
127 self.SetProperties()
128 self.CreateMenu()
129 self.CreateCtrls()
130 self.CreatePrinter()
131 self.BindEvents()
132 self.DoLayout()
133
134 #------------
135
136 self.CenterOnScreen()
137
138 #---------------------------------------------------------------------------
139
140 def SetProperties(self):
141 """
142 Set the main frame properties (title, icon...).
143 """
144
145 self.SetTitle("Html easy printing...")
146
147
148 def CreateMenu(self):
149 """
150 Make the frame menus.
151 """
152
153 menub = wx.MenuBar()
154
155 fmenu = wx.Menu()
156 fmenu.Append(wx.ID_PAGE_SETUP, "Page set&up\tCtrl+U")
157 fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
158 fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
159 fmenu.AppendSeparator()
160 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
161 menub.Append(fmenu, "&File")
162
163 self.SetMenuBar(menub)
164
165
166 def CreateCtrls(self):
167 """
168 Make widgets for my application.
169 """
170
171 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
172 font.SetWeight(wx.BOLD)
173 font.SetPointSize(10)
174
175 #------------
176
177 # First create the controls.
178 self.panel = wx.Panel(self,
179 id=-1,
180 style=wx.BORDER_THEME|
181 wx.TAB_TRAVERSAL)
182
183 self.demo = wx.StaticText(self.panel,
184 id=-1,
185 label="Demonstrating :")
186 self.demo.SetFont(font)
187
188 self.info = wx.StaticText(self.panel,
189 id=-1,
190 label="1) Direct printing,\n"
191 "2) HtmlEasyPrinting class,\n"
192 "3) Preview,\n"
193 "4) Menu,\n"
194 "5) Page setup.")
195 self.info.SetForegroundColour("red")
196 font.SetWeight(wx.NORMAL)
197 self.info.SetFont(font)
198
199 text = ('This the first line of text.\n'\
200 'This is the second line\nand the third. The fourth will be the number 4.0.\n'\
201 '4.0\n'\
202 'This is the fifth line, but by design it is too long to fit in the width of a standard'\
203 'page, so it will be forced to wrap around in order to fit without having'\
204 'some of its verbose verbage truncated.\n'\
205 'Here we have the final line.')
206
207 self.tc = wx.TextCtrl(self.panel,
208 id=-1,
209 size=(200, -1),
210 value=text,
211 style=wx.TE_MULTILINE|wx.TE_DONTWRAP)
212
213 self.btnSetup = wx.Button(self.panel,
214 id=wx.ID_PAGE_SETUP,
215 label="Page set&up")
216
217 self.btnPreview = wx.Button(self.panel,
218 wx.ID_PREVIEW,
219 label="Pre&view text")
220 self.btnPreview.SetFocus()
221
222 self.btnPrint = wx.Button(self.panel,
223 id=wx.ID_PRINT,
224 label="&Print")
225
226 self.btnClose = wx.Button(self.panel,
227 id=wx.ID_CLOSE,
228 label="E&xit")
229
230
231 def CreatePrinter(self):
232 """
233 Create the printer.
234 """
235
236 self.printer = MyHtmlPrinter(self)
237
238
239 def BindEvents(self):
240 """
241 Bind all the events related to my application.
242 """
243
244 # Bind some menu events to an events handler.
245 self.Bind(wx.EVT_MENU, self.OnBtnPageSetup, id=wx.ID_PAGE_SETUP)
246 self.Bind(wx.EVT_MENU, self.OnBtnPreview, id=wx.ID_PREVIEW)
247 self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
248 self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
249
250 # Bind some buttons events to an events handler.
251 self.Bind(wx.EVT_BUTTON, self.OnBtnPageSetup, self.btnSetup)
252 self.Bind(wx.EVT_BUTTON, self.OnBtnPreview, self.btnPreview)
253 self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
254 self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
255
256 # Bind the close event to an event handler.
257 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
258
259
260 def DoLayout(self):
261 """
262 Manage widgets Layout.
263 """
264
265 # MainSizer is the top-level one that manages everything.
266 mainSizer = wx.BoxSizer(wx.VERTICAL)
267
268 #------------
269
270 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
271 hBox1.Add(self.info, 0, wx.ALL, 15)
272
273 #------------
274
275 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
276 hBox2.Add(self.btnSetup, 0, wx.ALL, 10)
277 hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
278 hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
279 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
280
281 #------------
282
283 mainSizer.Add(self.demo, 0, wx.ALL, 10)
284 mainSizer.Add(wx.StaticLine(self.panel),
285 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
286 mainSizer.Add(self.tc, 1, wx.EXPAND | wx.ALL, 15)
287 mainSizer.Add(hBox1, 0, wx.ALL, 5)
288 mainSizer.Add(hBox2, 0, wx.ALL, 5)
289
290 #------------
291
292 # Finally, tell the panel to use the mainSizer for layout.
293 self.panel.SetSizer(mainSizer)
294
295
296 def OnBtnPageSetup(self, event):
297 """
298 Page setup click.
299 """
300
301 # Page setup dialog.
302 self.printer.page_setup()
303
304
305 def OnBtnPreview(self, event):
306 """
307 Print preview click.
308 """
309
310 self.sample_html = self.tc.GetValue()
311
312 # Preview html text.
313 print("Preview result :", self.printer.preview_text(self.sample_html))
314
315
316 def OnBtnPrint(self, event):
317 """
318 Print click.
319 """
320
321 self.sample_html = self.tc.GetValue()
322
323 # Print html text.
324 print("Print result :", self.printer.print_text(self.sample_html))
325
326
327 def OnBtnClose(self, event):
328 """
329 Close application.
330 """
331
332 self.Close(True)
333
334
335 def OnCloseWindow(self, event):
336 """
337 Destroy application.
338 """
339
340 self.Destroy()
341
342 #-------------------------------------------------------------------------------
343
344 class MyApp(wx.App):
345 """
346 wx.App sub-class that is the example application.
347 """
348 def OnInit(self):
349 """
350 Init MyApp instance.
351 """
352
353 #------------
354
355 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
356
357 #------------
358
359 frame = MyFrame(None, id=-1)
360 self.SetTopWindow(frame)
361 frame.Show(True)
362
363 return True
364
365 #-------------------------------------------------------------------------------
366
367 def main():
368 app = MyApp(False)
369 app.MainLoop()
370
371 #-------------------------------------------------------------------------------
372
373 if __name__ == "__main__" :
374 main()
Easy html grid printing
HTML file : template.html
1 <!doctype html>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html" charset="utf-8">
5 </head>
6 <body>
7 <table width="50%" cellspacing='2' cellpadding='0' border='0' bgcolor="black">
8
9 <tr>
10 <td align=center colspan="2" rowspan="1" width="20%" bgcolor="red">
11 <table cellspacing="7" cellpadding="0" border="0"><tr><td align=center><b><font face="Tahoma" color="white" size="3"> FIRSTNAME </font></b></td></tr></table>
12 </td>
13
14 <td align=center colspan="2" rowspan="1" width="80%" bgcolor="yellow">
15 <table cellspacing="7" cellpadding="0" border="0"><tr><td align=center><b><font face="Tahoma" color="black" size="3"> {{FIRSTNAME}} </font></b></td></tr></table>
16 </td>
17 </tr>
18
19
20
21 <tr>
22 <td align=center colspan="2" rowspan="1" width="20%" bgcolor="red">
23 <table cellspacing="7" cellpadding="0" border="0"><tr><td align=center><b><font face="Tahoma" color="white" size="3"> SURNAME </font></b></td></tr></table>
24 </td>
25
26 <td align=center colspan="2" rowspan="1" width="80%" bgcolor="yellow">
27 <table cellspacing="7" cellpadding="0" border="0"><tr><td align=center><b><font face="Tahoma" color="black" size="3"> {{SURNAME}} </font></b></td></tr></table>
28 </td>
29 </tr>
30
31
32
33 <tr>
34 <td align=center colspan="2" rowspan="1" width="20%" bgcolor="red">
35 <table cellspacing="7" cellpadding="0" border="0"><tr><td align=center><b><font face="Tahoma" color="white" size="3"> AGE </font></b></td></tr></table>
36 </td>
37
38 <td align=center colspan="2" rowspan="1" width="80%" bgcolor="yellow">
39 <table cellspacing="7" cellpadding="0" border="0"><tr><td align=center><b><font face="Tahoma" color="black" size="3"> {{AGE}} </font></b></td></tr></table>
40 </td>
41 </tr>
42
43 </table>
44 </body>
45 </html>
1 # sample_eight.py
2
3 import os
4 import sys
5 import wx
6 from wx.html import HtmlEasyPrinting
7 from wx.html import HtmlWindow
8
9 # class MyHtmlPrinter
10 # class MyFrame
11 # class MyApp
12
13 app_dir = os.path.split(os.path.abspath(sys.argv[0]))[0]
14 html_file = os.path.join(app_dir, "template.html")
15
16 #-------------------------------------------------------------------------------
17
18 if os.name == "posix":
19 print("\nPlatform : UNIX - Linux")
20 elif os.name in ['nt', 'dos', 'ce']:
21 print("\nPlatform : Windows")
22 else:
23 print("\nPlatform : ", platform.system())
24
25 #-------------------------------------------------------------------------------
26
27 class MyHtmlPrinter(HtmlEasyPrinting):
28 """
29 ...
30 """
31 def __init__(self, parent):
32
33 # Get the window name.
34 name = "Person"
35
36 # Init the HtmlEasyPrinting.
37 HtmlEasyPrinting.__init__(self, name, parent)
38
39 # Get the current script directory.
40 self.current_dir = os.path.normpath(os.path.dirname(__file__))
41
42 # Set some default printer and page options.
43 self.GetPrintData().SetPaperId(wx.PAPER_LETTER) # wx.PAPER_A4
44 self.GetPrintData().SetOrientation(wx.LANDSCAPE) # wx.PORTRAIT
45 # Black and white printing if False.
46 self.GetPrintData().SetColour(True)
47 self.GetPageSetupData().SetMarginTopLeft((20, 20))
48 self.GetPageSetupData().SetMarginBottomRight((20, 20))
49
50 #---------------------------------------------------------------------------
51
52 def page_setup(self):
53 """
54 Show page setup.
55 """
56
57 self.PageSetup()
58
59
60 def print_text(self, text):
61 """
62 Print the text.
63 """
64
65 return self.PrintText(text, basepath=self.current_dir)
66
67
68 def preview_text(self, text):
69 """
70 Preview html text.
71 """
72
73 # @DATE @ is replaced by the current date in default format.
74 # @PAGENUM@ is replaced by page number.
75 # @PAGESCNT@ is replaced by total number of pages.
76 # @TIME @ is replaced by the current time in default format.
77 # @TITLE@ is replaced with the title of the document.
78
79 header = "Person :"
80 footer = "Page @PAGENUM@ of @PAGESCNT@"
81
82 self.SetHeader(header)
83 self.SetFooter(footer)
84
85 return self.PreviewText(text, basepath=self.current_dir)
86
87
88 def print_file(self, file):
89 """
90 Print the text.
91 """
92
93 return self.PrintFile(file)
94
95
96 def preview_file(self, file):
97 """
98 Preview html file.
99 """
100
101 return self.PreviewFile(file)
102
103 #-------------------------------------------------------------------------------
104
105 class MyFrame(wx.Frame):
106 """
107 Create a main frame for my application.
108 """
109 def __init__ (self, parent, id, title=""):
110 wx.Frame.__init__(self,
111 parent,
112 id,
113 title,
114 size=(600, 417),
115 style=wx.DEFAULT_FRAME_STYLE)
116
117 #------------
118
119 # Sample html.
120 self.sample_html = None
121
122 #------------
123
124 # Simplified init method.
125 self.SetProperties()
126 self.CreateMenu()
127 self.CreateCtrls()
128 self.CreatePrinter()
129 self.BindEvents()
130 self.DoLayout()
131
132 #------------
133
134 self.CenterOnScreen()
135
136 #---------------------------------------------------------------------------
137
138 def SetProperties(self):
139 """
140 Set the main frame properties (title, icon...).
141 """
142
143 self.SetTitle("Html easy printing...")
144
145
146 def CreateMenu(self):
147 """
148 Make the frame menus.
149 """
150
151 menub = wx.MenuBar()
152
153 fmenu = wx.Menu()
154 fmenu.Append(wx.ID_PAGE_SETUP, "Page set&up\tCtrl+U")
155 fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
156 fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
157 fmenu.AppendSeparator()
158 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
159 menub.Append(fmenu, "&File")
160
161 self.SetMenuBar(menub)
162
163
164 def CreateCtrls(self):
165 """
166 Make widgets for my application.
167 """
168
169 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
170 font.SetWeight(wx.BOLD)
171 font.SetPointSize(10)
172
173 #------------
174
175 # First create the controls.
176 self.panel = wx.Panel(self,
177 id=-1,
178 style=wx.BORDER_THEME|
179 wx.TAB_TRAVERSAL)
180
181 self.demo = wx.StaticText(self.panel,
182 id=-1,
183 label="Demonstrating :")
184 self.demo.SetFont(font)
185
186 self.stFirstname = wx.StaticText(self.panel,
187 id=-1,
188 label="Firstname : ")
189
190 self.tcFirstname = wx.TextCtrl(self.panel,
191 id=-1,
192 size=(200, -1),
193 value="John")
194
195 self.stSurname = wx.StaticText(self.panel,
196 id=-1,
197 label="Surname : ")
198
199 self.tcSurname = wx.TextCtrl(self.panel,
200 id=-1,
201 size=(200, -1),
202 value="Doe")
203
204 self.stAge = wx.StaticText(self.panel,
205 id=-1,
206 label="Age : ")
207
208 self.tcAge = wx.TextCtrl(self.panel,
209 id=-1,
210 size=(200, -1),
211 value="32")
212
213 self.info = wx.StaticText(self.panel,
214 id=-1,
215 label="1) Direct printing,\n"
216 "2) HtmlEasyPrinting class,\n"
217 "3) Html file loading,\n"
218 "4) Preview,\n"
219 "5) Menu,\n"
220 "6) Page setup.")
221 self.info.SetForegroundColour("red")
222 font.SetWeight(wx.NORMAL)
223 self.info.SetFont(font)
224
225 self.btnSetup = wx.Button(self.panel,
226 id=wx.ID_PAGE_SETUP,
227 label="Page set&up")
228
229 self.btnPreview = wx.Button(self.panel,
230 wx.ID_PREVIEW,
231 label="Pre&view text")
232 self.btnPreview.SetFocus()
233
234 self.btnPrint = wx.Button(self.panel,
235 id=wx.ID_PRINT,
236 label="&Print")
237
238 self.btnClose = wx.Button(self.panel,
239 id=wx.ID_CLOSE,
240 label="E&xit")
241
242
243 def CreatePrinter(self):
244 """
245 Create the printer.
246 """
247
248 self.printer = MyHtmlPrinter(self)
249
250
251 def LoadTemplate(self, event):
252 """
253 Load html template.
254 """
255
256
257 sSurname = self.tcSurname.GetValue()
258 sFirstname = self.tcFirstname.GetValue()
259 sAge = self.tcAge.GetValue()
260
261 #------------
262
263 # Thanks to Pascal Faut.
264 # Returns html file ("template.html").
265 with open(html_file, "r") as MyTemplate:
266 strTemplate = MyTemplate.read()
267 self.sample_html = strTemplate
268
269 self.sample_html = self.sample_html.replace("{{SURNAME}}", sSurname)
270 self.sample_html = self.sample_html.replace("{{FIRSTNAME}}", sFirstname)
271 self.sample_html = self.sample_html.replace("{{AGE}}", sAge)
272
273
274 def BindEvents(self):
275 """
276 Bind all the events related to my application.
277 """
278
279 # Bind some menu events to an events handler.
280 self.Bind(wx.EVT_MENU, self.OnBtnPageSetup, id=wx.ID_PAGE_SETUP)
281 self.Bind(wx.EVT_MENU, self.OnBtnPreview, id=wx.ID_PREVIEW)
282 self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
283 self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
284
285 # Bind some buttons events to an events handler.
286 self.Bind(wx.EVT_BUTTON, self.OnBtnPageSetup, self.btnSetup)
287 self.Bind(wx.EVT_BUTTON, self.OnBtnPreview, self.btnPreview)
288 self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
289 self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
290
291 # Bind the close event to an event handler.
292 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
293
294
295 def DoLayout(self):
296 """
297 Manage widgets Layout.
298 """
299
300 # MainSizer is the top-level one that manages everything.
301 mainSizer = wx.BoxSizer(wx.VERTICAL)
302
303 #------------
304
305 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
306 hBox1.Add(self.info, 0, wx.ALL, 15)
307
308 #------------
309
310 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
311 hBox2.Add(self.btnSetup, 0, wx.ALL, 10)
312 hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
313 hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
314 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
315
316 #------------
317
318 # wx.GridBagSizer(vgap=0, hgap=0).
319 gSizer = wx.GridBagSizer(2, 2)
320 gSizer.Add(self.stFirstname, (0, 0), span=(wx.DefaultSpan),
321 flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
322 gSizer.Add(self.tcFirstname, (0, 1), span=wx.DefaultSpan)
323
324 gSizer.Add(self.stSurname, (1, 0), span=wx.DefaultSpan,
325 flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
326 gSizer.Add(self.tcSurname, (1, 1), span=wx.DefaultSpan)
327
328 gSizer.Add(self.stAge, (2, 0), span=wx.DefaultSpan,
329 flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
330 gSizer.Add(self.tcAge, (2, 1), span=wx.DefaultSpan)
331
332 #------------
333
334 mainSizer.Add(self.demo, 0, wx.ALL, 10)
335 mainSizer.Add(wx.StaticLine(self.panel),
336 0, wx.EXPAND|wx.TOP, 5)
337 mainSizer.Add(gSizer, 0, wx.ALL, 20)
338 mainSizer.Add(hBox1, 0, wx.LEFT|wx.BOTTOM, 5)
339 mainSizer.Add(hBox2, 0, wx.ALL, 5)
340
341 #------------
342
343 # Finally, tell the panel to use the mainSizer for layout.
344 self.panel.SetSizer(mainSizer)
345
346
347 def OnBtnPageSetup(self, event):
348 """
349 Page setup click.
350 """
351
352 # Page setup dialog.
353 self.printer.page_setup()
354
355
356 def OnBtnPreview(self, event):
357 """
358 Print preview click.
359 """
360
361 # Load template.
362 self.LoadTemplate(event)
363
364 if self.sample_html is not None:
365 # Preview html text.
366 print("Preview result:", self.printer.preview_text(self.sample_html))
367
368
369 def OnBtnPrint(self, event):
370 """
371 Print click.
372 """
373
374 # Load template.
375 self.LoadTemplate(event)
376
377 if self.sample_html is not None:
378 # Print html text.
379 print("Print result:", self.printer.print_text(self.sample_html))
380
381
382 def OnBtnClose(self, event):
383 """
384 Close application.
385 """
386
387 self.Close(True)
388
389
390 def OnCloseWindow(self, event):
391 """
392 Destroy application.
393 """
394
395 self.Destroy()
396
397 #-------------------------------------------------------------------------------
398
399 class MyApp(wx.App):
400 """
401 wx.App sub-class that is the example application.
402 """
403 def OnInit(self):
404 """
405 Init MyApp instance.
406 """
407
408 #------------
409
410 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
411
412 #------------
413
414 frame = MyFrame(None, id=-1)
415 self.SetTopWindow(frame)
416 frame.Show(True)
417
418 return True
419
420 #-------------------------------------------------------------------------------
421
422 def main():
423 app = MyApp(False)
424 app.MainLoop()
425
426 #-------------------------------------------------------------------------------
427
428 if __name__ == "__main__" :
429 main()
PDF file reading and printing :
First example
PDF file : wxpython.pdf
1 # sample_nine_a.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=(350, 300),
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 self.SetTitle("Reading test...")
55
56
57 def CreateMenu(self):
58 """
59 Make the frame menus.
60 """
61
62 menub = wx.MenuBar()
63
64 fmenu = wx.Menu()
65 fmenu.Append(-1, "Sho&w PDF\tCtrl+W")
66 fmenu.AppendSeparator()
67 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
68 menub.Append(fmenu, "&File")
69
70 self.SetMenuBar(menub)
71
72
73 def CreateCtrls(self):
74 """
75 Make widgets for my application.
76 """
77
78 boldFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
79 boldFont.SetWeight(wx.BOLD)
80 boldFont.SetPointSize(10)
81
82 #------------
83
84 # First create the controls.
85 self.panel = wx.Panel(self,
86 id=-1,
87 style=wx.BORDER_THEME|
88 wx.TAB_TRAVERSAL)
89
90 self.text = wx.StaticText(self.panel,
91 id=-1,
92 label="Demonstrating :")
93 self.text.SetFont(boldFont)
94
95 self.info = wx.StaticText(self.panel,
96 id=-1,
97 label="> Read PDF file with installed default program.")
98 self.info.SetForegroundColour("red")
99
100 self.btnView = wx.Button(self.panel,
101 id=-1,
102 label="Sho&w PDF")
103 self.btnView.SetFocus()
104
105 self.btnClose = wx.Button(self.panel,
106 id=wx.ID_CLOSE,
107 label="E&xit")
108
109
110 def BindEvents(self):
111 """
112 Bind all the events related to my application.
113 """
114
115 # Bind some menu events to an events handler.
116 self.Bind(wx.EVT_MENU, self.OnBtnViewPdf, id=-1)
117 self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
118
119 # Bind the close event to an event handler.
120 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
121
122 # Bind some buttons events to an events handler.
123 self.Bind(wx.EVT_BUTTON, self.OnBtnViewPdf, self.btnView)
124 self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
125
126
127 def DoLayout(self):
128 """
129 Manage widgets Layout.
130 """
131
132 # MainSizer is the top-level one that manages everything.
133 mainSizer = wx.BoxSizer(wx.VERTICAL)
134
135 #------------
136
137 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
138 hBox1.Add(self.info, 0, wx.ALL, 15)
139
140 #------------
141
142 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
143 hBox2.Add(self.btnView, 0, wx.ALL, 10)
144 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
145
146 #------------
147
148 mainSizer.Add(self.text, 0, wx.ALL, 10)
149 mainSizer.Add(wx.StaticLine(self.panel),
150 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
151 mainSizer.Add(hBox1, 0, wx.ALL, 5)
152 mainSizer.Add(hBox2, 0, wx.ALL, 5)
153
154 #------------
155
156 # Finally, tell the panel to use the mainSizer for layout.
157 self.panel.SetSizer(mainSizer)
158
159
160 def OnBtnViewPdf(self, event):
161 """
162 Launch a PDF program to read the file.
163 """
164
165 wx.BeginBusyCursor()
166 os.startfile("wxpython.pdf")
167 wx.CallAfter(wx.EndBusyCursor)
168
169
170 def OnBtnClose(self, event):
171 """
172 ...
173 """
174
175 self.Close(True)
176
177
178 def OnCloseWindow(self, event):
179 """
180 ...
181 """
182
183 self.Destroy()
184
185 #-------------------------------------------------------------------------------
186
187 class My_App(wx.App):
188 """
189 ...
190 """
191 def OnInit(self):
192
193 #------------
194
195 frame = My_Frame(None, id=-1)
196 self.SetTopWindow(frame)
197 frame.Show(True)
198
199 return True
200
201 #-------------------------------------------------------------------------------
202
203 def main():
204 app = My_App(False)
205 app.MainLoop()
206
207 #-------------------------------------------------------------------------------
208
209 if __name__ == "__main__" :
210 main()
Second example
PDF file : wxpython.pdf
1 # sample_nine_b.py
2
3 import sys
4 import os
5 import platform
6 import wx
7 import webbrowser
8
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_Frame(wx.Frame):
24 """
25 Create a main frame for my application.
26 """
27 def __init__(self, parent, id, title=""):
28 wx.Frame.__init__(self,
29 parent,
30 id,
31 title,
32 size=(350, 300),
33 style=wx.DEFAULT_FRAME_STYLE)
34
35 #------------
36
37 # Simplified init method.
38 self.SetProperties()
39 self.CreateMenu()
40 self.CreateCtrls()
41 self.BindEvents()
42 self.DoLayout()
43
44 #------------
45
46 self.CenterOnScreen()
47
48 #---------------------------------------------------------------------------
49
50 def SetProperties(self):
51 """
52 Set the main frame properties (title, icon...).
53 """
54
55 self.SetTitle("Reading test...")
56
57
58 def CreateMenu(self):
59 """
60 Make the frame menus.
61 """
62
63 menub = wx.MenuBar()
64
65 fmenu = wx.Menu()
66 fmenu.Append(-1, "Sho&w PDF\tCtrl+W")
67 fmenu.AppendSeparator()
68 fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
69 menub.Append(fmenu, "&File")
70
71 self.SetMenuBar(menub)
72
73
74 def CreateCtrls(self):
75 """
76 Make widgets for my application.
77 """
78
79 boldFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
80 boldFont.SetWeight(wx.BOLD)
81 boldFont.SetPointSize(10)
82
83 #------------
84
85 # First create the controls.
86 self.panel = wx.Panel(self,
87 id=-1,
88 style=wx.BORDER_THEME|
89 wx.TAB_TRAVERSAL)
90
91 self.text = wx.StaticText(self.panel,
92 id=-1,
93 label="Demonstrating :")
94 self.text.SetFont(boldFont)
95
96 self.info = wx.StaticText(self.panel,
97 id=-1,
98 label="> Read PDF file with default web browser.")
99 self.info.SetForegroundColour("red")
100
101 self.btnView = wx.Button(self.panel,
102 id=-1,
103 label="Sho&w PDF")
104 self.btnView.SetFocus()
105
106 self.btnClose = wx.Button(self.panel,
107 id=wx.ID_CLOSE,
108 label="E&xit")
109
110
111 def BindEvents(self):
112 """
113 Bind all the events related to my application.
114 """
115
116 # Bind some menu events to an events handler.
117 self.Bind(wx.EVT_MENU, self.OnBtnViewPdf, id=-1)
118 self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
119
120 # Bind the close event to an event handler.
121 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
122
123 # Bind some buttons events to an events handler.
124 self.Bind(wx.EVT_BUTTON, self.OnBtnViewPdf, self.btnView)
125 self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
126
127
128 def DoLayout(self):
129 """
130 Manage widgets Layout.
131 """
132
133 # MainSizer is the top-level one that manages everything.
134 mainSizer = wx.BoxSizer(wx.VERTICAL)
135
136 #------------
137
138 hBox1 = wx.BoxSizer(wx.HORIZONTAL)
139 hBox1.Add(self.info, 0, wx.ALL, 15)
140
141 #------------
142
143 hBox2 = wx.BoxSizer(wx.HORIZONTAL)
144 hBox2.Add(self.btnView, 0, wx.ALL, 10)
145 hBox2.Add(self.btnClose, 0, wx.ALL, 10)
146
147 #------------
148
149 mainSizer.Add(self.text, 0, wx.ALL, 10)
150 mainSizer.Add(wx.StaticLine(self.panel),
151 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
152 mainSizer.Add(hBox1, 0, wx.ALL, 5)
153 mainSizer.Add(hBox2, 0, wx.ALL, 5)
154
155 #------------
156
157 # Finally, tell the panel to use the mainSizer for layout.
158 self.panel.SetSizer(mainSizer)
159
160
161 def OnBtnViewPdf(self, event):
162 """
163 Launch a PDF program to read the file.
164 """
165
166 wx.BeginBusyCursor()
167 webbrowser.open_new("wxpython.pdf")
168 wx.CallAfter(wx.EndBusyCursor)
169
170
171 def OnBtnClose(self, event):
172 """
173 ...
174 """
175
176 self.Close(True)
177
178
179 def OnCloseWindow(self, event):
180 """
181 ...
182 """
183
184 self.Destroy()
185
186 #-------------------------------------------------------------------------------
187
188 class My_App(wx.App):
189 """
190 ...
191 """
192 def OnInit(self):
193
194 #------------
195
196 frame = My_Frame(None, id=-1)
197 self.SetTopWindow(frame)
198 frame.Show(True)
199
200 return True
201
202 #-------------------------------------------------------------------------------
203
204 def main():
205 app = My_App(False)
206 app.MainLoop()
207
208 #-------------------------------------------------------------------------------
209
210 if __name__ == "__main__" :
211 main()
ReportLab (PDF Toolkit)
An Open Source Python library for generating PDFs and graphics.
You must install this package for use it :
pip install reportlab
Link :
https://pypi.org/project/reportlab/
https://www.reportlab.com/opensource/
https://www.blog.pythonlibrary.org/2012/06/27/reportlab-mixing-fixed-content-and-flowables/
http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/
http://www.blog.pythonlibrary.org/2010/09/21/reportlab-tables-creating-tables-in-pdfs-with-python/
PDFViewer (David Hughes)
The wx.lib.pdfviewer.pdfViewer class can display and print PDF files.
You must install Python bindings for the PDF rendering library MuPDF before use it :
pip install PyMuPDF
1 # sample_ten.py
2
3 import os
4 import sys
5 import wx
6
7 try:
8 from wx.lib.pdfviewer import pdfViewer, pdfButtonPanel
9 havePyPdf = True
10 except ImportError:
11 havePyPdf = False
12
13 # class My_Panel
14 # class My_Frame
15 # class My_App
16
17 #-------------------------------------------------------------------------------
18
19 class My_Panel(wx.Panel):
20 """
21 Create a panel for my frame.
22 """
23 def __init__(self, parent):
24 wx.Panel.__init__(self, parent, -1)
25
26 hsizer = wx.BoxSizer(wx.HORIZONTAL)
27 vsizer = wx.BoxSizer(wx.VERTICAL)
28
29 self.buttonpanel = pdfButtonPanel(self,
30 wx.ID_ANY,
31 wx.DefaultPosition,
32 wx.DefaultSize,
33 0)
34
35 vsizer.Add(self.buttonpanel, 0,
36 wx.GROW|wx.ALIGN_CENTER_VERTICAL|
37 wx.LEFT|wx.RIGHT|wx.TOP, 5)
38
39 self.viewer = pdfViewer(self,
40 wx.ID_ANY,
41 wx.DefaultPosition,
42 wx.DefaultSize,
43 wx.HSCROLL|wx.VSCROLL|
44 wx.SUNKEN_BORDER)
45
46 vsizer.Add(self.viewer, 1,
47 wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM, 5)
48
49 loadbutton = wx.Button(self,
50 wx.ID_ANY,
51 "Load PDF file",
52 wx.DefaultPosition,
53 wx.DefaultSize,
54 0)
55
56 vsizer.Add(loadbutton, 0,
57 wx.ALIGN_CENTER|wx.ALL, 5)
58
59 hsizer.Add(vsizer, 1,
60 wx.GROW|wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5)
61
62 self.SetSizer(hsizer)
63 self.SetAutoLayout(True)
64
65 # Introduce buttonpanel and viewer to each other.
66 self.buttonpanel.viewer = self.viewer
67 self.viewer.buttonpanel = self.buttonpanel
68
69 self.Bind(wx.EVT_BUTTON, self.OnLoadButton, loadbutton)
70
71 #---------------------------------------------------------------------------
72
73 def OnLoadButton(self, event):
74 """
75 ...
76 """
77
78 dlg = wx.FileDialog(self, wildcard="*.pdf")
79
80 if dlg.ShowModal() == wx.ID_OK:
81 wx.BeginBusyCursor()
82 self.viewer.LoadFile(dlg.GetPath())
83 wx.EndBusyCursor()
84
85 dlg.Destroy()
86
87 #-------------------------------------------------------------------------------
88
89 class My_Frame(wx.Frame):
90 """
91 Create a main frame for my application.
92 """
93 def __init__(self):
94 style = (wx.DEFAULT_FRAME_STYLE)
95 wx.Frame.__init__(self, None, -1,
96 title="PDFViewer (PyMuPDF)",
97 size=(700, 500),
98 style=style)
99
100 #------------
101
102 pnl = My_Panel(self)
103
104 #------------
105
106 self.CenterOnScreen(wx.BOTH)
107
108 #------------
109
110 self.Show(True)
111
112 #-------------------------------------------------------------------------------
113
114 class My_App(wx.App):
115 """
116 ...
117 """
118 def OnInit(self):
119
120 #------------
121
122 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
123
124 #------------
125
126 frame = My_Frame()
127 self.SetTopWindow(frame)
128 frame.Show(True)
129
130 return True
131
132 #-------------------------------------------------------------------------------
133
134 def main():
135 app = My_App(False)
136 app.MainLoop()
137
138 #-------------------------------------------------------------------------------
139
140 if __name__ == "__main__" :
141 main()
Available with wxPython demo (Miscellaneous/PDFViewer).
Link :
https://pypi.org/project/PyMuPDF/
https://wxpython.org/Phoenix/docs/html/wx.lib.pdfviewer.html
https://github.com/pymupdf/PyMuPDF/wiki/GUI-scripts-to-display-a-PDF-using-wxPython-or-Tkinter
PDFWindow (only Win32)
Read PDF files (.pdf) with wxPython using wx.lib.pdfwin.PDFWindow class ActiveX control.
You must install this package for use it :
pip install comtypes
PDF file : document.pdf
1 # sample_eleven.py
2
3 """
4
5 Read PDF files (.pdf) with wxPython
6 using wx.lib.pdfwin.PDFWindow class ActiveX control
7 from wxPython's new wx.activex module, this allows one
8 to use an ActiveX control, as if it would be wx.Window.
9 it embeds the Adobe Acrobat Reader.
10 This works only with Windows.
11
12 """
13
14 import os
15 import sys
16 import wx
17
18 if wx.Platform == "__WXMSW__":
19 from wx.lib.pdfwin import PDFWindow
20 else:
21 dlg = wx.MessageDialog(self,
22 message="This demo only works on Microsoft Windows.",
23 caption="Sorry",
24 style=wx.OK|
25 wx.ICON_WARNING)
26 dlg.ShowModal()
27 dlg.Destroy()
28
29 appDir = os.path.split(os.path.abspath(sys.argv[0]))[0]
30 doc = os.path.join(appDir, "document.pdf")
31
32 # class My_Frame
33 # class My_App
34
35 #-------------------------------------------------------------------------------
36
37 class My_Frame(wx.Frame):
38 def __init__(self, parent, id, title):
39 wx.Frame.__init__(self, parent, -1,
40 title, size=(720, 600),
41 style=wx.DEFAULT_FRAME_STYLE |
42 wx.NO_FULL_REPAINT_ON_RESIZE)
43
44 #------------
45
46 # Simplified init method.
47 self.CreateCtrls()
48 self.LoadPdf()
49 self.BindEvents()
50 self.DoLayout()
51
52 #---------------------------------------------------------------
53
54 self.CenterOnScreen()
55
56 #-------------------------------------------------------------------
57
58 def CreateCtrls(self):
59 """
60 ...
61 """
62
63 fontSize = self.GetFont().GetPointSize()
64 boldFont = wx.Font(fontSize, wx.SWISS, wx.NORMAL, wx.BOLD)
65
66 #------------
67
68 self.panel = wx.Panel(self, -1)
69
70 #------------
71
72 # Add PDFWindow
73 self.pdf = PDFWindow(self.panel, style=wx.SUNKEN_BORDER)
74 self.pdf.setView("FitV")
75 self.pdf.setPageMode("Bookmarks")
76 self.pdf.setLayoutMode("SinglePage")
77 self.pdf.setShowScrollbars(True)
78
79 #------------
80
81 # Add controls
82 self.btn1 = wx.Button(self.panel, -1, "&Open")
83 self.btn1.SetToolTip("Open PDF file.")
84
85 self.btn2 = wx.Button(self.panel, -1, "<<", size=(30, -1))
86 self.btn2.SetToolTip("First page.")
87 self.btn2.SetFont(boldFont)
88
89 self.btn3 = wx.Button(self.panel, -1, "<", size=(30, -1))
90 self.btn3.SetToolTip("Previous page.")
91 self.btn3.SetFont(boldFont)
92
93 self.btn4 = wx.Button(self.panel, -1, ">", size=(30, -1))
94 self.btn4.SetToolTip("Next page.")
95 self.btn4.SetFont(boldFont)
96
97 self.btn5 = wx.Button(self.panel, -1, ">>", size=(30, -1))
98 self.btn5.SetToolTip("Last page.")
99 self.btn5.SetFont(boldFont)
100
101 self.txt1 = wx.StaticText(self.panel, -1, " Go to page" )
102 self.txtCtrl = wx.TextCtrl(self.panel, -1, "0", size=[30, -1])
103
104 self.txt2 = wx.StaticText(self.panel, -1, " Zoom")
105 self.zoom = wx.Choice(self.panel, -1,
106 choices=["Default",
107 "Fit",
108 "FitH",
109 "FitV",
110 "25%",
111 "50%",
112 "75%",
113 "100%",
114 "125%",
115 "200%",
116 "400%"])
117 self.zoom.SetSelection(0)
118 self.zoom.SetToolTip("Zoom.")
119
120 self.btn6 = wx.Button(self.panel, -1, "&Pr&int")
121 self.btn6.SetToolTip("Print PDF file.")
122
123 self.btn7 = wx.Button(self.panel, -1, "&Quit")
124 self.btn7.SetToolTip("Quit application.")
125
126
127 def BindEvents(self):
128 """
129 Bind all the events related to my frame.
130 """
131
132 self.Bind(wx.EVT_BUTTON, self.OnOpenBtn, self.btn1)
133 self.Bind(wx.EVT_BUTTON, self.OnFirstPageBtn, self.btn2)
134 self.Bind(wx.EVT_BUTTON, self.OnPrevPageBtn, self.btn3)
135 self.Bind(wx.EVT_BUTTON, self.OnNextPageBtn, self.btn4)
136 self.Bind(wx.EVT_BUTTON, self.OnLastPageBtn, self.btn5)
137 self.Bind(wx.EVT_BUTTON, self.OnPrintBtn, self.btn6)
138 self.Bind(wx.EVT_BUTTON, self.OnCloseBtn, self.btn7)
139
140 self.Bind(wx.EVT_TEXT, self.OnGotoPage, self.txtCtrl)
141 self.Bind(wx.EVT_CHOICE, self.OnZoom, self.zoom)
142
143 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
144 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
145
146
147 def DoLayout(self):
148 """
149 Manage widgets Layout.
150 """
151
152 # MainSizer is the top-level one that manages everything.
153 sizer = wx.BoxSizer(wx.VERTICAL)
154 sizer.Add(self.pdf, proportion=1, flag=wx.EXPAND)
155
156 #------------
157
158 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
159 btnSizer.Add(self.btn1, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
160 btnSizer.Add(self.btn2, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=2)
161 btnSizer.Add(self.btn3, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=2)
162 btnSizer.Add(self.btn4, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=2)
163 btnSizer.Add(self.btn5, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=2)
164 btnSizer.Add(self.txt1, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
165 btnSizer.Add(self.txtCtrl, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
166 btnSizer.Add(self.txt2, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
167 btnSizer.Add(self.zoom, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
168 btnSizer.Add(self.btn6, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
169 btnSizer.Add(self.btn7, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
170 btnSizer.Add((50,-1), proportion=2, flag=wx.EXPAND)
171
172 #------------
173
174 sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND)
175
176 #------------
177
178 # Finally, tell the panel to use the mainSizer for layout.
179 self.panel.SetSizer(sizer)
180 self.panel.SetAutoLayout(True)
181
182
183 def LoadPdf(self):
184 """
185 ...
186 """
187
188 self.pdf.LoadFile(doc)
189
190
191 def OnOpenBtn(self, event):
192 """
193 ...
194 """
195
196 dlg = wx.FileDialog(self, wildcard="*.pdf")
197
198 if dlg.ShowModal() == wx.ID_OK:
199 wx.BeginBusyCursor()
200 self.pdf.LoadFile(dlg.GetPath())
201 wx.EndBusyCursor()
202
203 dlg.Destroy()
204
205
206 def OnFirstPageBtn(self, event):
207 """
208 ...
209 """
210
211 self.pdf.gotoFirstPage()
212
213
214 def OnPrevPageBtn(self, event):
215 """
216 ...
217 """
218
219 self.pdf.gotoPreviousPage()
220
221
222 def OnNextPageBtn(self, event):
223 """
224 ...
225 """
226
227 self.pdf.gotoNextPage()
228
229
230 def OnLastPageBtn(self, event):
231 """
232 ...
233 """
234
235 self.pdf.gotoLastPage()
236
237
238 def OnGotoPage(self, event):
239 """
240 ...
241 """
242
243 npage = event.GetEventObject().GetValue()
244
245 try:
246 self.pdf.setCurrentPage(int(npage))
247 except ValueError:
248 pass
249
250
251 def OnZoom(self, event):
252 """
253 ...
254 """
255
256 astring = event.GetEventObject().GetStringSelection()
257
258 if astring.startswith('Fit'):
259 self.pdf.setView(astring)
260 else:
261 try:
262 percent = float(astring.replace('%',''))
263 self.pdf.setZoom(percent)
264 except ValueError:
265 pass
266
267
268 def OnPrintBtn(self, event):
269 """
270 ...
271 """
272
273 self.pdf.Print()
274
275
276 def OnCloseBtn(self, event):
277 """
278 ...
279 """
280
281 self.Close(True)
282
283
284 def OnEraseBackground(self, event):
285 """
286 ...
287 """
288
289 dc = event.GetDC()
290
291 if not dc:
292 dc = wx.ClientDC(self)
293 rect = self.GetUpdateRegion().GetBox()
294 dc.SetClippingRect(rect)
295
296
297 def OnCloseWindow(self, event):
298 """
299 ...
300 """
301
302 self.Destroy()
303
304 #-------------------------------------------------------------------------------
305
306 class My_App(wx.App):
307 """
308 ...
309 """
310 def OnInit(self):
311
312 #------------
313
314 self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
315
316 #------------
317
318 frame = My_Frame(None, -1, "PDFWindow (ActiveX)")
319 self.SetTopWindow(frame)
320 frame.Show(True)
321
322 return True
323
324 #-------------------------------------------------------------------------------
325
326 def main():
327 app = My_App(False)
328 app.MainLoop()
329
330 #-------------------------------------------------------------------------------
331
332 if __name__ == "__main__" :
333 main()
Available with wxPython demo (More Windows/Controls/ActiveX_PDFWindow).
PyMuPDF(Ruikai Liu / Jorj X. McKie)
MuPDF can access files in PDF, XPS, OpenXPS, epub, comic and fiction book formats, and it is known for both, its top performance and high rendering quality.
With PyMuPDF you therefore can access files with extensions *.pdf, *.xps, *.oxps, *.epub, *.cbz or *.fb2 from your Python scripts. A number of popular image formats is supported as well, including multi-page TIFF images.
PyMuPDF should run on all platforms that are supported by both, MuPDF and Python. These include, but are not limited to, Windows (XP/SP2 and up), Mac OSX and Linux, 32-bit or 64-bit. If you can generate MuPDF on a Python supported platform, then also PyMuPDF can be used there.
You must install Python bindings for the PDF rendering library MuPDF before use it :
pip install PyMuPDF
1 # sample_twelve.py
2
3 """
4 @created: 2015-10-23 13:40:00
5
6 @author: Jorj X. McKie
7
8 Let the user select a PyMuPDF-supported file and then scroll through it.
9
10 Dependencies:
11 PyMuPDF, wxPython 3.x
12
13 License:
14 GNU GPL 3.x, GNU AFFERO GPL 3
15
16 Changes in PyMuPDF 1.9.2
17 ------------------------
18 - supporting Python 3 as wxPython now supports it
19 - optionally show links in displayed pages
20 - when clicking on a link, attempt to follow it
21 - remove inline code for dialog icon and import from a library
22
23 Changes in PyMuPDF 1.8.0
24 ------------------------
25 - display a fancy icon on the dialogs, defined as inline code in base64 format
26 - display pages with a zoom factor of 120%
27 - dynamically resize dialog to reflect each page's image size / orientation
28 - minor cosmetic changes
29 """
30 from __future__ import print_function
31 import sys
32 print("Python:", sys.version)
33
34 try:
35 import wx
36 print("wxPython:", wx.version())
37 except:
38 raise SystemExit(__file__ + " needs wxPython.")
39
40 try:
41 import fitz
42 print(fitz.__doc__)
43 except:
44 raise SystemExit(__file__ + " needs PyMuPDF(fitz).")
45
46 try:
47 from PageFormat import FindFit
48 except ImportError:
49 def FindFit(*args):
50 return "not implemented"
51
52 try:
53 from icons import ico_pdf # PDF icon in upper left screen corner
54 do_icon = True
55 except ImportError:
56 do_icon = False
57
58 app = None
59 app = wx.App()
60 assert wx.VERSION[0:3] >= (3,0,2), "need wxPython 3.0.2 or later"
61 assert tuple(map(int, fitz.VersionBind.split("."))) >= (1,9,2), "need PyMuPDF 1.9.2 or later"
62
63 # make some adjustments for differences between wxPython versions 3.0.2 / 3.0.3
64 if wx.VERSION[0:3] >= (3,0,3):
65 cursor_hand = wx.Cursor(wx.CURSOR_HAND)
66 cursor_norm = wx.Cursor(wx.CURSOR_DEFAULT)
67 bmp_buffer = wx.Bitmap.FromBuffer
68 phoenix = True
69 else:
70 cursor_hand = wx.StockCursor(wx.CURSOR_HAND)
71 cursor_norm = wx.StockCursor(wx.CURSOR_DEFAULT)
72 bmp_buffer = wx.BitmapFromBuffer
73 phoenix = False
74
75 if str != bytes:
76 stringtypes = (str, bytes)
77 else:
78 stringtypes = (str, unicode)
79
80 def getint(v):
81 try:
82 return int(v)
83 except:
84 pass
85 if type(v) not in stringtypes:
86 return 0
87 a = "0"
88 for d in v:
89 if d in "0123456789":
90 a += d
91 return int(a)
92
93 # abbreviations to get rid of those long pesky names ...
94 #==============================================================================
95 # Define our dialog as a subclass of wx.Dialog.
96 # Only special thing is, that we are being invoked with a filename ...
97 #==============================================================================
98 class PDFdisplay(wx.Dialog):
99 def __init__(self, parent, filename):
100 defPos = wx.DefaultPosition
101 defSiz = wx.DefaultSize
102 zoom = 1.2 # zoom factor of display
103 wx.Dialog.__init__ (self, parent, id = wx.ID_ANY,
104 title = u"Display with PyMuPDF: ",
105 pos = defPos, size = defSiz,
106 style = wx.CAPTION|wx.CLOSE_BOX|
107 wx.DEFAULT_DIALOG_STYLE)
108
109 #======================================================================
110 # display an icon top left of dialog, append filename to title
111 #======================================================================
112 if do_icon:
113 self.SetIcon(ico_pdf.img.GetIcon()) # set a screen icon
114 self.SetTitle(self.Title + filename)
115 self.SetBackgroundColour(wx.Colour(240, 230, 140))
116
117 #======================================================================
118 # open the document with MuPDF when dialog gets created
119 #======================================================================
120 self.doc = fitz.open(filename) # create Document object
121 if self.doc.needsPass: # check password protection
122 self.decrypt_doc()
123 if self.doc.isEncrypted: # quit if we cannot decrpt
124 self.Destroy()
125 return
126 self.dl_array = [0] * len(self.doc)
127 self.last_page = -1 # memorize last page displayed
128 self.link_rects = [] # store link rectangles here
129 self.link_texts = [] # store link texts here
130 self.current_idx = -1 # store entry of found rectangle
131 self.current_lnks = [] # store entry of found rectangle
132
133 #======================================================================
134 # define zooming matrix for displaying PDF page images
135 # we increase images by 20%, so take 1.2 as scale factors
136 #======================================================================
137 self.matrix = fitz.Matrix(zoom, zoom) # will use a constant zoom
138
139 '''
140 =======================================================================
141 Overall Dialog Structure:
142 -------------------------
143 szr10 (main sizer for the whole dialog - vertical orientation)
144 +-> szr20 (sizer for buttons etc. - horizontal orientation)
145 +-> button forward
146 +-> button backward
147 +-> field for page number to jump to
148 +-> field displaying total pages
149 +-> PDF image area
150 =======================================================================
151 '''
152
153 # forward button
154 self.ButtonNext = wx.Button(self, wx.ID_ANY, u"forw",
155 defPos, defSiz, wx.BU_EXACTFIT)
156 # backward button
157 self.ButtonPrevious = wx.Button(self, wx.ID_ANY, u"back",
158 defPos, defSiz, wx.BU_EXACTFIT)
159 #======================================================================
160 # text field for entering a target page. wx.TE_PROCESS_ENTER is
161 # required to get data entry fired as events.
162 #======================================================================
163 self.TextToPage = wx.TextCtrl(self, wx.ID_ANY, u"1", defPos, wx.Size(40, -1),
164 wx.TE_RIGHT|wx.TE_PROCESS_ENTER)
165 # displays total pages and page paper format
166 self.statPageMax = wx.StaticText(self, wx.ID_ANY,
167 "of " + str(len(self.doc)) + " pages.",
168 defPos, defSiz, 0)
169 self.links = wx.CheckBox( self, wx.ID_ANY, u"show links",
170 defPos, defSiz, wx.ALIGN_LEFT)
171 self.links.Value = True
172 self.paperform = wx.StaticText(self, wx.ID_ANY, "", defPos, defSiz, 0)
173 # define the area for page images and load page 1 for primary display
174 self.PDFimage = wx.StaticBitmap(self, wx.ID_ANY, self.pdf_show(1),
175 defPos, defSiz, style = 0)
176 #======================================================================
177 # the main sizer of the dialog
178 #======================================================================
179 self.szr10 = wx.BoxSizer(wx.VERTICAL)
180 szr20 = wx.BoxSizer(wx.HORIZONTAL)
181 szr20.Add(self.ButtonNext, 0, wx.ALL, 5)
182 szr20.Add(self.ButtonPrevious, 0, wx.ALL, 5)
183 szr20.Add(self.TextToPage, 0, wx.ALL, 5)
184 szr20.Add(self.statPageMax, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
185 szr20.Add( self.links, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
186 szr20.Add(self.paperform, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
187 # sizer ready, represents top dialog line
188 self.szr10.Add(szr20, 0, wx.EXPAND, 5)
189 self.szr10.Add(self.PDFimage, 0, wx.ALL, 5)
190 # main sizer now ready - request final size & layout adjustments
191 self.szr10.Fit(self)
192 self.SetSizer(self.szr10)
193 self.Layout()
194 # center dialog on screen
195 self.Centre(wx.BOTH)
196
197 # Bind buttons and fields to event handlers
198 self.ButtonNext.Bind(wx.EVT_BUTTON, self.NextPage)
199 self.ButtonPrevious.Bind(wx.EVT_BUTTON, self.PreviousPage)
200 self.TextToPage.Bind(wx.EVT_TEXT_ENTER, self.GotoPage)
201 self.PDFimage.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
202 self.PDFimage.Bind(wx.EVT_MOTION, self.move_mouse)
203 self.PDFimage.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
204
205 #==============================================================================
206 # Button handlers and other functions
207 #==============================================================================
208 def OnLeftDown(self, evt):
209 if self.current_idx < 0 or not self.links.Value:
210 evt.Skip()
211 return
212 lnk = self.current_lnks[self.current_idx]
213 if lnk["kind"] == fitz.LINK_GOTO:
214 self.TextToPage.Value = str(lnk["page"] + 1)
215 self.GotoPage(evt)
216 elif lnk["kind"] == fitz.LINK_URI:
217 import webbrowser
218 try:
219 webbrowser.open_new(self.link_texts[self.current_idx])
220 except:
221 pass
222 elif lnk["kind"] == fitz.LINK_GOTOR:
223 import subprocess
224 try:
225 subprocess.Popen(self.link_texts[self.current_idx])
226 except:
227 pass
228 elif lnk["kind"] == fitz.LINK_NAMED:
229 if lnk["name"] == "FirstPage":
230 self.TextToPage.Value = "1"
231 elif lnk["name"] == "LastPage":
232 self.TextToPage.Value = str(len(self.doc))
233 elif lnk["name"] == "NextPage":
234 self.TextToPage.Value = str(int(self.TextToPage.Value) + 1)
235 elif lnk["name"] == "PrevPage":
236 self.TextToPage.Value = str(int(self.TextToPage.Value) - 1)
237 self.GotoPage(evt)
238 evt.Skip()
239 return
240
241 def move_mouse(self, evt): # show hand if in a rectangle
242 if not self.links.Value: # do not process links
243 evt.Skip()
244 return
245 if len(self.link_rects) == 0:
246 evt.Skip()
247 return
248 pos = evt.GetPosition()
249 self.current_idx = self.cursor_in_link(pos) # get cursor link rect
250
251 if self.current_idx >= 0: # if in a hot area
252 self.PDFimage.SetCursor(cursor_hand)
253 if phoenix:
254 self.PDFimage.SetToolTip(self.link_texts[self.current_idx])
255 else:
256 self.PDFimage.SetToolTipString(self.link_texts[self.current_idx])
257 else:
258 self.PDFimage.SetCursor(cursor_norm)
259 self.PDFimage.UnsetToolTip()
260
261 evt.Skip()
262 return
263
264 def OnMouseWheel(self, evt):
265 # process wheel as paging operations
266 d = evt.GetWheelRotation() # int indicating direction
267 if d < 0:
268 self.NextPage(evt)
269 elif d > 0:
270 self.PreviousPage(evt)
271 return
272
273 def NextPage(self, event): # means: page forward
274 page = getint(self.TextToPage.Value) + 1 # current page + 1
275 page = min(page, self.doc.pageCount) # cannot go beyond last page
276 self.TextToPage.Value = str(page) # put target page# in screen
277 self.NeuesImage(page) # refresh the layout
278 event.Skip()
279
280 def PreviousPage(self, event): # means: page back
281 page = getint(self.TextToPage.Value) - 1 # current page - 1
282 page = max(page, 1) # cannot go before page 1
283 self.TextToPage.Value = str(page) # put target page# in screen
284 self.NeuesImage(page)
285 event.Skip()
286
287 def GotoPage(self, event): # means: go to page number
288 page = getint(self.TextToPage.Value) # get page# from screen
289 page = min(page, len(self.doc)) # cannot go beyond last page
290 page = max(page, 1) # cannot go before page 1
291 self.TextToPage.Value = str(page) # make sure it's on the screen
292 self.NeuesImage(page)
293 event.Skip()
294
295 #==============================================================================
296 # Read / render a PDF page. Parameters are: pdf = document, page = page#
297 #==============================================================================
298 def NeuesImage(self, page):
299 if page == self.last_page:
300 return
301 self.PDFimage.SetCursor(cursor_norm)
302 self.PDFimage.UnsetToolTip()
303 self.last_page = page
304 self.link_rects = []
305 self.link_texts = []
306 bitmap = self.pdf_show(page) # read page image
307 if self.links.Value and len(self.current_lnks) > 0: # show links?
308 self.draw_links(bitmap, page) # modify the bitmap
309 self.PDFimage.SetBitmap(bitmap) # put it in screen
310 self.szr10.Fit(self)
311 self.Layout()
312 # image may be truncated, so we need to recalculate hot areas
313 if len(self.current_lnks) > 0:
314 isize = self.PDFimage.Size
315 bsize = self.PDFimage.Bitmap.Size
316 dis_x = (bsize[0] - isize[0]) / 2.
317 dis_y = (bsize[1] - isize[1]) / 2.
318 zoom_w = float(bsize[0]) / float(self.pg_ir.width)
319 zoom_h = float(bsize[1]) / float(self.pg_ir.height)
320 for l in self.current_lnks:
321 r = l["from"]
322 wx_r = wx.Rect(int(r.x0 * zoom_w - dis_x),
323 int(r.y0 * zoom_h) - dis_y,
324 int(r.width * zoom_w),
325 int(r.height * zoom_h))
326 self.link_rects.append(wx_r)
327
328 return
329
330 def cursor_in_link(self, pos):
331 for i, r in enumerate(self.link_rects):
332 if r.Contains(pos):
333 return i
334 return -1
335
336 def draw_links(self, bmp, pno):
337 dc = wx.MemoryDC()
338 dc.SelectObject(bmp)
339 dc.SetPen(wx.Pen("BLUE", width=1))
340 dc.SetBrush(wx.Brush("BLUE", style=wx.BRUSHSTYLE_TRANSPARENT))
341 pg_w = self.pg_ir.x1 - self.pg_ir.x0
342 pg_h = self.pg_ir.y1 - self.pg_ir.y0
343 zoom_w = float(bmp.Size[0]) / float(pg_w)
344 zoom_h = float(bmp.Size[1]) / float(pg_h)
345 for lnk in self.current_lnks:
346 r = lnk["from"].irect
347 wx_r = wx.Rect(int(r.x0 * zoom_w),
348 int(r.y0 * zoom_h),
349 int(r.width * zoom_w),
350 int(r.height * zoom_h))
351 dc.DrawRectangle(wx_r[0], wx_r[1], wx_r[2]+1, wx_r[3]+1)
352 if lnk["kind"] == fitz.LINK_GOTO:
353 txt = "page " + str(lnk["page"] + 1)
354 elif lnk["kind"] == fitz.LINK_GOTOR:
355 txt = lnk["file"]
356 elif lnk["kind"] == fitz.LINK_URI:
357 txt = lnk["uri"]
358 else:
359 txt = "unkown destination"
360 self.link_texts.append(txt)
361 dc.SelectObject(wx.NullBitmap)
362 dc = None
363 return
364
365 def pdf_show(self, pg_nr):
366 pno = int(pg_nr) - 1
367 if self.dl_array[pno] == 0:
368 self.dl_array[pno] = self.doc[pno].getDisplayList()
369 dl = self.dl_array[pno]
370 pix = dl.getPixmap(matrix = self.matrix, alpha = False)
371 bmp = bmp_buffer(pix.w, pix.h, pix.samples)
372 r = dl.rect
373 paper = FindFit(r.x1, r.y1)
374 self.paperform.Label = "Page format: " + paper
375 if self.links.Value:
376 self.current_lnks = self.doc[pno].getLinks()
377 self.pg_ir = dl.rect.irect
378 pix = None
379 return bmp
380
381 def decrypt_doc(self):
382 # let user enter document password
383 pw = None
384 dlg = wx.TextEntryDialog(self, 'Please enter password below:',
385 'Document needs password to open', '',
386 style = wx.TextEntryDialogStyle|wx.TE_PASSWORD)
387 while pw is None:
388 rc = dlg.ShowModal()
389 if rc == wx.ID_OK:
390 pw = str(dlg.GetValue().encode("utf-8"))
391 self.doc.authenticate(pw)
392 else:
393 return
394 if self.doc.isEncrypted:
395 pw = None
396 dlg.SetTitle("Wrong password. Enter correct one or cancel.")
397 return
398
399 #==============================================================================
400 # main program
401 #------------------------------------------------------------------------------
402 # Show a standard FileSelect dialog to choose a file for display
403 #==============================================================================
404 # Wildcard: offer all supported filetypes for display
405 wild = "*.pdf;*.xps;*.oxps;*.epub;*.cbz;*.fb2"
406
407 #==============================================================================
408 # define the file selection dialog
409 #==============================================================================
410 dlg = wx.FileDialog(None, message = "Choose a file to display",
411 wildcard = wild, style=wx.FD_OPEN|wx.FD_CHANGE_DIR)
412
413 # We got a file only when one was selected and OK pressed
414 if dlg.ShowModal() == wx.ID_OK:
415 # This returns a Python list of selected files (we only have one though)
416 filename = dlg.GetPath()
417 else:
418 filename = None
419
420 # destroy this dialog
421 dlg.Destroy()
422
423 # only continue if we have a filename
424 if filename:
425 # create the dialog
426 dlg = PDFdisplay(None, filename)
427 # show it - this will only return for final housekeeping
428 rc = dlg.ShowModal()
429
430 app = None
Download source
Additional Information
Link :
https://wiki.wxpython.org/MoreCommentsOnPrinting
https://wiki.wxpython.org/PrintingWithReportGenerators
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
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 and the wxPython community...
Thanks also to all known contributors or anonymous that I forgot.
And finally, congratulations to the many forums and blog for all the available examples and the help that 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....