2017-08-09 199 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中。然而,这段代码可能解决了你的问题......