qt實現界面顯示和打印部分分離

1.需求

要求實現pos端結算時彈出找零界面同時進行打開錢箱打印,找零界面是阻塞對話框,

2.解決

1.採用多線程解決找零界面是ui 打印因爲是通過html打印也是ui線程 qt規定所有ui只能在ui線程中 故無法導通
2.通過將html打印成圖片 開打印線程將圖片繪製到打印紙上 出現打印出來的東東較爲模糊 故無法導通
3.將打印單獨拎出來 打印時直接調用打印進程來搞 可以導通

3.代碼

調用部分代碼
void myprinter::on_testbtn_clicked()
{
    QString strExePath("");
    strExePath = QCoreApplication::applicationDirPath() + "\\catprinter.exe";

    //if (m_process.isOpen())
    QString strHtml("");
    strHtml += QString("<html>"
        "<head><style type=\"text/css\">"
        "body {margin-left:5%;}"
        "h1 {font-size:110%;text-align:center;width:100%;line-height:90%}"
        "h2 {font-size:100%;text-align:center;width=100%;line-height:90%}"
        "h3 {font-size:90%;text-align:center;width:100%;line-height:90%}");
    strHtml += QString("th {font-size:%1%;text-align:left;margin-left:0;line-height:90%}"
        "td {font-size:%1%;text-align:left;margin-left:0;line-height:90%}"
        "table {border:0;width:90%}</style></head>").arg(65);

    //頭部
    strHtml += QString("<body>");
    strHtml += QString("<h2>");
    strHtml += QStringLiteral("8637品牌工廠店部分");
    strHtml += QString("</h2>");
    strHtml += QString("</body></html>");

    QStringList list;
    list.push_back(strHtml);
    list.push_back(QString("80"));
    list.push_back(QString("1"));
    list.push_back(QString("GP-80160(Cut) Series"));
    list.push_back(QString("1"));
    list.push_back(QString("ST-1234567898776"));
    //QProcess process;
    m_process.startDetached(strExePath, list);

    //QMessageBox::information(this, "msg", "test");
}
打印進程 main.cpp
#include "catprinter.h"
#include <QtWidgets/QApplication>
#include <QtPrintSupport\QPrinter>
#include <QtPrintSupport\QPrintDialog>
#include <QtWebKitWidgets\QWebFrame>
#include <QtWebKitWidgets\QWebPage>
#include <QtWebKit\QWebElement>
#include <QtGui\QPageSize>
#include <QtCore\QRectF>
#include <QtGui\QPainter>
#include <QtGui\QTextDocument>
#include <QtCore\QFile>
#include <QtCore\QTextCodec>
#include <QPrinterInfo>
#include <windows.h>
#include <QStringList>

#include "zint.h"
#ifdef _DEBUG
#pragma comment(lib, "../Win32/Debug/zintd.dll.lib")
#else
#pragma comment(lib, "../Win32/Release/zint.dll.lib")
#endif

typedef struct stHtml
{
    bool bBarcode;
    int nTicketSize;
    int nPages;
    QString strPrinterName;
    QString strTicket;
}S_HTML;

void printHtml(const QString &strHtml, S_HTML &shtml);
bool drawBarcode(QPainter &painter, const QString &strImagePath, const QRect &rtBarcode, int width);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QString strHtml("");
    QStringList list = QCoreApplication::arguments();
    S_HTML shtml;
    if (list.count() > 6)
    {
        strHtml = list[1];
        shtml.nTicketSize = list[2].toInt();//stSetInfo.nTicketSize;
        shtml.nPages = list[3].toInt();//stSetInfo.nPages;
        shtml.strPrinterName = list[4];//stSetInfo.strPrinterName;
        shtml.bBarcode = list[5].toInt();//mapFormat[E_PRINT_BARCODE];           //modified by zrq 20150930
        shtml.strTicket = list[6];//stInfo.strTicket;
        printHtml(strHtml, shtml);
        //return a.exec();
    }
    else
        //return 0;

    //這裏調用打印機進行打印
    return 0; //a.exec();
}

