2017-08-09 153 views
1

我試圖製作一個iOS應用程序,可以「自動」將圖片打印到網絡上的打印機上。我對iOS和Qt相當陌生,但到目前爲止我還無法知道如何進行打印。我發現了一些示例,告訴我如何使用bonjour(https://doc.qt.io/archives/qq/qq23-bonjour.html),我想我可以或多或少地找到像這樣的打印機,但目前我無法找到任何有關如何使用QPrinter自動連接到打印機的幫助。 基本上到目前爲止我的代碼基本上是:iOS打印到網絡上的打印機

QPrinter printer; 
printer.setOutputFormat(QPrinter::NativeFormat); 
printer.setPrinterName("Canon SELPHY CP1200"); 
QPainter painter; 
if(!painter.begin(&printer)) 
{ 
    //failed, we actually hit this at the moment 
    return 1; 
} 
painter.drawText(10, 10, "Test !"); 
painter.end(); 

我認爲問題是,我需要以某種方式將設備連接到我的佳能打印機不知何故,但我不知道該怎麼做。任何洞察力將不勝感激:)

乾杯!

+0

我想你需要在'UIPrintInteractionController'上工作。看看一些例子https://stackoverflow.com/questions/34206207/printing-the-view-in-ios-with-swift – GIJOW

+0

我忘了添加qt標籤,但我希望能用ct直接在C++中使用qt ,如果這是可能的話。我認爲可以混合使用C++和objective-c,但是如果可能的話,我寧願使用一種語言,到目前爲止,已經決定使用C++與qt進行開發。 – Shikamu

回答

1

即使Qt的文檔聲明它的打印API可以在所有平臺上工作, Qt print support,它似乎並不適用於iOS。相反,看起來你需要去UIPrintInteractionController解決方案。這很容易做到。讓我給你一個簡單的例子。讓我假設你選擇Qt的,因爲你希望你的應用程序是便攜式的,並且你有一個專門的類PrinterManager來處理打印在你的框架:

// this is PrinterManager.hpp 
class PrinterManagerImpl; 

class PrinterManager : public QObject 
{ 
    Q_OBJECT 

public: 
    PrinterManager(QObject* a_Parent = Q_NULLPTR); 
    virtual ~PrinterManager(); 

    Q_INVOKABLE void setupPrinter(); 
    Q_INVOKABLE void print(const QString& a_PathToImg) const; 

private: 
    Q_DISABLE_COPY(PrinterManager) 

private: 
    std::unique_ptr<PrinterManagerImpl> m_Impl; 
}; 

與以下實現沿:

// this is PrinterManager.cpp 
#include "PrinterManager.hpp" 
#include "PrinterManagerImpl.hpp" 

#ifndef Q_OS_IOS 
PrinterManager::PrinterManager(QObject* a_Parent) 
    : QObject(a_Parent) 
    , m_Impl(new MyStandardPrinterManagerImpl) // implementation for any case except iOS 
{ } 
#endif 

PrinterManager::~PrinterManager() 
{ } 

void PrinterManager::setupPrinter() 
{ 
    m_Impl->setupPrinter(); 
} 

void PrinterManager::print(const QString& a_PathToImg) const 
{ 
    m_Impl->print(a_PathToImg); 
} 

像這樣指定,PrinterManager可以很容易地在QML中使用。

整個訣竅在於用PIMPL語言編寫PrinterManager,即將類實現封裝在成員m_Impl中。然後,基於您編譯代碼的平臺,您將提供任何PrinterManagerImpl是必需的。

隨着上述PrinterManager實現(CPP文件),您需要定義以下毫米文件(目標C++代碼),其中包含了IOS-具體實施PrinterManager的構造:

// this is PrinterManager.mm 
#import "PrinterManager.hpp" 
#import "IosPrinterManagerImpl.hpp" 

PrinterManager::PrinterManager(QObject* a_Parent) 
    : QObject(a_Parent) 
    , m_Impl(new IosPrinterManagerImpl()) // special iOS implementation 
{ } 

當你編譯這個代碼,考慮mm和cpp文件(如果你按照你的項目的.pro文件下面的建議)。當你爲iOS編譯它時,在cpp文件中找不到構造函數實現。可以在我們定義IosPrinterManagerImpl的mm文件中找到實現。讓我們來看看PrinterManagerImpl:

