zoukankan      html  css  js  c++  java
  • 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
    ---------------------
    作者:求道玉
    来源:CSDN
    原文:https://blog.csdn.net/amnes1a/article/details/70597506
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    Nginx系列p5:进程管理(信号)
    Nginx系列p4:进程结构
    one_day_one_linuxCmd---crontab 命令
    Nginx系列p3:实现一个具有缓存功能的反向代理服务器
    Nginx系列p2:重载,热部署,日志分割
    Nginx系列p1:安装
    数据链路层
    物理层习题与真题
    物理层
    计算机网络体系结构习题与真题
  • 原文地址:https://www.cnblogs.com/findumars/p/10246936.html
Copyright © 2011-2022 走看看