void printHtml(const QString &strHtml, S_HTML &shtml)
{
    if (shtml.strPrinterName.isEmpty())
        return;

    QPrinter printer;
    printer.setPrinterName(shtml.strPrinterName);
    //貌似沒什麼用,不過我還是設置了下
    printer.setFullPage(true);

    //計算在打印機的DPI下,58mm對應的點數
    int dpi=printer.logicalDpiX();
    int width=min(shtml.nTicketSize, printer.paperRect(QPrinter::Millimeter).width())*(dpi*1.0/25.4);//58mm

    //使用QWebPage來解析並輸出解析後的文檔到打印機
    QWebPage page;  
    page.mainFrame()->setHtml(strHtml);

    QWebFrame *frame=page.mainFrame();

    //設置網頁視口大小,因爲我在html文檔中用相對大小布局的
    page.setViewportSize(QSize(width,frame->findFirstElement("body").geometry().height()));

    if (!shtml.bBarcode)
    {
        for (int npage = 0; npage < shtml.nPages;)
        {
            QPainter painter(&printer);
            if (painter.isActive())
                frame->render(&painter);
            ++npage;
        }
    }
    else
    {
        QString strTicket(shtml.strTicket);
        if (strTicket.length() > 3)
            strTicket = strTicket.mid(3);

        QString strImagePath("");
        strImagePath = QCoreApplication::applicationDirPath() + "//test.png";
        struct zint_symbol * my_symbol = ZBarcode_Create();
        my_symbol->symbology = BARCODE_CODE93;//BARCODE_CODE11;
        strcpy(my_symbol->outfile, strImagePath.toLocal8Bit().toStdString().c_str());
        ZBarcode_Encode(my_symbol, (unsigned char*)strTicket.toLocal8Bit().toStdString().c_str(), 0);
        ZBarcode_Print(my_symbol, 0); 
        ZBarcode_Delete(my_symbol);

        QSize imgsize(width, frame->findFirstElement("table.barcode").geometry().height());
        QRect rtBarcode(2, frame->findFirstElement("table.barcode").geometry().top(), 
                        imgsize.width(), imgsize.height());

        for (int npage = 0; npage < shtml.nPages;)
        {
            //這裏修改下直接打印到圖片上看下效果
            QPainter painter(&printer);
            if (painter.isActive())
                frame->render(&painter);
            drawBarcode(painter, strImagePath, rtBarcode, width);
            ++npage;
        }
    }
}

bool drawBarcode(QPainter &painter, const QString &strImagePath, const QRect &rtBarcode, int width)
{
    QImage image(strImagePath, "PNG");
    QRect rt1 = image.rect();
    QRect rtwindow = painter.window();
    QRect rtview = painter.viewport();
    int nmax = 0;
    if (image.width() + 20 < width)
        nmax = max(image.width() + 20, width);
    else
        nmax = min(image.width() + 20, width);

    QRect rtimage(0, 0, nmax, rtwindow.height());
    QRect rtimageview(0, 0, nmax, rtview.height());
    int nmin = min(image.width(), nmax - 80);
    QRectF rtdes(40, rtBarcode.top(), nmin, rtBarcode.height());
    QRectF rtsrc(0, 0, image.width(), image.height());
    painter.setWindow(rtimage);
    painter.setViewport(rtimageview);
    painter.drawImage(rtdes, image, rtsrc);  
    painter.setWindow(rtwindow);
    painter.setViewport(rtview);
    return true;
}

4.備註

1.完整測試部分代碼:http://download.csdn.net/detail/zhang_ruiqiang/9173255
2.調用時也可以將調用打印部分放在線程中,在線程中調用打印進程
發佈了65 篇原創文章 · 獲贊 8 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章