// this is PrinterManagerImpl.hpp 
class PrinterManagerImpl 
{ 
    public: 
    PrinterManagerImpl() { } 
    virtual ~PrinterManagerImpl() { } 

    virtual void setupPrinter() = 0; 
    virtual void print(const QString& a_PathToImg) const = 0; 

    private: 
    Q_DISABLE_COPY(PrinterManagerImpl) 
}; 

的IosPrinterManagerImpl看起來像這樣(從this videothis advice啓發):

// IosPrinterManagerImpl.hpp 
#import "PrinterManagerImpl.hpp" 
#import <UIKit/UIPrinter.h> 

class QWidget; 

class IosPrinterManagerImpl : public PrinterManagerImpl 
{ 
public: 
    IosPrinterManagerImpl(); 
    virtual ~IosPrinterManagerImpl(); 

    virtual void setupPrinter() override; 
    virtual void print(const QString& a_PathToImg) const override; 

private: 
    UIPrinter* m_Printer; 
    QWidget* m_Dialog; 
}; 

它的實施是

// IosPrinterManagerImpl.mm 
#import "IosPrinterManagerImpl.hpp" 

#import <QApplication> 
#import <QWidget> 
#import <QWindow> 

#import <UIKit/UIPrinterPickerController.h> 
#import <UIKit/UIPrintInteractionController.h> 
#import <UIKit/UIPrintInfo.h> 

IosPrinterManagerImpl::IosPrinterManagerImpl() 
    : PrinterManagerImpl() 
    , m_Dialog(new QWidget(QApplication::activeWindow())) 
{ 
    m_Dialog->setGeometry(0, 0, 100, 100); 
} 

IosPrinterManagerImpl::~IosPrinterManagerImpl() 
{ } 

void IosPrinterManagerImpl::setupPrinter() 
{ 
    // this displays an UI where you can select the printer you want from your local network 
    auto picker = [UIPrinterPickerController printerPickerControllerWithInitiallySelectedPrinter:m_Printer]; 

    if(auto view = reinterpret_cast<UIView*>(m_Dialog->window()->winId())) 
    { 
    [picker presentFromRect:view.bounds inView:view animated:YES 
      completionHandler:^(UIPrinterPickerController* controller, BOOL userDidSelect, NSError* /*err*/) 
      { 
       if(userDidSelect) 
       { 
       m_Printer = controller.selectedPrinter; 
       } 
      } 

    ]; 
    } 
} 

void IosPrinterManagerImpl::print(const QString& a_PathToImg) const 
{ 
    auto printInfo([UIPrintInfo printInfo]); 
    printInfo.jobName = @"Test"; 
    printInfo.outputType = UIPrintInfoOutputPhoto; 

    auto imgUrl([NSURL fileURLWithPath:a_PathToImg.toNSString()]); 
    auto canPrint([UIPrintInteractionController canPrintURL: imgUrl]); 

    auto controller = [UIPrintInteractionController sharedPrintController]; 
    if(controller && canPrint) 
    { 
    controller.printInfo = printInfo; 
    controller.printingItem = imgUrl; 
    // this allows your app to directly print to the selected printer 
    [controller printToPrinter: m_Printer 
       completionHandler: ^(UIPrintInteractionController* /*printCtrl*/, BOOL completed, NSError* err) 
    { 
     if(completed && !err) 
     { 
     qInfo() << "Print successful"; 
     } 
    }]; 
    } 
} 

在你pro文件,您需要按以下方式添加上述objective-C++文件:

ios { 
    OBJECTIVE_SOURCES += $${PRINTERMANAGER_FOLDER}/PrinterManager.mm \ 
    $${PRINTERMANAGER_FOLDER}/IosPrinterManagerImpl.mm \ 
    $${PRINTERMANAGER_FOLDER}/IosPrinterManagerImpl.hpp 
} 

我不是專家的Objective-C++代碼編寫器。例如,我非常肯定你可以以更聰明的方式將setupPrinter()方法中創建的打印機選取器小部件集成到Qt GUI中。然而,這段代碼可能解決了你的問題......