序文
以前にQRコードのプログラムを書いたことがあるのですが、USBメモリに入っていて持ってこなかったので、ネットの情報から探して書き直しました。
オンライン QR コード生成のほとんどは、サードパーティ ライブラリ libqrencode を使用します。これも同様です。
レンダリング
元々はアニメ絵だったのですが、ハモりがあったのでスクリーンショットに差し替え、さらにコーディングもしました。その結果、QR コードはダイアログ ボックスに配置され、移動することはできますが、閉じることはできません。コード ロジック制御によって閉じる必要があります。
参考
主に以下のブログを参考に、作者が詳しく書いたもので、第3ライブラリのダウンロードパス、コンパイル、使用例などを記載し、それをもとにQRコードの表示形式をより適切なものになるよう修正してみました。私にとって、プロジェクトの要件。
Qt + libqrencode で QR コードを生成_Gong Jianbo のブログ - CSDN ブログ
この記事へのリンクが後で無効になるのではないかと躊躇していたので、簡単に記録しました。
libqrencode アドレス
公式サイトアドレス:
ソースコードはgithubからダウンロードしました: GitHub - Fukuchi/libqrencode: A fast and Compact QR Code encoder library
cmakeはlibqrencodeをコンパイルします
コードを使用する
QR コード (ダイアログ ボックス) を表示するクラス QRCodeDialog をカプセル化しました。参考ブログのコードに基づいていくつかの変更を加えました。たとえば、QR コードのサイズは、コントロールのサイズ、QR の形状に応じて調整されますコードは正方形などです。 具体的なコードは次のとおりです (追記: ここでは簡単に使用しただけで、ライブラリ 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);
最終的な効果は次のとおりです。
結論
忘れないように書き留めてください。