也許你的苦思冥想,大神們早已有答案。打開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 <QGraphicsItem>
#include <qzint.h>
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 <QDebug>
#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條碼庫的強大已經有目共睹了,有相關需求的可以下載下傳一份ZINT條碼庫研究一下,畢竟重複造輪子這種事兒還是少幹為妙。
ps:其實任何事情都要用辨證的角度去看,雖然我當初煞費苦心的研究條碼的編碼規則,通過效率并不高的算法實作了一些常用條碼的生成,但至少我懂了條碼的編碼規則,當客戶需要連續變化的條碼時,我可以很自信的告訴他選擇code_128條碼,當客戶輸入條碼内容和實際生成的條碼掃出來不一緻時,我能很确定的告訴客戶你輸入的條碼内容不标準,條碼校驗碼錯了,或許這些就是我最大的收獲吧。
測試程式下載下傳位址:https://download.csdn.net/download/p154613730/10833507