制作Code128B一维条形码的综合教程

制作Code128B一维条形码的综合教程

Code128B的制作

这是一篇综合教程,以制作Code128B条形码为例,介绍一下使用QT进行C++和QML混合编程。涉及到C++和QML的相互通信、画布Canvas、Flickble的简单使用等,最后介绍一下QT程序的发布。适合初学者哦。

Code128B条形码规则

这个规则不是很难,https://blog.csdn.net/walk_ing/article/details/52712641,这一链接中的介绍很详细,接触过QT的新同学应该也能看明白,原理请大家看这个链接,这里就写下实现的基本原理。
Code128B条形码用到的是ID和Code128B的值还有编码值的对应关系,这样就需要建立两个一维数组,分别存储Code128B和编码值,这两个数组如下:
《制作Code128B一维条形码的综合教程》
《制作Code128B一维条形码的综合教程》
然后根据前面的链接,计算数据位和检验位,把开始位和结束位添加上,就可以得到绘制条形码所需要的bsbsbsbs这种信息。
如果你只需要条形码的生成规则,参考下面的代码,这是包含在项目中的一段代码。

QString input;//这是输入信息,需要制作它的条形码
int length_input = input.length();//长度
QString P_Data = "";//数据位
QString p_Check = "";//检验位
int iCount = 0;
int iCheck = 104;

int i = 0;
int y;
while (i < length_input){ 
    y = 0;
    while(y < 107){ 
        if (input.mid(i , 1) == CB[y])
        { 
            P_Data = P_Data + CD[y];//数据位
            iCheck = iCheck + (i + 1) * y;
            y = 107;
        }else{ 
            y++;
        }
    }
    i++;
}
iCheck = iCheck % 103;//取余
P_Check = CD[iCheck];//获取检验位
QString output = P_StartB + P_Data + P_Check + P_Stop;//到这里,生成的就是所需要的BSBSS这种信息,再然后就画图就行了。

QT中C++与QML的相互通信

笔者刚开始接触QT时,使用的是5.11版本,作为一个业余爱好者,QT的Creater实现是太好用了,会C++的同学上手QT简直不要太简单,后来才接触QML,然后发现使用QML制作界面也是很舒服的说,特别是QT跨平台的特性,使用QML制作一个简单的安卓程序都不用做太复杂的适配。然后问题也来了,C++和QML是两种不同的编写方式,如何做到两者的相互通信,这个问题笔者查询了各种教程,总结出了一个不算太复杂的过程。

新建一个工程项目,选择Qt Quick Application – Empty这一项,然后一路下一步。
《制作Code128B一维条形码的综合教程》
项目建好后,需要建立一个处理类,用于C++和QML的通信,这个类创建好之后,可以保存一下作为模板,以后有新建其他项目的时候,这个类可以直接使用。方法和代码如下:
《制作Code128B一维条形码的综合教程》
在项目上右键,然后添加新文件—>C+±–>C++ Class,笔者一般命名为connect,生成两个文件,connect.h和connect.cpp。然后对这两个文件进行修改。

connect.h

#ifndef CONNECT_H
#define CONNECT_H
#include <QObject>
#include <QDebug>

class connect : public QObject
{ 
    Q_OBJECT

public:
    explicit connect(QObject *parent = nullptr);
    ~connect();

    QString emitMes;//用于传送信息
    
public slots:
    void slot_mesQtoC(QString);//传值,QML to C++

signals:
    void signal_mesQtoC();//传值,QML to C++
    void signal_mesCtoQ(const QString &mesCtoQ);//传值, C++ to QML
};

#endif // CONNECT_H

connect.cpp

#include "connect.h"

connect::connect(QObject *parent)
{ 
   
}
connect::~connect()
{ 
}

void connect::slot_mesQtoC(QString mes)//接收从QML传来的信息
{ 
    qDebug()<<"C++ connect.cpp: "<<mes;
    emitMes = "this info comes from C++";
    emit signal_mesCtoQ(emitMes);//传送信息给QML
}

C++类建好后,下一步是创建C++和QML的联系,这需要在main.cpp中添加一行语句:
main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include <QtQml>//添加包含
#include "connect.h"//添加沟通类


