Qt中的打印操作

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章