Zint生成多种条码及二维码

也许你的苦思冥想,大神们早已有答案。打开CSDN手机App,看到这么一段话,突然有很多感触,相信很多小伙伴都有同样的想法。很多时候,我们都是在干着重复造轮子的事儿,有时是我们当时认知有限,有时是我们太执着。

还记得当时项目需要根据输入内容实时生成几种常用的一维条形码,当时也没怎么多想,找来一本常用条码编码规则的书,照着书上介绍的各种条码的编码规则,一步一步通过算法实现了,依稀还记得当初每次实现一个条码后激动的心情。完成后还得到了老板的表扬,当时心里别提有多舒畅。

再到后来,项目需要根据输入内容生成二维码(QR码),还是老规矩,找来二维码的编码规则,看了好久,发现二维码的编码规则相对一位条码来说,复杂了太多,当时心里有点没底。心想看看网上有没有类似的生成二维码的算法,在网上搜索了一下,阅读了别人写的一些关于QRcode的文章,最后发现一个qrencode-3.4.4的标准库。下载后查看了库的一些用法,结合项目的实际需求,花了大概半天的时间就生成了符合项目需求的二维码,能够调用标准库里提供的API来调整二维码的属性。当时心里还在感慨提供这个库的人真NB,这个库太好用了!省去了很多二维码的开发时间。

再后来,项目需要根据输入内容生成Datamatrix码,不同以往,我这次连DM码的编码规则都没看,直接在网上搜索相关Datamatrix码的相关信息,果然,我又发现一个libdmtx-0.7.4的标准库,还支持中文编码。没过多久我又把DM码给鼓捣出来了。

空闲时,我又在网上搜索了相关条码以及二维码生成的相关信息,最后发现了一个功能更加强大的Zint条码库。Zint 条码库支持目前市场上主流的条码类型,包括 QR码、DM码、code-128码、EAN13码等等。最让我惊喜的是,有大神基于Qt对zint条码库进行了一次简单的封装,生成条码的同时对条码内容的绘制进行了合理的布局,能够自适应条码的缩放,这个功能对我来说太有意义了。分享一下,希望对大家有帮助。

具体实现方式也很简单,在官网上下载最新的ZINT条码库,可以直接编译成动态链接库,当然也可以把源码嵌入到工程文件直接编译使用,我使用后者进行测试。


#ifndef BARCODEITEM_H
#define BARCODEITEM_H

#include 
#include 

class BarcodeItem : public QGraphicsItem
{
public:
    explicit BarcodeItem(QGraphicsItem *parent = Q_NULLPTR);
	~BarcodeItem();

	QRectF boundingRect() const;
	void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);

public:
    mutable Zint::QZint barcode;

	Zint::QZint::AspectRatioMode ar;

    QRectF rect() const;
    void setRect(const QRectF &rect);
    inline void setRect(qreal x, qreal y, qreal w, qreal h);

    struct BarcodeItemProp{
        int m_symbol;
        QString m_text;
        QString m_primaryMessage;
        int m_height;
        int m_borderWidth;
        int m_width;
        int m_securityLevel;
        int m_pdf417CodeWords;
        int m_input_mode;
        QColor m_fgColor;
        QColor m_bgColor;
        QString m_lastError;
        int m_error;
        int m_whitespace;
        zint_symbol * m_zintSymbol;
        float m_scale;
        int m_option_3;
        bool m_hidetext;
        float m_dot_size;
    } barcodeItemPara;

    void drawBarcodeItem(BarcodeItemProp barcodeItemPara);


private:
    QRectF m_rect;
    mutable QRectF m_boundingRect;
};

inline void BarcodeItem::setRect(qreal x, qreal y, qreal w, qreal h)
{
    setRect(QRectF(x, y, w, h));
}

#endif

#include 
#include "barcodeitem.h"

BarcodeItem::BarcodeItem(QGraphicsItem *parent)
        : QGraphicsItem(parent)
{
    setRect(QRectF(0,0,200,200));

    barcodeItemPara.m_symbol = BARCODE_CODE128;
    barcodeItemPara.m_hidetext = false;
    barcodeItemPara.m_text = "6922162891569";
    barcodeItemPara.m_height = 38;
    barcodeItemPara.m_scale = 8.0;
    barcodeItemPara.m_dot_size = 4.0 / 5.0;
    barcodeItemPara.m_pdf417CodeWords = 928;
    barcodeItemPara.m_securityLevel = -1;
    barcodeItemPara.m_input_mode = UNICODE_MODE;
    barcodeItemPara.m_option_3 = 0;
    barcodeItemPara.m_width = 0;
    barcodeItemPara.m_borderWidth = 1;
}

BarcodeItem::~BarcodeItem()
{
}

QRectF BarcodeItem::boundingRect() const
{
    //return QRectF(0, 0, w, h);
    if(m_boundingRect.width() == 0){
        m_boundingRect = QRectF(0,0,800,300);
    }
    return m_boundingRect;
}

void BarcodeItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
    barcode.render(*painter,boundingRect(),ar);
}

QRectF BarcodeItem::rect() const
{
    return m_rect;
}