int main(int argc, char *argv[])
{ 
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    qmlRegisterType<connect>("Connect.module",1,0,"Connect");///这一行是最重要的,注意字母大小写是要区分的

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) { 
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

接下来就是在QML中的应用了,看一下注解:
main.qml

import Connect.module 1.0///导入的这一个,就是在main.cpp中添加的一行

ApplicationWindow { ///这里项目新建的时候是Window,此项目中用到了popup,这里改成了ApplicationWindow
    id: win_main
    visible: true
    width: 720
    height: 960
    color: "#eeeeee"
    title: qsTr("Code128B制作")

    //传值控制
    property  string mesQtoC: ""
    Connect{ //这是一个连接
        id: cet
        onSignal_mesQtoC: slot_mesQtoC(mesQtoC)///传值,QML TO C++
    }
    Connections{ 
        target: cet
        /* 这里有两种写法,Qt 5中使用的第一种,Qt 6开始放弃了这种写法,采用直接用函数的参数进行传值 */
        onSignal_mesCtoQ:{ 
            console.log("QML_main qml: " + mesCtoQ)
        }
        /* 这里的写法就是Qt 6中的写法,connect.h和connect.cpp中其他的都不变 * 2021.11.29 function onSignal_mesCtoQ(mesCtoQ){ console.log(mesCtoQ) } */
    }
    Rectanle{ 
        width: 100
        height: 100
        anchors.center: parent
        MouseArea{ 
            anchors.fill: parent
            onClicked:{ 
                mesQtoC = "this info comes form QML"
                cet.onSignal_mesQtoC()///NOTE:此处有问题,当传送的内容不包含回车时,C++接收到的内容是一行,没有问题。但是当文本中包含回车时,C++接收的内容使用qDebug输出时,包含几个回车就会重复输出几次。把同样的内容再传回QML时,使用console.log也会重复输出几次。 
            }
        }
    }
}

写到这里,C++和QML之间的通信就完成了,这几步还是比较容易的,但是传送的内容包含回车的时候,会多传送几次,各位看官可以试一下。

Canvas画布和Flickable

Canvas是QML中用于画图的控件,绘制条形码会用到这个控件,前面生成的bsbsbs这种字符,写一个控制条件,把b画矩形,s不画,最后形成的图像就是一个条形码了。但是笔者在用Canvas绘图时遇到一个问题,诸位在源码中查看具体问题吧。
Flickable是做滚动条用的,笔者在源码中为TextEdit添加了滚动条,引用的原文找不到了,原作者看到了可以@一下。

Flickable{ 
        id: flick_can
        x: 0
        y: 220
        width: parent.width
        height: parent.height - flick.height - 20
        contentWidth: ca.width
        contentHeight: ca.height

        Canvas{ //画布//这个画布的使用比较简单,更为详细的使用参考QT的帮助文档吧
            id: ca
            anchors.top: parent.top
            anchors.left: parent.left
            width: win_main.width
            height: win_main.height * 2
            property int px: 0
            property int py: 0
            property int pw: 0
            property int ph: 0
            onPaint: { 
                var ctx = getContext("2d")//这个是固定的
                ctx.fillStyle = caColor//这个是颜色
                ctx.fillRect(px+50,py,pw,ph)//这个是绘制的坐标
            }
        }
        Rectangle{ //这是一个边框
            anchors.fill: parent
            border.width: 1
            border.color: "#7ecef4"
            color: "transparent"
        }
    }

写到这里后,诸位拼接一下上面的代码就可以绘制出一个完整的条形码了。笔者的源代码中提供了一次绘制多行的方法,诸位看官可以下载试试。

QT程序发布

最后写一下程序发布的过程,初学的朋友们可以看一下。

版本信息

首先我们为程序添加版本信息,我们在源码所在的文件夹中新建一个.txt文件,然后重命名为version.rc,用记事本打开编辑,内容如下:

IDI_ICON1 ICON "c128.ico"

#if defined(UNDER_CE)
#include <winbase.h>
#else
#include <winver.h>
#endif

VS_VERSION_INFO VERSIONINFO
    FILEVERSION 1,0,0,10
    PRODUCTVERSION 1,0,0,10
    FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
    FILEFLAGS VS_FF_DEBUG
#else
    FILEFLAGS 0x0L
#endif
    FILEOS VOS__WINDOWS32
    FILETYPE VFT_DLL
    FILESUBTYPE 0x0L
    BEGIN
        BLOCK "StringFileInfo"
        BEGIN
            BLOCK "080404b0"
            BEGIN
                VALUE "CompanyName", "中国软件股份有限公司\0"
                VALUE "FileDescription", "软件名称\0"
                VALUE "FileVersion", "1.0.0.10\0"
                VALUE "ProductVersion", "1.0.0.10\0"
                VALUE "LegalCopyright", "版权所有 (C) 中国软件股份有限公司\0"
                VALUE "LegalTrademarks", "中国软件股份有限公司\0"
                VALUE "OriginalFilename", "version.exe\0"
                VALUE "ProductName", "软件名称\0"
                VALUE "InternalName", "version.exe\0"
           END
        END

        BLOCK "VarFileInfo"
        BEGIN
            VALUE "Translation", 0x804, 1200
        END
    END

第一行是图标,诸位可以将制作好的图标也放在源码所在的文件夹,然后在版本信息中添加上之后,生成的exe文件就会换成制作的图标了。其他信息随自己更改。然后在工程项目的.pro文件中加上一行

RC_FILE += version.rc//版本的文件名

参考https://www.cnblogs.com/Braveliu/p/4506844.html

程序发布

QT为程序的发布提供了一个工具,可以在开始菜单中找到这个工具。
《制作Code128B一维条形码的综合教程》
首先我们Release模式运行一下做好的项目,然后在项目文件夹下会生成一个项目同名的.exe文件。在QT安装的文件夹下新建一个发布程序专用的文件夹,笔者一般命名为QTRC,将.exe文件复制到这个文件夹下。然后打开命令框工具,使用windeployqt命令来获取发布所需要的各种文件。

需要提一下的是,当程序中不涉及QML文件时,一个windeployqt命令就可以

C:\Qt\Qt5.11.2\5.11.2\mingw53_32>cd c:\qtrc//进入文件夹
c:\QTRC>windeployqt code128.exe//查找文件

如果包含了QML文件,则还需要获取QML运行所需要的文件。方法如下。
笔者项目所在的文件夹是D:\QtProjects\code128

C:\Qt\Qt5.11.2\5.11.2\mingw53_32>windeployqt -qmldir QtProjects\code128 c:\qtrc//exe文件要放在qtrc文件夹中

之后点击.exe文件就可以直接运行了,如果出现错误或是提示缺少文件,可以参考笔者之前写的一篇纠错文章:https://blog.csdn.net/weixin_43193739/article/details/99112169
这时候所带出的文件不一定全部都需要,如果对文件体积有要求的话,可以挨个删除试试。

    原文作者:如来说法
    原文地址: https://blog.csdn.net/weixin_43193739/article/details/110581459
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