我写的一个Qt 显示二维码( QR Code)的控件(可以去掉对 libpthread 的依赖,而且编译出的库文件可以在 vc2010 的release 模式下使用)
2017-03-14 01:53
1156 查看
最近一个项目需要显示二维码,所以花了点时间(只用了一个晚上,写的很不完善),写了个显示二维码的控件。当然这个控件用到了些开源的代码,比如qrencode,所以我也打算把我的代码开源。
我的代码参考了
http://stackoverflow.com/questions/21400254/how-to-draw-a-qr-code-with-qt-in-native-c-c
基本就是按照这里面的思路来写的。
首先要下载 libqrencode,这是一个c 语言的QR code 生成库。QR Code 可以容纳 7000 个数字或者4000个字符,可以承载的信息量很大,用起来也很方便。关于QR Code更详细的信息可以自行 google.
Libqrencode 暂时只支持 QR Code model 2,如果需要ECI 或者FNC1模式的话,还要想别的办法。
编译Libqrencode 我用的是 MSYS2,直接 configure 的话还遇到了点小问题,报的错误如下:
[plain] view plain copy
...
checking for pkg-config... no
checking for strdup... yes
checking for pthread_mutex_init in -lpthread... yes
checking for png... no
configure: error: in `/home/Ivan/qrencode-3.4.4':
configure: error: The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
Alternatively, you may set the environment variables png_CFLAGS
and png_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
See `config.log' for more details
大体的意思就是我的编译环境中没有 pkg-config,不过没关系,按照作者的说法,Libqrencode 不依赖于任何第三方的库。在configure 时加一个参数--without-tools ,就可以顺利通过了。
编译之后在 .lib 目录中生成一个 libqrencode.a ,再加上 qrencode.h 这两个文件就够了。我用的Qt 开发环境是 VS2010+Qt4.5.1 。Libqrencode.a 在 VS2010 中也是可以用的,另外还需要libwinpthread.dll.a 这个文件,因为Libqrencode中用到了libpthread 的一些函数。
补充一下,经过测试,这里生成的 libqrencode.a 在 VS2010 中使用还是有些问题的,表现为 Debug 模式下运行正常,可是一旦将程序编译为 Release 模式就无法运行。看来还需要用 vs2010 编译libqrencode。估计不那么简单,等有时间了折腾一下。
将 config.h 文件中
/* Define to 1 if using pthread is enabled. */
#define HAVE_LIBPTHREAD 1
改为:
//#define HAVE_LIBPTHREAD 1
就可以去掉对 libpthread 的依赖,而且编译出的库文件可以在 vc2010 的release 模式下使用。
我写的控件很简单,具体的看代码吧
[cpp] view plain copy
#ifndef QRWIDGET_H
#define QRWIDGET_H
#include <QWidget>
#include "qrencode.h"
class QRWidget : public QWidget
{
Q_OBJECT
public:
explicit QRWidget(QWidget *parent = 0);
~QRWidget();
void setString(QString str);
int getQRWidth() const;
bool saveImage(QString name, int size);
private:
void draw(QPainter &painter, int width, int height);
QString string;
QRcode *qr;
signals:
protected:
void paintEvent(QPaintEvent *);
QSize sizeHint() const;
QSize minimumSizeHint() const;
public slots:
};
#endif // QRWIDGET_H
[cpp] view plain copy
#include "qrwidget.h"
#include <QPainter>
#include <QImage>
QRWidget::QRWidget(QWidget *parent) : QWidget(parent)
{
qr = NULL;
setString("Hello QR Code");
}
QRWidget::~QRWidget()
{
if(qr != NULL)
{
QRcode_free(qr);
}
}
int QRWidget::getQRWidth() const
{
if(qr != NULL)
{
return qr->width;
}
else
{
return 0;
}
}
void QRWidget::setString(QString str)
{
string = str;
if(qr != NULL)
{
QRcode_free(qr);
}
qr = QRcode_encodeString(string.toStdString().c_str(),
1,
QR_ECLEVEL_L,
QR_MODE_8,
1);
update();
}
QSize QRWidget::sizeHint() const
{
QSize s;
if(qr != NULL)
{
int qr_width = qr->width > 0 ? qr->width : 1;
s = QSize(qr_width * 4, qr_width * 4);
}
else
{
s = QSize(50, 50);
}
return s;
}
QSize QRWidget::minimumSizeHint() const
{
QSize s;
if(qr != NULL)
{
int qr_width = qr->width > 0 ? qr->width : 1;
s = QSize(qr_width, qr_width);
}
else
{
s = QSize(50, 50);
}
return s;
}
bool QRWidget::saveImage(QString fileName, int size)
{
if(size != 0 && !fileName.isEmpty())
{
QImage image(size, size, QImage::Format_Mono);
QPainter painter(&image);
QColor background(Qt::white);
painter.setBrush(background);
painter.setPen(Qt::NoPen);
painter.drawRect(0, 0, size, size);
if(qr != NULL)
{
draw(painter, size, size);
}
return image.save(fileName);
}
else
{
return false;
}
}
void QRWidget::draw(QPainter &painter, int width, int height)
{
QColor foreground(Qt::black);
painter.setBrush(foreground);
const int qr_width = qr->width > 0 ? qr->width : 1;
double scale_x = width / qr_width;
double scale_y = height / qr_width;
for( int y = 0; y < qr_width; y ++)
{
for(int x = 0; x < qr_width; x++)
{
unsigned char b = qr->data[y * qr_width + x];
if(b & 0x01)
{
QRectF r(x * scale_x, y * scale_y, scale_x, scale_y);
painter.drawRects(&r, 1);
}
}
}
}
void QRWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QColor background(Qt::white);
painter.setBrush(background);
painter.setPen(Qt::NoPen);
painter.drawRect(0, 0, width(), height());
if(qr != NULL)
{
draw(painter, width(), height());
}
}
下面是软件界面:
http://blog.csdn.net/liyuanbhu/article/details/44599031
我的代码参考了
http://stackoverflow.com/questions/21400254/how-to-draw-a-qr-code-with-qt-in-native-c-c
基本就是按照这里面的思路来写的。
首先要下载 libqrencode,这是一个c 语言的QR code 生成库。QR Code 可以容纳 7000 个数字或者4000个字符,可以承载的信息量很大,用起来也很方便。关于QR Code更详细的信息可以自行 google.
Libqrencode 暂时只支持 QR Code model 2,如果需要ECI 或者FNC1模式的话,还要想别的办法。
编译Libqrencode 我用的是 MSYS2,直接 configure 的话还遇到了点小问题,报的错误如下:
[plain] view plain copy
...
checking for pkg-config... no
checking for strdup... yes
checking for pthread_mutex_init in -lpthread... yes
checking for png... no
configure: error: in `/home/Ivan/qrencode-3.4.4':
configure: error: The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
Alternatively, you may set the environment variables png_CFLAGS
and png_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
See `config.log' for more details
大体的意思就是我的编译环境中没有 pkg-config,不过没关系,按照作者的说法,Libqrencode 不依赖于任何第三方的库。在configure 时加一个参数--without-tools ,就可以顺利通过了。
编译之后在 .lib 目录中生成一个 libqrencode.a ,再加上 qrencode.h 这两个文件就够了。我用的Qt 开发环境是 VS2010+Qt4.5.1 。Libqrencode.a 在 VS2010 中也是可以用的,另外还需要libwinpthread.dll.a 这个文件,因为Libqrencode中用到了libpthread 的一些函数。
补充一下,经过测试,这里生成的 libqrencode.a 在 VS2010 中使用还是有些问题的,表现为 Debug 模式下运行正常,可是一旦将程序编译为 Release 模式就无法运行。看来还需要用 vs2010 编译libqrencode。估计不那么简单,等有时间了折腾一下。
将 config.h 文件中
/* Define to 1 if using pthread is enabled. */
#define HAVE_LIBPTHREAD 1
改为:
//#define HAVE_LIBPTHREAD 1
就可以去掉对 libpthread 的依赖,而且编译出的库文件可以在 vc2010 的release 模式下使用。
我写的控件很简单,具体的看代码吧
[cpp] view plain copy
#ifndef QRWIDGET_H
#define QRWIDGET_H
#include <QWidget>
#include "qrencode.h"
class QRWidget : public QWidget
{
Q_OBJECT
public:
explicit QRWidget(QWidget *parent = 0);
~QRWidget();
void setString(QString str);
int getQRWidth() const;
bool saveImage(QString name, int size);
private:
void draw(QPainter &painter, int width, int height);
QString string;
QRcode *qr;
signals:
protected:
void paintEvent(QPaintEvent *);
QSize sizeHint() const;
QSize minimumSizeHint() const;
public slots:
};
#endif // QRWIDGET_H
[cpp] view plain copy
#include "qrwidget.h"
#include <QPainter>
#include <QImage>
QRWidget::QRWidget(QWidget *parent) : QWidget(parent)
{
qr = NULL;
setString("Hello QR Code");
}
QRWidget::~QRWidget()
{
if(qr != NULL)
{
QRcode_free(qr);
}
}
int QRWidget::getQRWidth() const
{
if(qr != NULL)
{
return qr->width;
}
else
{
return 0;
}
}
void QRWidget::setString(QString str)
{
string = str;
if(qr != NULL)
{
QRcode_free(qr);
}
qr = QRcode_encodeString(string.toStdString().c_str(),
1,
QR_ECLEVEL_L,
QR_MODE_8,
1);
update();
}
QSize QRWidget::sizeHint() const
{
QSize s;
if(qr != NULL)
{
int qr_width = qr->width > 0 ? qr->width : 1;
s = QSize(qr_width * 4, qr_width * 4);
}
else
{
s = QSize(50, 50);
}
return s;
}
QSize QRWidget::minimumSizeHint() const
{
QSize s;
if(qr != NULL)
{
int qr_width = qr->width > 0 ? qr->width : 1;
s = QSize(qr_width, qr_width);
}
else
{
s = QSize(50, 50);
}
return s;
}
bool QRWidget::saveImage(QString fileName, int size)
{
if(size != 0 && !fileName.isEmpty())
{
QImage image(size, size, QImage::Format_Mono);
QPainter painter(&image);
QColor background(Qt::white);
painter.setBrush(background);
painter.setPen(Qt::NoPen);
painter.drawRect(0, 0, size, size);
if(qr != NULL)
{
draw(painter, size, size);
}
return image.save(fileName);
}
else
{
return false;
}
}
void QRWidget::draw(QPainter &painter, int width, int height)
{
QColor foreground(Qt::black);
painter.setBrush(foreground);
const int qr_width = qr->width > 0 ? qr->width : 1;
double scale_x = width / qr_width;
double scale_y = height / qr_width;
for( int y = 0; y < qr_width; y ++)
{
for(int x = 0; x < qr_width; x++)
{
unsigned char b = qr->data[y * qr_width + x];
if(b & 0x01)
{
QRectF r(x * scale_x, y * scale_y, scale_x, scale_y);
painter.drawRects(&r, 1);
}
}
}
}
void QRWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QColor background(Qt::white);
painter.setBrush(background);
painter.setPen(Qt::NoPen);
painter.drawRect(0, 0, width(), height());
if(qr != NULL)
{
draw(painter, width(), height());
}
}
下面是软件界面:
http://blog.csdn.net/liyuanbhu/article/details/44599031
相关文章推荐
- 我写的一个Qt 显示二维码( QR Code)的控件
- 我写的一个Qt 显示二维码( QR Code)的控件
- 使用WinRar将Qt编译生成的exe和依赖的dll文件打包为一个exe文件的简单方法
- 一个 Qt 显示图片的控件(继承QWidget,使用QPixmap记录图像,最后在paintEvent进行绘制,可缩放)
- 编译一个可以不依赖vs的release项目
- Qt 在Release 模式下 qDebug 等 显示输出信息的行号和文件
- mingw qt(可以去掉mingwm10.dll、libgcc_s_dw2-1.dll、libstdc++-6.dll的依赖,mingw默认都是动态链接gcc的库而TDM是静态链接gcc库,tdm版本更好用。用aspack压缩没有问题。qt本身不使用异常处理)good
- VC2010使用GDI+在picture control控件里面显示图片
- 一个可以显示图片(包括GIF动画)的ATL控件,以及在RichEdit中如何使用此控件插入图片
- QT使用MySql的配置(使用addLibraryPath载入插件),编译QT的MySql驱动问题及解决方案(自己使用libmysql.lib进行编译mysql.pro,万不得已可以查看Makefile.Debug以解决问题)
- 创建一个程序读入和显示视频文件,并可以使用滑动条控制视频文件的播放。一个滑动条用来控制视频播放位置,以10为步长跳进。另一个滑动条用来控制停止/播放
- Qt5.2.0 MinGW480 release静态版编译结果、过程及QtCreator配置分享(realfan的编译方法)(configure -h可以显示帮助)(静态编译mysql插件,需要做一些其它工作,机器上要有mysql)(不编译qtwebkit,就不用安装ActivePerl了)(用到 QMediaPlayer的编译办法)
- 编译一个可以不依赖vs的release项目
- 启动VC++2010时显示“您可以在命令行上使用/log参数运行应用程序”的解决办法
- VC2010 中使用条件编译判断是32位还是64位编译模式
- 备忘: VC++ 自动适用编译两种模式库文件 (DLL, LIB)
- 使用draggablegridview开源库添加自定义控件可以显示,添加自定义的layout文件可以显示背景色但是无法显示其控件
- 使用javac命令编译文件同一个包下的依赖类找不到
- 一个可以显示图片(包括GIF动画)的ATL控件,以及在RichEdit中如何使用此控件插入图片
- 一个VC6的工程转换为VS2008的工程后,编译找不到而且不能升级vc90.pdb文件的问题解决方法 2010-9-28 14:00