zoukankan      html  css  js  c++  java
  • 我写的一个Qt 显示二维码( QR Code)的控件(可以去掉对 libpthread 的依赖,而且编译出的库文件可以在 vc2010 的release 模式下使用)

    最近一个项目需要显示二维码,所以花了点时间(只用了一个晚上,写的很不完善),写了个显示二维码的控件。当然这个控件用到了些开源的代码,比如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
     
     在CODE上查看代码片派生到我的代码片
    1. ...  
    2. checking for pkg-config... no  
    3. checking for strdup... yes  
    4. checking for pthread_mutex_init in -lpthread... yes  
    5. checking for png... no  
    6. configure: error: in `/home/Ivan/qrencode-3.4.4':  
    7. configure: error: The pkg-config script could not be found or is too old.  Make sure it  
    8. is in your PATH or set the PKG_CONFIG environment variable to the full  
    9. path to pkg-config.  
    10.   
    11. Alternatively, you may set the environment variables png_CFLAGS  
    12. and png_LIBS to avoid the need to call pkg-config.  
    13. See the pkg-config man page for more details.  
    14.   
    15. To get pkg-config, see <http://pkg-config.freedesktop.org/>.  
    16. 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
     
     在CODE上查看代码片派生到我的代码片
    1. #ifndef QRWIDGET_H  
    2. #define QRWIDGET_H  
    3.   
    4. #include <QWidget>  
    5. #include "qrencode.h"  
    6.   
    7. class QRWidget : public QWidget  
    8. {  
    9.     Q_OBJECT  
    10. public:  
    11.     explicit QRWidget(QWidget *parent = 0);  
    12.     ~QRWidget();  
    13.     void setString(QString str);  
    14.     int getQRWidth() const;  
    15.     bool saveImage(QString name, int size);  
    16. private:  
    17.     void draw(QPainter &painter, int width, int height);  
    18.     QString string;  
    19.     QRcode *qr;  
    20. signals:  
    21.   
    22. protected:  
    23.     void paintEvent(QPaintEvent *);  
    24.     QSize sizeHint() const;  
    25.     QSize minimumSizeHint() const;  
    26. public slots:  
    27. };  
    28.   
    29. #endif // QRWIDGET_H  
    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #include "qrwidget.h"  
    2. #include <QPainter>  
    3. #include <QImage>  
    4. QRWidget::QRWidget(QWidget *parent) : QWidget(parent)  
    5. {  
    6.     qr = NULL;  
    7.     setString("Hello QR Code");  
    8. }  
    9.   
    10. QRWidget::~QRWidget()  
    11. {  
    12.     if(qr != NULL)  
    13.     {  
    14.         QRcode_free(qr);  
    15.     }  
    16. }  
    17.   
    18. int QRWidget::getQRWidth() const  
    19. {  
    20.     if(qr != NULL)  
    21.     {  
    22.         return qr->width;  
    23.     }  
    24.     else  
    25.     {  
    26.         return 0;  
    27.     }  
    28. }  
    29.   
    30. void QRWidget::setString(QString str)  
    31. {  
    32.     string = str;  
    33.     if(qr != NULL)  
    34.     {  
    35.         QRcode_free(qr);  
    36.     }  
    37.     qr = QRcode_encodeString(string.toStdString().c_str(),  
    38.                              1,  
    39.                              QR_ECLEVEL_L,  
    40.                              QR_MODE_8,  
    41.                              1);  
    42.     update();  
    43. }  
    44. QSize QRWidget::sizeHint()  const  
    45. {  
    46.     QSize s;  
    47.     if(qr != NULL)  
    48.     {  
    49.         int qr_width = qr->width > 0 ? qr->width : 1;  
    50.         s = QSize(qr_width * 4, qr_width * 4);  
    51.     }  
    52.     else  
    53.     {  
    54.         s = QSize(50, 50);  
    55.     }  
    56.     return s;  
    57. }  
    58.   
    59. QSize QRWidget::minimumSizeHint()  const  
    60. {  
    61.     QSize s;  
    62.     if(qr != NULL)  
    63.     {  
    64.         int qr_width = qr->width > 0 ? qr->width : 1;  
    65.         s = QSize(qr_width, qr_width);  
    66.     }  
    67.     else  
    68.     {  
    69.         s = QSize(50, 50);  
    70.     }  
    71.     return s;  
    72. }  
    73. bool QRWidget::saveImage(QString fileName, int size)  
    74. {  
    75.     if(size != 0 && !fileName.isEmpty())  
    76.     {  
    77.         QImage image(size, size, QImage::Format_Mono);  
    78.         QPainter painter(&image);  
    79.         QColor background(Qt::white);  
    80.         painter.setBrush(background);  
    81.         painter.setPen(Qt::NoPen);  
    82.         painter.drawRect(0, 0, size, size);  
    83.         if(qr != NULL)  
    84.         {  
    85.             draw(painter, size, size);  
    86.         }  
    87.         return image.save(fileName);  
    88.     }  
    89.     else  
    90.     {  
    91.         return false;  
    92.     }  
    93. }  
    94.   
    95. void QRWidget::draw(QPainter &painter, int width, int height)  
    96. {  
    97.     QColor foreground(Qt::black);  
    98.     painter.setBrush(foreground);  
    99.     const int qr_width = qr->width > 0 ? qr->width : 1;  
    100.     double scale_x = width / qr_width;  
    101.     double scale_y = height / qr_width;  
    102.     for( int y = 0; y < qr_width; y ++)  
    103.     {  
    104.         for(int x = 0; x < qr_width; x++)  
    105.         {  
    106.             unsigned char b = qr->data[y * qr_width + x];  
    107.             if(b & 0x01)  
    108.             {  
    109.                 QRectF r(x * scale_x, y * scale_y, scale_x, scale_y);  
    110.                 painter.drawRects(&r, 1);  
    111.             }  
    112.         }  
    113.     }  
    114. }  
    115.   
    116. void QRWidget::paintEvent(QPaintEvent *)  
    117. {  
    118.     QPainter painter(this);  
    119.     QColor background(Qt::white);  
    120.     painter.setBrush(background);  
    121.     painter.setPen(Qt::NoPen);  
    122.     painter.drawRect(0, 0, width(), height());  
    123.     if(qr != NULL)  
    124.     {  
    125.         draw(painter, width(), height());  
    126.     }  
    127. }  

    下面是软件界面:

    http://blog.csdn.net/liyuanbhu/article/details/44599031

  • 相关阅读:
    Android的LinearLayout中orientation默认值为什么是HORIZONTAL
    Android中HttpURLConnection对象是怎么生成的
    记一个擦除硬盘数据,防止已删除文件被恢复的程序
    添加一个Android框架层的系统服务与实现服务的回调
    在 Activity 中实现 getContentView 操作
    (01)明明配置了log4j.properties为什么还是不打印日志
    (05)pom.xml文件报错web.xml is missing and <failOnMissingWebXml> is set to true
    (04)maven中的几个常用插件
    (03)开发环境eclipse、myEclipse本地tomcat调试发布maven项目遇到的糟心事
    (04)Storm与Kafka结合使用简单案例
  • 原文地址:https://www.cnblogs.com/findumars/p/6546099.html
Copyright © 2011-2022 走看看