void BarcodeItem::setRect(const QRectF &rect)
{
    if(m_rect == rect)
        return;
    prepareGeometryChange();
    m_rect = rect;
    m_boundingRect = m_rect;
    update();
}

void BarcodeItem::drawBarcodeItem(BarcodeItem::BarcodeItemProp barcodeItemPara)
{
    barcode.setHeight(barcodeItemPara.m_height);
    barcode.setText(barcodeItemPara.m_text);
    barcode.setScale(barcodeItemPara.m_scale);
    barcode.setInputMode(barcodeItemPara.m_input_mode);
    barcode.setWidth(barcodeItemPara.m_width);
    barcode.setOption3(barcodeItemPara.m_option_3);
    barcode.setHideText(barcodeItemPara.m_hidetext);
    barcode.setDotSize(barcodeItemPara.m_dot_size);
    barcode.setPdf417CodeWords(barcodeItemPara.m_pdf417CodeWords);
    barcode.setSymbol(barcodeItemPara.m_symbol);
    barcode.setSecurityLevel(barcodeItemPara.m_securityLevel);
    barcode.setBorderWidth(barcodeItemPara.m_borderWidth);
    barcode.setBorderType(Zint::QZint::NO_BORDER);

    this->setRect(QRectF(0,0,barcode.width()*barcodeItemPara.m_scale,barcode.height()*barcodeItemPara.m_scale));
    update();
}


 

添加一个继承QGraphicsItem的类用来绘制条码及二维码,主要的是实现方法封装在qzint类中的render()函数体中,这里就不贴代码了。具体的调用方法很简单,设置条码内容,条码类别,以及对应条码相关属性后,调用drawBarcodeItem()更新条码信息,调用update()执行paint()完成对barcodeItem的重绘,更新条码显示。

 

    BarcodeItem *barcode = new BarcodeItem;
    QGraphicsScene *scene = new QGraphicsScene;
    QGraphicsView *view = new QGraphicsView;

    barcode->drawBarcodeItem(barcode->barcodeItemPara);
    scene->addItem(barcode);
    view->setScene(scene);

    QVBoxLayout *vLayout = new QVBoxLayout;
    QLineEdit *input = new QLineEdit;
    QComboBox *box = new QComboBox;
    QStringList barcodeList;
    barcodeList << "Barcode_128"
                << "Barcode_39"
                << "EAN13"
                << "QRcode"
                << "Datamatrix"
                << "Pdf147";
    input->setText(QString("6922162891569"));
    box->addItems(barcodeList);
    input->setFixedHeight(50);
    box->setFixedHeight(50);

    vLayout->addWidget(view);
    vLayout->addWidget(input);
    vLayout->addWidget(box);
    this->setLayout(vLayout);

    connect(input,&QLineEdit::textChanged,this,[=](const QString inputStr){
        barcode->barcodeItemPara.m_text = inputStr;
        barcode->drawBarcodeItem(barcode->barcodeItemPara);
        view->update();
    });

    connect(box,&QComboBox::currentTextChanged,this,[=](const QString comboStr){
        if(comboStr == QString("Barcode_128")){
            barcode->barcodeItemPara.m_symbol = BARCODE_CODE128;
        }
        else if(comboStr == QString("Barcode_39")){
            barcode->barcodeItemPara.m_symbol = BARCODE_CODE39;
        }
        else if(comboStr == QString("EAN13")){
            barcode->barcodeItemPara.m_symbol = BARCODE_EANX;
        }
        else if(comboStr == QString("QRcode")){
            barcode->barcodeItemPara.m_symbol = BARCODE_QRCODE;
        }
        else if(comboStr == QString("Datamatrix")){
            barcode->barcodeItemPara.m_symbol = BARCODE_DATAMATRIX;
        }
        else if(comboStr == QString("Pdf147")){
            barcode->barcodeItemPara.m_symbol = BARCODE_PDF417;
        }
        barcode->drawBarcodeItem(barcode->barcodeItemPara);
        view->update();
    });    

这里测试了code_128,code_39,EAN13,qrcode,datamatrix,pdf417,生成6中条码如下:

Zint生成多种条码及二维码_第1张图片

Zint生成多种条码及二维码_第2张图片

Zint生成多种条码及二维码_第3张图片

Zint生成多种条码及二维码_第4张图片

Zint生成多种条码及二维码_第5张图片

Zint生成多种条码及二维码_第6张图片

看到这里相信大家对ZINT条码库的强大已经有目共睹了,有相关需求的可以下载一份ZINT条码库研究一下,毕竟重复造轮子这种事儿还是少干为妙。

ps:其实任何事情都要用辨证的角度去看,虽然我当初煞费苦心的研究条码的编码规则,通过效率并不高的算法实现了一些常用条码的生成,但至少我懂了条码的编码规则,当客户需要连续变化的条码时,我可以很自信的告诉他选择code_128条码,当客户输入条码内容和实际生成的条码扫出来不一致时,我能很确定的告诉客户你输入的条码内容不标准,条码校验码错了,或许这些就是我最大的收获吧。

测试程序下载地址:https://download.csdn.net/download/p154613730/10833507

 

你可能感兴趣的:(Qt)