Каждый разработчик знает, как неожиданно сложной становится печать, когда макет «плывёт», шрифты выглядят иначе, а один и тот же код ведёт себя по-разному на разных платформах. Сталкивались ли вы с ощущением, что вывод на печать — это отдельный мир со своими ловушками?
Эта глава постепенно раскрывает, почему печать в Qt на самом деле проще, чем кажется, и где именно кроется ключевая идея, снимающая до 80 % типичных проблем. Здесь вы обнаружите, как единый механизм рисования избавляет от дублирования логики.
Будет показано, как один и тот же код работает для экрана, принтера и PDF, какие 5 ключевых настроек реально влияют на результат, и как корректно управлять страницами, ориентацией и масштабированием — без «магических чисел» и хакающих решений.
После этой главы подход к печати меняется навсегда: от хаотичных экспериментов — к контролируемому и предсказуемому результату. Пропустить её — значит продолжать решать уже решённые проблемы.
В этой главе вы найдёте готовые к использованию примеры кода.
Самопроверка по главе
Почему класс QPrinter унаследован от QPaintDevice и как это упрощает задачу разработчика?Ответ
Правильный ответ: Благодаря наследованию от QPaintDevice печать работает как обычное рисование — для вывода на принтер используются те же методы QPainter, что и для экрана, что устраняет необходимость изучать отдельный API для печати.
Зачем в проектном файле нужно явно подключать модуль QtPrintSupport?Ответ
Правильный ответ: Классы печати (QPrinter, QPrintDialog) находятся в отдельном модуле QtPrintSupport, который не включен по умолчанию, поэтому его необходимо добавить через QT += printsupport или target_link_libraries в CMake.
Что произойдет, если передать пустую строку в метод setOutputFileName()?Ответ
Правильный ответ: Система проигнорирует перенаправление вывода в файл, и печать будет осуществлена на физическое печатающее устройство вместо сохранения в файл.
Как перенаправить вывод печати в PDF-файл вместо отправки на принтер?Ответ
Правильный ответ: Нужно вызвать метод setOutputFormat() со значением QPrinter::PdfFormat и указать имя выходного файла через setOutputFileName() — это создаст PDF-документ вместо отправки на физический принтер.
Почему необходимо вызывать метод viewport() перед началом рисования при печати?Ответ
Правильный ответ: Большинство принтеров не могут использовать всю площадь листа для печати, поэтому viewport() возвращает доступную для печати прямоугольную область, что позволяет избежать вывода за пределы печатаемой зоны.
Зачем нужен метод setFontEmbeddingEnabled() и когда его следует использовать?Ответ
Правильный ответ: Метод внедряет шрифты в документ, гарантируя, что файл содержит все необходимые шрифты; это полезно при использовании файлов на других платформах, где нужных шрифтов может не быть установлено.
Какую комбинацию методов нужно использовать для установки альбомной ориентации и печати трех копий?Ответ
Правильный ответ: setPageOrientation(QPageLayout::Landscape) для альбомной ориентации и setCopyCount(3) для установки количества копий.
Почему в примере кода используется std::unique_ptr для объекта QPrinter?Ответ
Правильный ответ: Это соответствует принципу RAII и автоматически освобождает память при уничтожении объекта, избавляя от необходимости явного удаления в деструкторе и снижая риск утечек памяти.
Зачем передавать указатель на родительский виджет во второй параметр конструктора QPrintDialog?Ответ
Правильный ответ: Это позволяет диалоговому окну быть отцентрированным относительно основного окна приложения, обеспечивая лучшую пользовательскую навигацию.
Как вычислить количество страниц для печати после того, как пользователь выбрал диапазон в диалоге печати?Ответ
Правильный ответ: Нужно вычесть fromPage() из toPage() и прибавить единицу: int nPages = dlg.toPage() – dlg.fromPage() + 1.
Что произойдет, если забыть вызвать newPage() при печати многостраничного документа?Ответ
Правильный ответ: Все содержимое будет нарисовано на одной странице поверх друг друга, так как newPage() необходим для создания новой страницы в задании печати перед продолжением рисования.
Какие три ключевых метода класса QPrinter позволяют управлять цветностью, размером листа и диапазоном страниц?Ответ
Правильный ответ: setColorMode() для управления цветным/черно-белым режимом, setPageSize() для изменения размера листа через объект QPageSize, и setFromTo() для задания диапазона печатаемых страниц.
Практические задания
Простой уровень
Приложение для печати визитной карточки
Создайте Qt-приложение с кнопкой “Напечатать визитку”, которое выводит на печать простую визитную карточку с вашим именем, должностью и контактной информацией. Используйте разные размеры шрифтов и цвета для оформления текста. Добавьте декоративную рамку вокруг визитки.
Подсказки: Подключите модуль QtPrintSupport в проектном файле. Создайте QPrinter и используйте QPainter для рисования на нем. Используйте метод viewport() для получения области печати. Примените drawRect() для рамки, setFont() для разных размеров текста и drawText() с флагами выравнивания. Откройте диалог печати через QPrintDialog перед выводом.
Средний уровень
Генератор отчетов с выбором формата вывода
Разработайте приложение, которое создает простой отчет с заголовком, датой создания, таблицей данных (3-4 строки) и итогами. Пользователь должен иметь возможность выбрать, куда выводить отчет: на принтер или сохранить в PDF-файл. Реализуйте переключатель режимов (радиокнопки) и программную настройку ориентации страницы в альбомный режим для более удобного размещения таблицы.
Подсказки: Используйте QRadioButton для выбора режима вывода. При выборе PDF используйте setOutputFormat(QPrinter::PdfFormat) и setOutputFileName(). Для альбомной ориентации примените setPageOrientation(QPageLayout::Landscape). Рисуйте таблицу через drawLine() и drawText(). Создайте отдельный метод для рисования отчета, который можно использовать как для печати, так и для PDF.
Сложный уровень
Многостраничный фотоальбом с компоновкой
Создайте приложение для печати фотоальбома: пользователь выбирает несколько изображений (минимум 6), и программа автоматически размещает по 2 изображения на каждой странице с подписями под ними. На первой странице должна быть обложка с названием альбома и датой создания. Реализуйте масштабирование изображений с сохранением пропорций, добавьте нумерацию страниц в нижний колонтитул. Предусмотрите возможность печати в цветном или черно-белом режиме.
Подсказки: Используйте QFileDialog для выбора нескольких изображений. Загружайте их через QImage. Организуйте цикл по страницам с вызовом newPage() для каждой новой страницы после первой. Масштабируйте изображения методом scaled() с флагом Qt::KeepAspectRatio. Рассчитайте позиции для размещения двух изображений на странице (верхняя и нижняя половины с учетом отступов). Для обложки используйте крупный шрифт по центру. Для нумерации страниц используйте счетчик в цикле и drawText() в углу страницы. Добавьте QCheckBox для выбора цветного/черно-белого режима и применяйте setColorMode().
💬 Присоединяйтесь к обсуждению!
Разобрались с выводом на печать в Qt? Возникли вопросы по настройке QPrinter или организации многостраничной печати?
Поделитесь своим опытом работы с генерацией PDF, расскажите о нестандартных задачах печати или помогите другим читателям освоить материал главы!