【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文件還是得自己來生成了,格式什麼的都不在話下,一切都由你掌控!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章