Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Программирование с использованием gtkmm 3. Glade и Gtk::Builder

Оригинал: 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 г.
Перевод: А.Панин
Дата перевода: 10 Апреля 2014 г.

26. Glade и Gtk::Builder

Хотя вы и можете создавать и размещать виджеты на уровне кода на языке C++, довольно скоро это занятие станет утомительным и однообразным. Также в этом случае будет требоваться повторная компиляция приложения для проверки изменений. Приложение Glade позволяет вам размещать виджеты в визуальном режиме с последующим сохранением строкового представления этого размещения в формате XML. После этого ваше приложение сможет использовать API Gtk::Builder для загрузки данных в формате XML из файла во время исполнения и получить указатели на экземпляры классов определенным образом названных виджетов.

Данный подход имеет следующие преимущества:
  1. Требуется меньше кода на языке C++.
  2. Изменения пользовательского интерфейса могут быть оценены достаточно быстро, что дает возможность последовательного совершенствования пользовательских интерфейсов.
  3. Дизайнеры интерфейсов, не обладающие знаниями в области программирования, могут создавать и изменять пользовательские интерфейсы.

Вам все также потребуется код на языке C++ для обработки изменений пользовательского интерфейса, возникающих в результате действий пользователя, но при этом использование объекта типа Gtk::Builder для загрузки строкового представления размещения виджетов позволяет вам сфокусировать внимание на реализации функций обработки именно этих изменений.

26.1. Загрузка файла .glade

Экземпляр класса Gtk::Builder должен использоваться посредством умного указателя типа Glib::RefPtr. Как и в случае всех подобных классов, вам придется использовать метод create() для получения экземпляра. Например, это может быть сделано следующим образом:
Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create_from_file("basic.glade");

Этот вызов позволяет создать экземпляры классов окон, описанных в рамках файла с расширением .glade, хотя эти окна и не будут показаны сразу же в том случае, если вы не использовали соответствующий переключатель в окне "Свойства" приложения Glade.

Для создания экземпляра класса только одного окна или одного из дочерних виджетов, вы можете использовать имя этого виджета в качестве второго параметра метода. Например, это может быть сделано следующим образом:
Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create_from_file("basic.glade", "treeview_products");

26.2. Получение доступа к виджетам

Для получения доступа к виджету, к примеру, для показа диалога с помощью метода объекта виджета show(), следует использовать метод get_widget(), передавая имя виджета. Это имя должно быть задано в окне "Свойства" приложения Glade. В том случае, если необходимый виджет не обнаруживается или имеет отличный тип, в качестве значения указателя будет использовано значение 0.
Gtk::Dialog* pDialog = 0;
builder->get_widget("DialogBasic", pDialog);

В рамках класса Gtk::Builder реализована проверка на соответствие значения указателя нулевому, а также проверка соответствия типа виджета ожидаемому типу с последующим выводом предупреждений в командную оболочку.

Помните о том, что вы не создаете экземпляр класса виджета в ходе вызова метода get_widget(), а просто получаете указатель на уже существующий экземпляр. Вы всегда будете получать указатель на тот же экземпляр класса при вызове метода get_widget() того же объекта на основе класса Gtk::Builder с передачей того же имени виджета. Экземпляры классов виджетов создаются в ходе вызова метода Gtk::Builder::create_from_file().

Метод get_widget() возвращает объекты дочерних виджетов, созданные с использованием метода Gtk::manage() (обратитесь к главе "Управление памятью"), поэтому эти объекты будут уничтожаться при уничтожении объекта родительского контейнерного виджета. Таким образом, в том случае, если вы получаете только дочерний виджет от объекта на основе класса Gtk::Builder вместо получения объекта окна со всеми виджетами, вы должны либо поместить этот виджет в контейнерный виджет, либо уничтожить объект виджета самостоятельно. Объекты окон (таких, как диалоги) не могут находиться под управлением, так как эти виджеты не имеют родительских контейнерных виджетов, поэтому вы должны уничтожать их самостоятельно на каком-либо этапе.

26.2.1. Пример

Данный простой пример демонстрирует методику загрузки созданного с помощью приложения Glade файла с описанием графического интерфейса в процессе работы приложения с последующим доступом к виджетам посредством объекта на основе класса Gtk::Builder.

Исходный код

Файл: main.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

26.3. Использование собственных виджетов

Вы можете использовать приложение Glade для размещения ваших собственных нестандартных виджетов, созданных на основе классов стандартных виджетов gtkmm. Это позволяет вам поддерживать хорошую организацию и инкапсуляцию кода. Конечно же, вы не сможете в точности оценить внешний вид и работать со свойствами вашего нестандартного виджета в Glade, но вы сможете установить его расположение, добавить дочерние виджеты и изменить свойства, объявленные в рамках базового класса виджета из состава gtkmm.

Для этого должен использоваться метод Gtk::Builder::get_widget_derived() подобным образом:
DerivedDialog* pDialog = 0;
builder->get_widget_derived("DialogBasic", pDialog);

Ваш дочерний класс должен иметь конструктор, который принимает указатель на переменную расположенного уровнем ниже типа языка C, а также экземпляр класса Gtk::Builder. Все соответствующие классы gtkmm объявляют типы расположенных уровнем ниже классов языка C как BaseObjectType (класс Gtk::Dialog, к примеру, объявляет тип BaseObjectType с помощью оператора typedef как GtkDialog).

Вы должны вызвать конструктор базового класса из списка инициализации, предоставив указатель на объект языка C. Например, это может быть сделано следующим образом:
DerivedDialog::DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder)
: Gtk::Dialog(cobject)
{
}
Также вы должны провести инкапсуляцию кода для осуществления манипуляций с дочерними виджетами в рамках конструктора дочернего класса, возможно, использовав метод get_widget() или get_widget_derived() снова. Например, это может быть сделано следующим образом:
DerivedDialog::DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder)
: Gtk::Dialog(cobject),
  m_builder(builder),
  m_pButton(0)
{
  //Получение созданного с помощью Glade объекта виджета кнопки и установка обработчика сигналов:
  m_builder->get_widget("quit_button", m_pButton);
  if(m_pButton)
  {
    m_pButton->signal_clicked().connect( sigc::mem_fun(*this, &DerivedDialog::on_button_quit) );
  }
}

26.3.1. Пример

Данный пример демонстрирует методику загрузки файла, созданного с помощью приложения Glade, в процессе работы приложения, а также способ доступа к виджетам, реализованным в рамках дочерних классов.

Исходный код

Файл: deriveddialog.h (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: main.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: deriveddialog.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)


Следующий раздел : Интернационализация и локализация.