【Qt 5.3.2】Qt局域网收银软件(Qt+MySQL+小票打印机(58mm)+普通打印机)

一直想开始写自己的博客,之前都是在学习业内大牛们的博客,目前这点渣技术也是从大牛们的博客中汲取消化而来的,但是由于各种事儿比较多(就是懒),也苦于找不到一个感兴趣又写的来的话题,就拖到了现在,刚好最近接了个私活儿,客户的需求简单来说就是一个局域网的收银软件,需要打印小票(58mm),并且每个月末需要打印出每个客户本月的所有订单(A4),之前也写过类似的收银软件,但是这次跟以前的都不一样,这次首先是需要局域网使用,所以首先就得选择合适的数据库,平时为了方便,大小软件都用SQLITE,因为实在是太方便了,不用编译库,不用安装额外的数据库,轻量级…貌似有点儿跑题了(←_←),言归正传,其实一开始也是想用SQLITE的,也可以支持局域网操作,当然,SQLITE本身是不支持局域网访问的,但是可以通过共享文件夹来使得局域网电脑可以访问到文件,当然也就可以访问到数据库了,网上查了半天资料,又发现一个严重的问题,多用户操作数据库时,可能会同时访问到数据库文件,而由于SQLITE本身特有的工作原理,每次执行SQL语句时都会有打开和关闭文件的过程,so,如果多用户访问的话可能会出问题,于是想了半天,准备用守护进程+消息队列这种模式来解决这个问题,于是准备先写个在放数据库的主机上的守护进程,写啊写,写了半天,突然惊醒,想给自己一巴掌,这特么还用自己写么?你丫SB了吧!直接装个MySQL不就行了,人家把这些都帮你做好了,你还在这自己写个毛啊,能有人家专业的写的效率高不成,就这样,本着不浪费资源的精神,前面所做的工作归零,又从头开始,首先是下载MySQL,选择合适的版本下载安装,具体的安装过程可以参见mysql 5.6安装图解,版本不同可能会略有差异,不过这都不重要,具体安装过程就不多说了,各位碰到问题的话可以再找找资料,我的安装过程也是比较坎坷,安装卸载了好几次,后来发现其实第一次已经装好了…
装完以后,还得配置下,使得MySQL可以在局域网中访问,具体过程见《如何设置mysql在局域网中访问》,这个配置完了以后,MySQL就可以先放下了,然后就开始coding,几个小时后,除了打印账单,打印小票,界面这些(貌似也没有其他的了吧(←←),其他的已经写好了,然后由于之前没有接触过小票打印机,最多是在超市买东西见过。。。,上某宝买了个小票打印机(后来客户给报销了,某宝果然方便了我等屌丝),几天后收完快递搬回宿舍,宿舍的弟兄们都惊呆了,纷纷以为我要开超市,我赶紧解释我不开超市><,玛德我倒是想开,你给我赞助啊,然后每次有人来宿舍我就得解释下(T_T),说多了都是泪,不说这些了,说下后面遇到的主要问题以及解决方案吧,小票打印机回来后,装完驱动,小本本上就多了个新设备,然后就可以愉快的打印小票了,操作起来和一般的打印机并没有什么区别,打印小票也和平时在word里边打印文档没有什么区别,重要的是自己写软件使用小票打印机打印时,文档的大小尤其是宽度一定得设置合适了,具体见下面代码,
`

    /*
    **由于软件中会使用到两种打印机(票据打印机&普通打印机)
    **所以不能都使用默认打印机来打印,我设置普通打印机为默认打印机
    **然后在Qt中创建printer对象的时候,对应的打印机其实是默认的
    **普通打印机,于是我加了个配置文件,用户在初次使用软件打印小票
    **时,会弹出一个界面,让用户选择小票打印机,然后将这个打印机的
    **名字存到setting.ini文件中,之后运行时就从文件中读取小票打印机
    **的名称,这样就可以愉快的使用两种打印机了
    **
    */
    QPrinter printer(QPrinter::HighResolution);
    //如果是首次运行程序,先选择小票打印机,并生成配置文件
    if(printer_name_58.isEmpty()||paper_name_58.isEmpty())
    {
        QPrintDialog d(this);
        if(QDialog::Rejected==d.exec())
            return;
        printer_name_58=d.printer()->printerName();
        paper_name_58=d.printer()->paperName();

        QFile file("setting.ini");
        file.open(QIODevice::WriteOnly|QIODevice::Text);
        file.write((printer_name_58+"&&"+paper_name_58).toLatin1());
        file.close();
    }

    //选择小票打印机
    printer.setPrinterName(printer_name_58);
    //由于默认打印机不是小票打印机,所以纸张大小在设置了打印机后
    //还是A4,就会导致打印出来边距什么的都不正确,随便设置一个小
    //票打印机不支持的纸张大小,printer就会自动的选择小票打印机
    //默认的纸张大小,这样打印出来边距就正常了,这应该是Qt的一个Bug
    printer.setPaperName(paper_name_58);

    //貌似没什么用,不过我还是设置了下
    printer.setFullPage(true);

    //计算在打印机的DPI下,58mm对应的点数
    int dpi=printer.logicalDpiX();
    int width=58*(dpi*1.0/25.4);//58mm

    //我一般打印什么的喜欢用html来布局,因为Qt自带的QDocument
    //效果感觉一般,而且也不如html好控制

    //使用QWebPage来解析并输出解析后的文档到打印机
    QWebPage page;
    page.mainFrame()->setHtml(html);

    QWebFrame *frame=page.mainFrame();
    frame->setTextSizeMultiplier(1.4);

    //设置网页视口大小,因为我在html文档中用相对大小布局的
    page.setViewportSize(QSize(width,frame->findFirstElement("table").geometry().height()));

    //将网页通过painter打印出来
    QPainter painter(&printer);
    frame->render(&painter);

`上面就是小票打印部分的代码,具体的html代码就不贴了

说完了小票打印,再来说说客户账单的打印,这个跟上面的不太一样,因为涉及到分页什么的,而我又懒得自己处理复杂的分页,所以在此本着充分使用已有软件功能的精神,使用COM接口调用word来帮我实现这个功能,其实说来也简单,上面也说了,我一般喜欢使用html来进行布局,所以,在这里也是不例外,依然是用html table来控制报表格式,最后输出到一个html文档,直接用word打开这个html文件,就可以愉快的看着强大的word帮我们处理好分页信息了,然后在调用word的打印功能就OK了(PS:偷懒真是人类进步的阶梯啊(^_^))下面上代码:

    //软件启动时
    word=new QAxObject("Word.Application");

    此处略去1w行代码...

    //下面是打印函数
    QAxObject *docs = word->querySubObject("Documents");
    //filename就是生成的html文件名,注意得用**绝对路径**!!
    docs->dynamicCall("Open (const QString&)", filename);
    word->dynamicCall("PrintOut ()");
    docs->dynamicCall("Close (Boolean)", false);
    //打印函数结束

    //记得退出软件时调用接口关闭winword进程
    word->dynamicCall("Quit (void)");

绝对简单,绝对靠谱!当然具体的html文件还是得自己来生成了,格式什么的都不在话下,一切都由你掌控!

你可能感兴趣的:(Qt,Qt,小票,收银,打印机,局域网)