Библиотека сайта rus-linux.net
Программирование с использованием gtkmm 3. Печать
Оригинал: Programming with gtkmm 3Авторы: Murray Cumming, Bernhard Rieder, Jonathon Jongsma, Ole Laursen, Marko Anastasov, Daniel Elstner, Chris Vine, David King, Pedro Ferreira, Kjell Ahlstedt
Дата публикации: 15 Октября 2013 г.
Перевод: А.Панин
Дата перевода: 28 марта 2014 г.
20. Печать
На уровне разрабатываемого приложения API печати gtkmm предоставляет диалоги, которые являются однообразными во всех приложениях и позволяют использовать стандартный API для рисования на основе библиотеки Cairo вместе с системой вывода текста на основе библиотеки Pango. В основе реализации данного обобщенного API лежат специфичные для платформ механизмы и специфичные для принтеров драйверы.
20.1. Объект операции печати PrintOperation
Основным объектом, создаваемым для каждой из операций печати, является объект на основе класса Gtk::PrintOperation
. Для обработки результатов формирования страницы следует устанавливать обработчики для его сигналов или наследовать класс от лежащего в основе данного объекта класса и перекрывать виртуальные обработчики сигналов. Объект операции печати PrintOperation
автоматически обрабатывает все настройки, касающиеся цикла печати.
20.1.1. Сигналы
Gtk::PrintOperation::run()
позволяет начать цикл печати, в процессе которого генерируются различные сигналы:
begin_print
: Вы должны обрабатывать этот сигнал, так как на данном этапе вы должны создать и настроить набор объектов областей вывода текста на основе классаPango::Layout
с помощью передаваемого объекта контекста печати на основе классаGtk::PrintContext
, а также разделить ваш печатаемый документ на страницы.paginate
: Операция разделения документа на страницы может выполняться достаточно медленно, поэтому в том случае, если вы хотите следить за процессом разделения документа на страницы, вы можете осуществить вызов методаGtk::PrintOperation::set_show_progress()
с последующей обработкой данного сигнала.- Для каждой страницы, изображение которой должно быть сформировано, генерируются следующие сигналы:
request_page_setup
: Предоставляет объект контекста печатиPrintContext
, номер страницы и объект настроек страницы на основе классаGtk::PageSetup
. Обрабатывайте этот сигнал в том случае, если вам необходимо модифицировать настройки страниц с доступом к настройками каждой из них.draw_page
: вы должны обрабатывать этот сигнал, предоставляющий объект контекста печатиPrintContext
и номер страницы. Объект контекста печатиPrintContext
должен использоваться для создания контекста Cairo на основе классаCairo::Context
, с помощью которого обрабатываемая страница должна прорисовываться. Для вывода текста следует осуществить обход набора объектов областей вывода текста на основе классаPango::Layout
, который вы создали в рамках обработчика сигнала"begin_print"
.
end_print
: Обработчик данного сигнала является безопасным местом для освобождения любых ресурсов, относящихся к представленной объектом на основе классаGtk::PrintOperation
операции печати. В том случае, если вы используете специальный унаследованный от классаGtk::PrintOperation
класс, обычно проще выполнить описанные действия в дестукторе.done
: Данный сигнал генерируется в момент окончания печати и сообщает о том, что все предназначенные для печати данные были обработаны. Учтите, что передаваемый объект результата печати на основе классаGtk::PrintOperationResult
может сообщать о том, что произошла ошибка. В любом случае, вы, скорее всего, захотите уведомить пользователя о конечном результате операции.status_changed
: Генерируется всегда, когда изменяется статус задачи печати до ее завершения. Следует вызывать методGtk::PrintOperation::set_track_print_status()
для отслеживания состояния задачи после начала печати. Для просмотра статуса следует использовать методget_status()
или методget_status_string()
.
20.2. Настройка параметров страницы
Класс операции печати Gtk::PrintOperation
содержит метод с именем set_default_page_setup()
, который устанавливает стандартный размер бумаги, ориентацию листа и размеры полей. Для показа диалога настройки страницы в вашем приложении следует использовать метод Gtk::run_page_setup_dialog()
, который возвращает объект настроек страницы на основе класса Gtk::PageSetup
, хранящий заданне с помощью диалога настройки. Используйте этот объект для обновления настроек объекта операции печати на основе класса Gtk::PrintOperation
, для доступа к выбранным настройкам размера страницы типа Gtk::PaperSize
и ориентации страницы типа Gtk::PageOrientation
, а также к специфичным для принтера размерам полей.
Вы должны сохранить созданный на основе класса Gtk::PageSetup
объект настроек страницы для того, чтобы иметь возможность использовать его в будущем в том случае, если диалог настроек страницы будет показан снова.
//В рамках класса, унаследованного от класса Gtk::Window и хранящего объекты m_refPageSetup и m_refSettings в качестве дочерних объектов... Glib::RefPtr<Gtk::PageSetup> new_page_setup = Gtk::run_page_setup_dialog(*this, m_refPageSetup, m_refSettings); m_refPageSetup = new_page_setup;
Координатная система Cairo в рамках обработчика сигнала "draw_page"
автоматически поворачивается в соответствии с текущей ориентацией страницы. Она обычно располагается внутри установленных принтером полей, но вы можете изменить ее расположение с помощью метода Gtk::PrintOperation::set_use_full_page()
. Стандартной единицей измерения являются пиксели устройства. Для выбора других единиц измерения используйте метод Gtk::PrintOperation::set_unit()
.
20.3. Вывод текста
Вывод текста осуществляется с помощью библиотеки Pango. Создание объекта области вывода текста на основе класса Pango::Layout
осуществляется с помощью метода Gtk::PrintContext::create_pango_layout()
. Объект контекста печати также предоставляет метрики страницы, которые могут быть получены с помощью методов get_width()
и get_height()
. Количество страниц может быть установлено с помощью вызова метода Gtk::PrintOperation::set_n_pages()
. Для непосредственного вывода текста с помощью библиотеки Pango в рамках обработчика сигналов "on_draw_page"
следует получить контекст Cairo с помощью метода Gtk::PrintContext::get_cairo_context()
и показать текст Pango, представленный объектом на основе класса Pango::LayoutLines
, который появится на странице с заданным номером.
Обратитесь к примеру для ознакомления с реализацией описанного механизма.
20.4. Асинхронные операции
По умолчанию метод Gtk::PrintOperation::run()
возвращает управление тогда, когда операция печати завершается. Если вам необходимо выполнить операцию без блокировки, следует осуществить вызов метода Gtk::PrintOperation::set_allow_async()
. Учтите, что метод set_allow_aync()
не поддерживается на всех платформах, однако сигнал "done"
будет генерироваться в любом случае.
Метод run()
может возвращать результат PRINT_OPERATION_RESULT_IN_PROGRESS
. Для отслеживания статуса и обработки результата выполнения операции печати или ошибки вам придется реализовать обработчики сигналов "done"
и "status_changed"
:
// В рамках метода класса ExampleWindow... Glib::RefPtr<PrintOperation> op = PrintOperation::create(); // ...настройка объекта операции печати... op->signal_done().connect(sigc::bind(sigc::mem_fun(*this, &ExampleWindow::on_printoperation_done), op)); // выполнение операции печати
"status_changed"
. Например, это может быть сделано следующим образом:
void ExampleWindow::on_printoperation_done(Gtk::PrintOperationResult result, const Glib::RefPtr<PrintOperation>& op) { if (result == Gtk::PRINT_OPERATION_RESULT_ERROR) //вывод уведомления для пользователя else if (result == Gtk::PRINT_OPERATION_RESULT_APPLY) //Обновление параметров объекта настроек печати PrintSettings с использованием параметров объекта операции печати PrintOperation. if (! op->is_finished()) op->signal_status_changed().connect(sigc::bind(sigc::mem_fun(*this, &ExampleWindow::on_printoperation_status_changed), op)); }
void ExampleWindow::on_printoperation_status_changed(const Glib::RefPtr<PrintFormOperation>& op) { if (op->is_finished()) //операция печати завершена else //получение статуса операции с помощью метода get_status() или get_status_string() //обновление состояния пользовательского интерфейса }
20.5. Экспорт в файл формата PDF
Glib::RefPtr<Gtk::PrintOperation> op = Gtk::PrintOperation::create(); // ...установка параметров объекта операции печати... op->set_export_filename("test.pdf"); Gtk::PrintOperationResult res = op->run(Gtk::PRINT_OPERATION_ACTION_EXPORT);
20.6. Расширение функций диалога печати
- После установки заголовка вкладки с помощью метода
Gtk::PrintOperation::set_custom_tab_label()
следует создать новый виджет и вернуть соответствующий ему объект из обработчика сигнала"create_custom_widget"
. Скорее всего, вы захотите сделать этот виджет контейнерным для упаковки каких-либо других виджетов. - После работы с диалогом следует получать данные от созданных виджетов с помощью обработчика сигналов
"custom_widget_apply"
.
"custom_widget_apply"
и передает объект виджета, который вы создали ранее, для упрощения кода вы можете сделать виджеты, которые будут участвовать в процессе ввода пользователем каких-либо данных, дочерними виджетами класса. К примеру, предположим, что вы объявили виджет ввода строки на основе класса Gtk::Entry
с именем m_Entry
дочерним виджетом вашего класса CustomPrintOperation
:
Gtk::Widget* CustomPrintOperation::on_create_custom_widget() { set_custom_tab_label("Моя специальная вкладка"); Gtk::Box* hbox = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 8); hbox->set_border_width(6); Gtk::Label* label = Gtk::manage(new Gtk::Label("Введите какой-либо текст: ")); hbox->pack_start(*label, false, false); label->show(); hbox->pack_start(m_Entry, false, false); m_Entry.show(); return hbox; } void CustomPrintOperation::on_custom_widget_apply(Gtk::Widget* /* widget */) { Glib::ustring user_input = m_Entry.get_text(); //... }
Пример в директории examples/book/printing/advanced
демонстрирует описанный подход.
20.7. Предварительный просмотр
// в рамках класса, унаследованного от класса Gtk::Window... Glib::RefPtr<PrintOperation> op = PrintOperation::create(); // ...настройка параметров объекта операции печати... op->run(Gtk::PRINT_OPERATION_ACTION_PREVIEW, *this);
На платформах Unix стандартный механизм предварительного просмотра использует внешнюю программу для просмотра документов. На платформе Windows при этом будет показан стандартный системный диалог предварительного просмотра. В случае необходимости вы можете изменить это поведение и показывать специальный диалог предварительного просмотра. Обратитесь к примеру в директории /examples/book/printing/advanced
.
Следующий раздел : 20.8. Пример.