Qt中對打印的支持是有一個獨立的printsupport模塊來完成的,所以,要想在程序中使用Qt的打印功能,必須先在pro文件中添加下面這句代碼:
QT += printsupport
在這個模塊中,提供了八個類來支持打印功能。我們來簡單的看幾個與打印有直接關係的幾個類:
- QPageSetupDialog:該類可以用來對打印頁面進行一些相關的配置,如頁面方向,邊距等。
- QPrintDialog:該類就代表我們常見的打印對話框。
- QPrintPreviewDialog:該類代表打印預覽對話框。可以在此對話框中看到我們對頁面的設置效果。
- QPrinter:可以簡單的理解爲用於打印的繪圖設備。
- QPrinterInfo:可以使用該類來獲得當前電腦上所連接的可用的打印設備的信息。
下面,我們通過實例來實際瞭解一下這幾個類的使用。
新建一個GUI程序,往界面上拖入一個列表框和4個按鈕。效果如下:
下面,我們要完成的功能是,點擊“PrinterInfo”按鈕,將當前電腦可用的所有打印設備的信息加載到文本框中,然後,再將這些信息打印出來。
先來看“PrinterInfo”按鈕的功能代碼:
//Printer Info
void Widget::on_printerinfo_clicked()
{
QString info;
list = QPrinterInfo::availablePrinters();
for(const QPrinterInfo& printerInfo : list)
{
info = "defaultDuplexMode: ";
switch (printerInfo.defaultDuplexMode())
{
case QPrinter::DuplexNone:
info += "DuplexNone";
break;
case QPrinter::DuplexAuto:
info += "DuplexAuto";
break;
case QPrinter::DuplexLongSide:
info += "DuplexLongSide";
break;
case QPrinter::DuplexShortSide:
info += "DuplexShortSide";
break;
}
ui->listWidget->addItem(info);
info = "defaultPageSize: ";
info += printerInfo.defaultPageSize().name();
ui->listWidget->addItem(info);
info = "description: ";
info += printerInfo.description();
ui->listWidget->addItem(info);
info = "isDefault: ";
info += printerInfo.isDefault() ? "true" : "false";
ui->listWidget->addItem(info);
info = "isRemote: ";
info += printerInfo.isRemote() ? "true" : "false";
ui->listWidget->addItem(info);
info = "location: " + printerInfo.location();
ui->listWidget->addItem(info);
info = "makeAndModel: " + printerInfo.makeAndModel();
ui->listWidget->addItem(info);
info = "maximumPhysicalPageSize: " + printerInfo.maximumPhysicalPageSize().name();
ui->listWidget->addItem(info);
info = "minimumPhysicalPageSize: " + printerInfo.minimumPhysicalPageSize().name();
ui->listWidget->addItem(info);
info = "printerName: " + printerInfo.printerName();
ui->listWidget->addItem(info);
info = "state: ";
switch(printerInfo.state())
{
case QPrinter::Idle:
info += "Idle";
break;
case QPrinter::Active:
info += "Active";
break;
case QPrinter::Aborted:
info += "Aborted";
break;
case QPrinter::Error:
info += "Error";
break;
}
ui->listWidget->addItem(info);
info = "supportedDuplexModes: ";
for(QPrinter::DuplexMode mode : printerInfo.supportedDuplexModes())
{
switch (mode)
{
case QPrinter::DuplexNone:
info += "DuplexNone";
break;
case QPrinter::DuplexAuto:
info += "DuplexAuto";
break;
case QPrinter::DuplexLongSide:
info += "DuplexLongSide";
break;
case QPrinter::DuplexShortSide:
info += "DuplexShortSide";
break;
}
}
ui->listWidget->addItem(info);
info = "supportedPageSizes: ";
for(QPageSize ps : printerInfo.supportedPageSizes())
{
info += ps.name();
}
ui->listWidget->addItem(info);
info = "supportedResolutions: ";
for(int resolution : printerInfo.supportedResolutions())
{
info += QString::number(resolution);
}
ui->listWidget->addItem(info);
info = "supportsCustomPageSizes: ";
info += printerInfo.supportsCustomPageSizes() ? "true" : false;
ui->listWidget->addItem(info);
ui->listWidget->addItem("");
}
}
其中,QPrinterInfo類的詳細信息,大家可以參看Qt幫助文檔。此處,我們使用該類的靜態方法availablePrinters()來獲取到所有可用的打印設備,每一個打印設備由一個QPrinterInfo類來表示,然後我們將每一個QPrinterInfo的詳細信息插入到QListWidget中。每一個QPrinterInfo的信息以一個空行分隔。下面,也用這個空行來完成分頁。“PageSetupDialog”按鈕的實現代碼如下:
//頁面設置對話框
void Widget::on_pagesetupdlg_clicked()
{
QPrinter printer(QPrinter::HighResolution);
QPageSetupDialog dlg(&printer);
if(QDialog::Accepted == dlg.exec())
{
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName("D:/test.pdf");
QPainter painter;
if (! painter.begin(&printer))
{
// failed to open file
qWarning("failed to open file, is it writable?");
return ;
}
int count = ui->listWidget->count();
for(int i = 0, j = 1; i < count; i++)
{
QString text = ui->listWidget->item(i)->text();
if(text != "")
{
//printer.pageSize().width();
painter.drawText(10, painter.fontMetrics().height()*j++, text);
}
else if(text == "" && i < count - 1)
{
if (! printer.newPage()) //分頁
{
qWarning("failed in flushing page to disk, disk full?");
break;
}
j = 1;
}
}
painter.end();
qDebug() << "print finished";
}
}
我們先定義了一個QPrinter對象,爲下面的打印文本操作做準備;然後,再使用該對象定義一個QPageSetupDialog對象;最後,調用該類的exec()函數,顯示出該頁面設置 對話框。在這個頁面中,我們可以設置打印所用的頁面的大小和文本的打印方向,以及文本的邊距等。如果在設置之後點擊了確定按鈕,則代碼中的exec()會返回Accepted,在此,我們使用輸出到文件的方式來將這些文本打印到D:/test.pdf文件中。
至於實際的打印動作,還是由QPainter類來實現的,這得益於計算機的抽象機制,允許我們使用同一套API來完成向屏幕和打印機的輸出。
打開test.pdf,就可以看到我們打印的內容了。
“PrintDialog”按鈕的實現代碼如下:
//打印對話框
void Widget::on_printdlg_clicked()
{
QPrinter printer;
//設置頁數範圍
printer.setFromTo(1, list.size());
QPrintDialog printDlg(&printer, this);
if(QDialog::Accepted == printDlg.exec())
{
QPainter painter;
if (! painter.begin(&printer))
{
// failed to open file
qWarning("failed to open file, is it writable?");
return ;
}
int count = ui->listWidget->count();
for(int i = 0, j = 1; i < count; i++)
{
QString text = ui->listWidget->item(i)->text();
if(text != "")
{
painter.drawText(10, painter.fontMetrics().height()*j++, text);
}
else if(text == "" && i < count - 1)
{
if (! printer.newPage())
{
qWarning("failed in flushing page to disk, disk full?");
break;
}
j = 1;
}
}
painter.end();
qDebug() << "print finished";
}
}
其實,該類的使用方式和上一個類似。都是先定一個QPrinter對象,然後使用該對象來創建一個QPrintDialog對話框,最後調用exec()來顯示該對話框。如下:另外,在代碼中,我們去掉了輸出到文件的代碼,此時,如果點擊確定且計算機連接了可用的打印機的話,就會將內容發送到打印機進行打印。
至於打印預覽也一樣,只不過是將內容輸入到屏幕,展示給用戶看而已。實現代碼如下:
//打印預覽對話框
void Widget::on_printpreviewdlg_clicked()
{
QPrinter printer(QPrinter::HighResolution);
QPrintPreviewDialog printPreDlg(&printer, this);
connect(&printPreDlg, &QPrintPreviewDialog::paintRequested,
[=, this](QPrinter* printer)
{
QPainter painter;
if (! painter.begin(printer))
{
// failed to open file
qWarning("failed to open file, is it writable?");
return ;
}
int count = ui->listWidget->count();
for(int i = 0, j = 1; i < count; i++)
{
QString text = ui->listWidget->item(i)->text();
if(text != "")
{
painter.drawText(10, painter.fontMetrics().height()*j++, text);
}
else if(text == "" && i < count - 1)
{
if (! printer->newPage())
{
qWarning("failed in flushing page to disk, disk full?");
break;
}
j = 1;
}
}
painter.end();
});
printPreDlg.exec();
}
同樣是先創建一個QPrinter對象,然後使用該對象來創建一個QPrintPreviewDialog對象來顯示預覽對話框。不同的是,預覽對話框的內容是通過一個paintRequested信號來請求的,所以,我們連接了該信號,在槽函數中將要顯示的文本通過QPainter 輸出到預覽對話框中。運行結果如下:
注意,我們在連接paintRequestd信號時,使用了C++11的lambda表達式,所以還要在pro文件中添加對c++11的支持。即添加下面這行代碼:
CONFIG += c++11