iOS打印到网络上的打印机

时间:2017-08-09 13:37:09

标签: ios qt printing

我正在尝试制作一款能够自动生成的应用程序"将图片打印到网络上的打印机。我是iOS和Qt的新手,但到目前为止我还没有找到如何进行打印。我找到了一些示例,告诉我如何使用bonjour(https://doc.qt.io/archives/qq/qq23-bonjour.html),我想我可以或多或少地找到这样的打印机,但到目前为止我还没有找到任何关于如何使用QPrinter的帮助自动连接到该打印机。 基本上我的代码到目前为止基本上是:

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();

我认为问题在于我需要以某种方式将设备连接到佳能打印机,但我不知道该怎么做。任何见解将不胜感激:))

干杯!

1 个答案:

答案 0 :(得分: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);
}

如此指定,可以在QML中轻松使用PrinterManager。

整个技巧包括使用PIMPL惯用法编写PrinterManager,即在成员m_Impl中封装类实现。然后,根据您编译代码的平台,您将提供所需的任何PrinterManagerImpl。

除了上面的PrinterManager实现(cpp文件)之外,还需要定义以下mm文件(对于objective-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中。但是,这段代码可能解决了您的问题......