In QT, printing is similar to plotting in qwidget, qpixmap, or qimage. The general steps are as follows: 1. Creating the qprinter of the drawing device; 2. Pop Up the Print dialog box and qprintdialog, which allows users to select a printer, set attributes. 3. Create a qpainter. 4. Use qpainter to draw a page. 5. Call qprinter: Newpage () and draw the next page. 6. Repeat steps 4 and 5, until all pages are printed. On Windows and Mac OS X platforms, qprinter uses the system's print driver. On UNIX, qprinter generates a script and sends it to LP or LPR (or to a program. The print program has the qprinter function: setprintprogram ()). You can call qprinter: setoutputformat (qprinter: pdfformat) to generate a PDF file.
Figure 8.12. Printing
Qimage
First, let's look at a simple example to print a qimage to a page. Void printwindow: printimage (const qimage & image) {qprintdialog printdialog (& printer, this); If (printdialog.exe C () {qpainter painter (& printer); qrect rect = painter. viewport (); qsize size = image. size (); size. scale (rect. size (), QT: keepaspectratio); painter. setviewport (rect. X (), rect. Y (), size. width (), size. height (); painter. setwindow (image. rect (); painter. drawimage (0, 0, image) ;}} here, we assume that The intwindow class has a member variable printer of the qprinter type. Of course, we can also create a qprinter on the heap of the printimage () function, but it cannot record the settings when the user prints the qprintdialog, and call exec () to display it, if you click OK, return true; otherwise, return false. After exec () is called, The qprinter object can be used. (You can also directly call the member function of qprinter for copying without displaying the qprintdialog). Then, we create qpainter and the drawing device is qprinter. Set the window to the rectangle of the displayed image, and draw the image at (0, 0. Generally, the qpainter window is automatically initialized, And the printer and screen have the same resolution (1 inch has 72 to 100 points), so that the print code of the control can be reused. In the above function, we set the qpainter window. Printing on one page is simple, but many applications need to print multiple pages. At this time, we print one page at a time, and then call Newpage () to print another page. Here we need to solve the problem of determining how much content is printed on a page. There are two ways to process multi-page printed documents in QT: 1. We can convert data to HTML format and describe them using qtextdocument. qtextdocument is the multi-text engine of QT. 2. Manually paging. Let's take a look at the two methods respectively. In the first example, we want to print a flower guide: one column is the name of the flower, and the other column is the text description. The text format of each entry is stored as "Name: Description ". For example, miltonopsis santanae: a most dangerous orchid species. Since data of each flower can be represented by a string, we can use qstringlist to represent data of all flowers. The following code is an example of printing using the QT multi-text engine: void printwindow: printflowerguide (const qstringlist & entries) {qstring HTML; foreach (qstring entry, entries) {qstringlist fields = entry. split (":"); qstring Title = QT: escape (fields [0]); qstring body = QT: escape (fields [1]); HTML + = "<Table width =/" 100%/"border = 1 cellspacing = 0>/N" "<tr> <TD bgcolor =/" lightgray/"> <font size =/"+ 1/"> "" <B> <I> "+ title +" </I> </B> </font>/n <Tr> <TD> "+ body +"/n </table>/n <br>/N ";} printhtml (HTML);} first converts qstringlist to HTML. Each flower is a line in an HTML table. Call QT: escapte () to convert the special characters '&', '> ', '<' and so on are expressed with the corresponding HTML characters ('amp', '& gt', '& lt'), and then printhtml () is called to print the text: void printwindow :: printhtml (const qstring & html) {qprintdialog printdialog (& printer, this); If (printdialog.exe C () {qpainter painter (& printer); qtextdocument textdocument; textdocument. sethtml (HTML); textdocument. print (& printer) ;}} function printhtml () The qprintdialog dialog box is displayed to print an HTML document. These codes can print arbitrary HTML documents in all QT applications.
Figure 8.13. Printing a flower Guide using qtextdocument
Currently, it is the most convenient method to convert text to HTML document and print it with qtextdocument. If you need more settings, You need to layout and draw the page by yourself. The following method is to print the flower Guide using manual intervention. First, let's take a look at the printflowerguide () function: void printwindow: printflowerguide (const qstringlist & entries) {qprintdialog printdialog (& printer, this); If (printdialog.exe C ()) {qpainter painter (& printer); qlist <qstringlist> pages; paginate (& painter, & pages, entries); printpages (& painter, pages) ;}} create qpainter, after setting the printer, call the paginate () function to determine which items are on that page. The result of executing this function is to get a list of qstringlists. Each qstringlist is displayed on a page and the result is passed to printpages () for printing. For example, the flower Guide to be printed has 6 entries: A, B, C, D, E, F. Where A and B are printed on the first page, c, d, e on the second page, and F on the third page. Void printwindow: paginate (qpainter * painter, qlist <qstringlist> * pages, const qstringlist & entries) {qstringlist currentpage; int pageheight = painter-> window (). height ()-2 * largegap; int y = 0; foreach (qstring entry, entries) {int Height = entryheight (painter, entry ); if (Y + height> pageheight &&! Currentpage. empty () {pages-> append (currentpage); currentpage. clear (); y = 0;} currentpage. append (entry); y + = height + mediumgap;} If (! Currentpage. Empty () pages-> append (currentpage);} The paginate () function paginate the entries in the Hua Hui guide. Calculate the height of each entry based on entryheight. At the same time, consider the vertical distance between the top and bottom of the page largegap. Traverse all entries. If this entry can be placed on the current page, it will be placed in the list of the current page. When the current page is full, place the current page in the page list to start a new page. Int printwindow: entryheight (qpainter * painter, const qstring & entry) {qstringlist fields = entry. split (":"); qstring Title = Fields [0]; qstring body = Fields [1]; int textwidth = painter-> window (). width ()-2 * smallgap; int maxheight = painter-> window (). height (); painter-> setfont (titlefont); qrect titlerect = painter-> boundingrect (0, 0, textwidth, maxheight, QT: textwordwrap, title ); painter-> setfont (bodyfont); qrect bodyrect = painter-> boundingrect (0, 0, textwidth, maxheight, QT: textwordwrap, body); Return titlerect. height () + bodyrect. height () + 4 * smallgap;} function entryheight () calculates the vertical distance of each entry based on qpainter: boundingrect, figure 8.4 shows the layout of the entry and the meaning of the smallgap mediumgap: The entryheight () function uses qpainter: boundingrect () to compute the vertical space needed by one entry. figure 8.14 shows the layout of a flower entry and the meaning of the smallgap and mediumgap constants.
Figure 8.14. A flower entry's layout
Void printwindow: printpages (qpainter * painter,
Const qlist <qstringlist> & pages) {int firstpage = printer. frompage ()-1; if (firstpage> = pages. size () return; If (firstpage =-1) firstpage = 0; int lastpage = printer. topage ()-1; if (lastpage =-1 | lastpage> = pages. size () lastpage = pages. size ()-1; int numpages = lastpage-firstpage + 1; for (INT I = 0; I <printer. numcopies (); ++ I) {for (Int J = 0; j <numpages; ++ J) {if (I! = 0 | j! = 0) printer. newpage (); int index; If (printer. pageorder () = qprinter: firstpagefirst) {Index = firstpage + J;} else {Index = lastpage-J;} printpage (painter, pages [Index], index + 1) ;}} the function printpages () is used to call printpage () to print each page in order and number of copies. With qprintdialog, you may need to print multiple copies, set the print range, or print them in reverse order. We need to consider these requirements in the program to determine the print scope first. Qprinter: frompage () and topage () return the range of pages selected by the user. If no value is selected, 0 is returned. We performed the minus 1 operation because our page index starts from 0. If the user does not select a range, print all pages with firstpage and lastpage content. Then we print each page. The outermost loop is the number of printed copies set by the user. For printers that support multiple copies, qprinter: numcopies () always returns 1. If the printer driver does not support multiple copies, numcopies () returns the number of copies specified by the user, and multiple copies can be printed by an application. (In the qimage example in this section, we did not consider printing multiple copies for the sake of simplicity .)
Figure 8.15. Printing a flower Guide using
Qpainter
The number of printed pages cyclically in the inner layer. If the page number is not the first page, call Newpage () to clear the original page and start filling the new page. Call printpage () to print each page. Void printwindow: printpage (qpainter * painter, const qstringlist & entries, int pagenumber) {painter-> Save (); painter-> translate (0, largegap ); foreach (qstring entry, entries) {qstringlist fields = entry. split (":"); qstring Title = Fields [0]; qstring body = Fields [1]; printbox (painter, title, titlefont, QT: lightgray ); printbox (painter, body, bodyfont, QT: White); painter-> translate (0, mediumgap );} Painter-> restore (); painter-> setfont (footerfont); painter-> drawtext (painter-> window (), QT: alignhcenter | QT: alignbottom, qstring:: Number (pagenumber);} The printpage () function prints every entry on the page. Print the title with printbox (), and then print the description with printbox. Print the page number at the bottom of each page.
Figure 8.16. The flower guide's page layout
Void printwindow: printbox (qpainter * painter, const qstring & STR, const qfont & font, const qbrush & brush) {painter-> setfont (font ); int boxwidth = painter-> window (). width (); int textwidth = boxwidth-2 * smallgap; int maxheight = painter-> window (). height (); qrect textrect = painter-> boundingrect (smallgap, smallgap, textwidth, maxheight, QT: textwordwrap, STR); int boxheight = textrect. height () + 2 * Smallgap; painter-> setpen (qpen (QT: Black, 2, QT: solidline); painter-> setbrush (Brush); painter-> drawrect (0, 0, boxwidth, boxheight); painter-> drawtext (textrect, QT: textwordwrap, STR); painter-> translate (0, boxheight);} printbox () first, draw a rectangle box, and then draw text in the rectangle box.