2016-06-29 5 views
1

Я использую классы QPrinter и QPainter для печати в PDF-файлах с помощью виртуального устройства Windows. Объект QPainter открывает диалоговое окно, в котором можно ввести путь и имя файла PDF.QPainter сбой при печати в PDF с QPrinter

Он работает правильно для намеренного использования. Однако при нажатии кнопки Отмена в диалоговом окне приложение аварийно завершает работу. Вот фрагмент кода, который воспроизводит ошибку:

#include <iostream> 
#include <QApplication> 
#include <QPrinterInfo> 
#include <QPainter> 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 

    foreach(QPrinterInfo printerInfo, QPrinterInfo::availablePrinters()) { 
     if (printerInfo.state() == QPrinter::PrinterState::Error) 
      continue; 

     // Look for the virtual printer device that generates a pdf. 
     if (printerInfo.printerName() == "Microsoft Print to PDF") 
     { 
      QPrinter * qPrinter = new QPrinter(printerInfo, QPrinter::HighResolution); 
      QPainter * qPainter = new QPainter(); 

      // This statement pops up a file selection dialog. 
      // When it is cancelled, the application crashes ... 
      qPainter->begin(qPrinter); 

      // ... and this statement is never reached. 
      std::cout << "Starting printing on the pdf file." << std::endl; 

      // We print some text in the PDF file. 
      qPainter->drawText(100, 100, "Lorem ipsum dolor sit amet, consectetur adipiscing elit."); 
      qPrinter->newPage(); 
      qPainter->drawText(100, 100, "Mauris ut urna eget dui eleifend placerat."); 
      qPrinter->newPage(); 

      // Close the printer and clean-up. 
      qPainter->end(); 
      delete qPrinter; 
      delete qPainter; 
     } 
    } 

    return 0; 
} 

При нажатии на кнопку Отмена сбои приложений во время вызова QPainter :: начать(). Я что-то упускаю? Может ли быть ошибка в этом методе?

Update: защиты вызова QPainter :: начать() с примеркой уловом не помешали аварии:

#include <iostream> 
#include <QApplication> 
#include <QPrinterInfo> 
#include <QPainter> 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 

    foreach(QPrinterInfo printerInfo, QPrinterInfo::availablePrinters()) { 
     if (printerInfo.state() == QPrinter::PrinterState::Error) 
      continue; 

     // Look for the virtual printer device that generates a pdf. 
     if (printerInfo.printerName() == "Microsoft Print to PDF") 
     { 
      QPrinter * qPrinter = new QPrinter(printerInfo, QPrinter::HighResolution); 
      QPainter * qPainter = new QPainter(); 

      // This statement pops up a file selection dialog. 
      // When it is cancelled, the application crashes ... 
      try 
      { 
       qPainter->begin(qPrinter); 
      } 
      catch(...) { } 

      // ... and this statement is never reached. 
      std::cout << "Starting printing on the pdf file." << std::endl; 

      if (qPainter->isActive()) 
      { 
       // We print some text in the PDF file. 
       qPainter->drawText(100, 100, "Lorem ipsum dolor sit amet, consectetur adipiscing elit."); 
       qPrinter->newPage(); 
       qPainter->drawText(100, 100, "Mauris ut urna eget dui eleifend placerat."); 
       qPrinter->newPage(); 
       qPainter->end(); 
      } 

      // Close the printer and clean-up. 
      delete qPrinter; 
      delete qPainter; 
     } 
    } 

    return 0; 
} 
+0

'QPainter :: begin()' возвращает 'bool', вы должны действовать только тогда, когда он возвращает' true'. Проверьте, возвращает ли он «false» при нажатии «отмена», я не тестировал себя, но я сильно подозреваю. –

+0

Кажется, это эта ошибка https://bugreports.qt.io/browse/QTBUG-48488, и вам нужно добавить try catch вокруг метода begin – demonplus

+0

@KarstenKoop авария происходит до начала() заканчивается. – lackadaisical

ответ

0

Попробуйте использовать QPrinter::ScreenResolution вместо QPrinter::HighResolution.

Принтер PDF sets 1200 dpi, что приводит к распределению памяти 500 МБ, что слишком велико с 32-разрядным Qt, тогда сбой происходит в malloc от QImage.

В качестве альтернативы вы можете переключиться на 64 бит Qt. Он все равно будет медленным, но печать прекрасна. Если вы хотите получить более высокий dpi, чем ScreenResolution, вы можете установить его с QPrinter::setResolution(int dpi) примерно на 300.