前言
之前写过二维码的程序,但是在U盘上,没带,又重新找的网上资料写的。
网上二维码的生成,大多用到是第三方库libqrencode,这也一样:
效果图
本来是个动图的,都被和谐了,所以换成截图,而且还打码了。效果是二维码放在一个对话框里,可以移动,但是不可关闭,得靠代码逻辑控制关闭。
参考
主要参考下面的博客,这个作者写的很详细,给了第三库的下载路径,编译和使用示例,我在其基础上对二维码的显示形式进行了点修改,使其更为符合我的项目要求。
Qt + libqrencode 生成二维码_龚建波的博客-CSDN博客
犹豫担心后面此文章链接失效,所以我还是对其进行了简单的记录。
libqrencode地址
官网地址:
libqrencode
我是在github上下载的源码:GitHub - fukuchi/libqrencode: A fast and compact QR Code encoding library
cmake编译libqrencode
使用代码
自己封装了一个类QRCodeDialog,用来显示二维码(对话框),在参考博客代码的基础上进行了一些更改,比如二维码大小根据控件大小调整,二维码形状为正方形等,具体代码如下(ps:这里只特别浅显的使用了一下,具体关于库libqrencode的api并没有学习):
主要是用到了libqrencode里的函数
/**
*
* QRcode_encodeString 从字符串创建一个符号。库自动解析输入字符串并在二维码符号中编码.
* @warning 禁用pthread时线程不安全.
* @param string NUL('\0')结尾的C字符串.
* @param version 符号版本.越大可容纳的信息越多.0则按实际内容确定
* @param level 纠错等级,枚举.
* @param hint 编码模式,utf8用QR_MODE_8.
* @param casesensitive 区分大小写(1) 不区分(0).
* @return 返回QRcode类的实例。结果QRcode的版本可能是大于指定的版本.
* 出现错误时,返回NULL,设置errno以指示错误.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw ERANGE input data is too large.
*/
QRcode *QRcode_encodeString(const char *string, int version,
QRecLevel level, QRencodeMode hint, int casesensitive);
.h 文件
#ifndef QRCODEDIALOG_H
#define QRCODEDIALOG_H
#include <QDialog>
#include <QResizeEvent>
#include"qrencode.h"
#include<QMouseEvent>
namespace Ui {
class QRCodeDialog;
}
class QRCodeDialog : public QDialog
{
Q_OBJECT
public:
explicit QRCodeDialog(QWidget *parent = 0);
~QRCodeDialog();
/**
* @brief setQRCodeInfo 设置二维码信息
* @param info 内容
* @param casesensitive 区分大小写(1) 不区分(0).
*/
void setQRCodeInfo(const QString& info, int casesensitive = 1);
protected:
void resizeEvent(QResizeEvent* event)override;
...
private:
QImage qrEncode(const QString& info, int casesensitive = 1);
private:
Ui::QRCodeDialog *ui;
QString m_strInfo;
int m_iCasesensitive;
...
};
#endif // QRCODEDIALOG_H
.cpp文件
#include "QRCodeDialog.h"
#include "ui_QRCodeDialog.h"
#include <QPainter>
#include<QDebug>
QRCodeDialog::QRCodeDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::QRCodeDialog)
,m_iCasesensitive(1)
{
ui->setupUi(this);
setModal(true);
setWindowFlags(Qt::FramelessWindowHint | Qt::Tool|windowFlags());
ui->label->setAlignment(Qt::AlignCenter);
}
QRCodeDialog::~QRCodeDialog()
{
delete ui;
}
void QRCodeDialog::setQRCodeInfo(const QString &info, int casesensitive)
{
m_strInfo=info;
m_iCasesensitive=casesensitive;
}
void QRCodeDialog::resizeEvent(QResizeEvent *event)
{
if(!m_strInfo.isEmpty())
{
QImage img = qrEncode(m_strInfo,m_iCasesensitive);
QPixmap pix=QPixmap::fromImage(img);
int width=qMin(ui->label->width(),ui->label->height());
pix=pix.scaled(width,width);
//ui->label->setPixmap(QPixmap::fromImage(img));
ui->label->setPixmap(pix);
}
QDialog::resizeEvent(event);
}
QImage QRCodeDialog::qrEncode(const QString &info, int casesensitive)
{
QImage ret; //放二维码图片结果
int scale = 4; //方块绘制大小
QByteArray info_data = info.toUtf8();
QRcode* qr = QRcode_encodeString(info_data.constData(), 0, QR_ECLEVEL_Q, QR_MODE_8, casesensitive);
if (qr && qr->width > 0)
{
int img_width = qr->width * scale;
ret = QImage(img_width, img_width, QImage::Format_Mono); //mono位图
QPainter painter(&ret);
painter.fillRect(0, 0, img_width, img_width, Qt::white);//背景填充白色
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::red); //黑色方块
for (int y = 0; y < qr->width; y++) //行
{
for (int x = 0; x < qr->width; x++) //列
{
if (qr->data[y * qr->width + x] & 1) //1表示黑块
{
QRect r(x * scale, y * scale, scale, scale);
painter.drawRect(r);
}
}
}
QRcode_free(qr);
}
return ret;
}
上面绘制的是黑白色,若是想改变颜色当然也是可以的:
调整QImage的格式,上面代码用的是QImage::Format_Mono,即为通常所讲的位图模式,若是此模式下,即使改变QPainter刷子的颜色,也是无法改变绘制的方块颜色,所以这里改一下
ret = QImage(img_width, img_width,QImage::Format_RGB32 );
修改背景颜色:
painter.fillRect(0, 0, img_width, img_width,QColor(167,220,237));
修改方块的颜色
painter.setBrush(Qt::blue);
最终效果是这样的:
结束语
记录一下吧,省的又忘了。