The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Каталог документации / Раздел "Программирование, языки" / Оглавление документа

Prev

Up

Home

GTK+ Reference Manual

Next

Основные вопросы

Common Questions Поиск ответов на основные вопросы в руководстве GTK+

Вопросы и ответы

Это перечень ("index") основных вопросов "Как мне сделать..." справочного описания. Если вы не уверены какую документацию вам нужно прочитать для решения вашего вопроса, то данный список хороший способ для начала.

1. Общие вопросы

1.1.

Как мне начать использовать GTK+?

На официальном сайте GTK+ есть обучающая программа и список часто задаваемых вопросов FAQ. Большое количество документации от подобных руководств до сетевых книг (online books) может быть найдено на GNOME developer's site. После изучения этих материалов вы можете вернуться к данному справочному описанию для детального изучения. Перевод на русский язык обучающей программы может быть найден в сети, например на сайте www.opennet.ru

1.2.

Где я могу получить помощь по GTK+, отправить сообщение об ошибке или сделать особенный запрос?

Смотрите раздел Список адресов и сообщения об ошибках.

1.3.

Как я могу перейти от одной версии GTK+ к другой?

Смотрите список несовместимых изменений версии 1.2 от 2.0. А также, GNOME 2.0 porting guide на http://developer.gnome.org для детального обсуждения перехода с версии 1.2 на 2.0. Вы также можете найти дополнительную информацию по этому вопросу в документации по специфичным виджетам и функциям.

Если вы имеете вопрос не затронутый в данном руководстве, не стесняйте спрашивать в списке рассылки и пожалуйста сообщите об ошибках найденных в документации.

1.4.

Как работать с памятью в GTK+? Должен я освобождать данные возвращённые функциями?

Смотрите документацию по GObject и GtkObject. Для GObject специально объявлены g_object_ref() и g_object_unref(). GtkObject это суб класс GObject таким образом применяются те же самые пункты, кроме того он имеет состояние "floating"(разъяснения в его документации).

Строки, возвращенные функциями, будут объявлены "const" (используя G_CONST_RETURN) если они не должны быть освобождены. Строки, не константы, должны быть освобождены при помощи g_free(). Массивы подчиняются те же самым правилам. (Если вы найдете исключение из правил, пожалуйста сообщите на http://bugzilla.gnome.org.)

1.5.

Почему происходит утечка памяти в моей программе, если я закрываю виджет немедленно после его создания?

Если GtkFoo не окно верхнего уровня, то

 foo = gtk_foo_new ();
 gtk_widget_destroy (foo);

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

Чтобы сделать это, вы должны получить ссылку на виджет и пропустить плавающую ссылку (ref and sink в GTK+ манере) после создания:

 foo = gtk_foo_new ();
 g_object_ref (foo); 
 gtk_object_sink (GTK_OBJECT (foo));

Когда вы захотите избавится от виджета, вы должны вызвать gtk_widget_destroy() чтобы прервать любые внешние подключения к виджету перед пропуском вашей ссылки:

 gtk_widget_destroy (foo); 
 g_object_unref (foo); 

Когда вы немедленно добавляете виджет в контейнер, это предполагает начало плавающей ссылки и вам не нужно ни о чём беспокоиться ... только вызвать gtk_widget_destroy() чтобы избавиться от виджета.

1.6.

Как я могу использовать GTK+ с потоками?

Этот вопрос рассмотрен в GDK threads documentation. Смотрите также GThread документацию для портативных потоков примитивов.

1.7.

Как я могу интернационализировать GTK+ программу?

Большинство людей используют GNU gettext, уже установленный вместе с GLib. В UNIX или Linux системах с установленным gettext, в командной строке наберите info gettext для прочтения документации.

Короткий контрольный список о том как использовать gettext: вызов bindtextdomain()- таким образом gettext может найти файлы подключенные к вашему переводу, вызов textdomain()- чтобы установить по умолчанию область перевода, вызов gettext() - для просмотра каждой строки переведенной в области по умолчанию. Традиционно люди для удобства создают макроопределения:

  define  _(x)  gettext (x)
  define N_(x)  x

Вы используете N_() (N заменяет пустую команду) выделяя строки для перевода в контексте, где это не позволяет функциональный вызов gettext(), такой как инициализатор массивов. В конечном счете вы должны вызвать gettext() на строке, чтобы фактически выбрать перевод. _() выделяет строку для перевода и фактический перевод.

Полный код макроопределения выглядит так:

 include <libintl.h>

 define  _(x)  gettext (x)
 define N_(x)  x

 static const char *global_variable = N_("Translate this string");

 static void
 make_widgets (void)
 {
    GtkWidget *label1;
    GtkWidget *label2;

    label1 = gtk_label_new (_("Another string to translate"));
    label2 = gtk_label_new (_(global_variable));
...

Библиотеки использующие gettext должны использовать dgettext() вместо gettext(), которая позволяет им определять область перевода каждый раз когда поступает запрос о переводе. Библиотеки должны также избегать вызова textdomain(), так как они будут определять область перевода вместо использования установленной по умолчанию.Для dgettext() макрос _() может быть определён так:

  define _(x) dgettext ("MyDomain", x)

1.8.

Как я могу использовать не-ASCII символы в GTK+ программах ?

GTK+ использует Unicode (более точно UTF-8) для всех текстов. UTF-8 кодирует каждый Unicode указатель как последовательность одного из шести байт и имеет множество хороших свойств, поэтому это хороший выбор для работы с текстом в программах написанных на языке C:

  • ASCII символы закодированы привычным ASCII codepoints.

  • ASCII символы никогда не появляются как часть другого символа.

  • Нулевой байт не является частью символа, поэтому UTF-8 строками, заканчивающиеся нулём, можно управлять обычными библиотечными функциями С.

Дополнительная информация относительно Unicode и UTF-8 может быть найдена в UTF-8 and Unicode FAQ for Unix/Linux. GLib обеспечивает функции для преобразования строк между UTF-8 и другими кодировками, смотрите g_locale_to_utf8() и g_convert().

Текст полученный из внешних источников (например файлы или пользовательский ввод), должен быть конвертирован в UTF-8 перед тем как направляться в GTK+. Следующий пример перекодирует из IS0-8859-1 контекст полученного файла из stdout:

gchar *text, *utf8_text;
gsize length;
GError *error = NULL;

if (g_file_get_contents (filename, &text, &length, NULL)) 
  {
     utf8_text = g_convert (text, length, "UTF-8", "ISO-8859-1", 
                            NULL, NULL, &error);
     if (error != NULL)
       {
         fprintf ("Couldn't convert file %s to UTF-8\n", filename);
         g_error_free (error);
       }
     else
       g_print (utf8_text);
  }
else 
  fprintf (stderr, "Unable to read file %s\n", filename);

Для строковых констант в исходном коде, есть несколько альтернатив для обработки не-ASCII содержимого:

direct UTF-8

Если ваш редактор и компилятор способны обрабатывать содержимое в кодировке UTF-8, это очень удобно использовать UTF-8 для строковых констант, так как это позволяет вам редактировать строки в режиме "wysiwyg". Заметьте, что эта опция может уменьшить мобильность вашего кода.

escaped UTF-8

Даже если ваш инструментарий не может обработать UTF-8 непосредственно, вы всё же можете закодировать строковые константы в UTF-8 используя для этого escape-последовательности, такие как \212 или \xa8 для кодирования каждого байта. Это мобильно, но сложно для редактирования. Будьте внимательны смешивая escape-последовательности с обычным текстом; "\xa8abcd" длина этой строки равна 1 !

runtime conversion

Если строковые константы могут быть представлены в кодировке поддерживаемой вашим инструментарием (например IS0-8859-1), вы можете создать свой исходный файл в этой кодировке и использовать g_convert() для преобразования строк в UTF-8 во время исполнения. Помните, это требует некоторого дополнительного времени, поэтому вы возможно захотите переместить преобразование из внутренних циклов.

Этот пример демонстрирует три подхода использования знака авторского права © который находится в Unicode и ISO-8859-1 под номером 169 и представлен в UTF-8 двумя байтами 194, 169:

g_print ("direct UTF-8: ©");
g_print ("escaped UTF-8: \302\251");
text = g_convert ("runtime conversion: ©", -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL);
g_print(text);
g_free (text);

1.9.

Как я могу использовать GTK+ с языком C++?

Есть два способа добиться этого. Заголовочные файлы GTK+ используют подмножество C что допустимо для C++, таким образом вы можете просто использовать нормальный GTK+ API в C++ программах. Альтернативно, вы можете использовать "C++ привязку" такую как gtkmm которая обеспечивает C++-native API.

Используя непосредственно GTK+, имейте в виду, что только функции могут подключаться к сигналам, но не методы. Таким образом вам нужно использовать глобальные функции или функции класса "static" для подключения сигналов.

Другая основная проблема непосредственного использования GTK+, в том что C++ будет не явно преобразовывать целочисленное в перечисление. Это происходит когда используется bitfields; в C вы можете написать следующий код:

  gdk_window_set_events (gdk_window, 
                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);

в то время как в C++ вы должны писать так:

  gdk_window_set_events (gdk_window, 
                         (GdkEventMask) GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);

Тем ни менее, очень немногие функции требуют этого приведения.

1.10.

Как мне использовать GTK+ с другими non-C языками?

Смотрите list of language bindings в http://www.gtk.org.

1.11.

Как мне загрузить файл изображения или анимации?

Чтобы загрузить изображение прямо в отображаемый виджет, используйте gtk_image_new_from_file() [1]. Чтобы загрузить изображение для другой цели, используйте gdk_pixbuf_new_from_file(). Для загрузки анимации, используйте gdk_pixbuf_animation_new_from_file(). gdk_pixbuf_animation_new_from_file() может также загружать не анимационные изображения, в комбинации с gdk_pixbuf_animation_is_static_image() загружается файл неизвестного типа.

Для загрузки изображения или анимации асинхронно (без блокирования), используйте GdkPixbufLoader.

1.12.

Как отображать текст ?

Для отрисовки части текста, применяя Pango layout и gdk_draw_layout(), используйте следующий код:

 layout = gtk_widget_create_pango_layout (widget, text);
 fontdesc = pango_font_description_from_string ("Luxi Mono 12");
 pango_layout_set_font_description (layout, fontdesc); 
 gdk_draw_layout (..., layout);
 pango_font_description_free (fontdesc);
 g_object_unref (layout);

Не используйте устаревшие GdkFont и gdk_draw_text().

Смотрите также раздел "Text Handling in GTK 2" в Porting applications to the GNOME 2.0 platform.

1.13.

Как мне узнать размер части текста ?

Чтобы получить размер части текста, применяя Pango layout и pango_layout_get_pixel_size(), используйте следующий код:

 layout = gtk_widget_create_pango_layout (widget, text);
 fontdesc = pango_font_description_from_string ("Luxi Mono 12");
 pango_layout_set_font_description (layout, fontdesc); 
 pango_layout_get_pixel_size (layout, &width, &height);
 pango_font_description_free (fontdesc);
 g_object_unref (layout);

Не используйте устаревшую функцию gdk_text_width().

Смотрите также раздел "Text Handling in GTK 2" в Porting applications to the GNOME 2.0 platform.

1.14.

Почему не регистрируются типы если я использую макрос GTK_TYPE_BLAH ?

Макрос GTK_TYPE_BLAH определён как вызовы gtk_blah_get_type() и _get_type() функции, объявленные как G_GNUC_CONST , которые позволяют компилятору постоянно оптимизировать вызовы если оказывается что значение не используется.

Основа решения этой проблемы заключается в хранении результата во временной переменной, которая препятствует постоянному процессу оптимизации.

volatile GType dummy = GTK_TYPE_BLAH;
2. Какой виджет должен я использовать...

2.1.

...для списков и деревьев?

Смотрите tree widget overview вы должны использовать виджет GtkTreeView. (Список это тоже дерево но без переходов, поэтому можно использовать tree widget и для списков.) Не используйте устаревшие виджеты GtkTree или GtkCList/GtkCTree во вновь создаваемом коде, они менее гибки и приводят к худшему интерфейсу.

2.2.

...для отображения многострочного текста или редактирования?

Смотрите text widget overview вы должны использовать виджет GtkTextView. Не используйте устаревшие виджеты GtkText во вновь создаваемом коде, для избежания множества проблем.

Если вы имеете только небольшой объём текста, GtkLabel может также соответствовать вашим потребностям. Текст можно сделать выделяемым с помощью gtk_label_set_selectable(). Для ввода единичной строки текста смотрите GtkEntry.

2.3.

...для отображения анимации или изображений?

GtkImage может отображать изображения в любом доступном для GTK+ формате. Вы также можете использовать GtkDrawingArea, если вам нужно сделать что-то более сложное, например начертить текст или график поверх изображения.

2.4.

...для представления взаимоисключающих выборов, для чего Windows использовал бы combo box?

Для этого случая рекомендуется использовать GTK+ виджет GtkComboBox. Этот виджет выглядит как combo box или текущеме меню выбора, в зависимости от используемой темы. Если вам нужен редактируемый ввод текста, используйте GtkComboBoxEntry.



3. GtkWidget

3.1.

Как я могу поменять цвет виджета?

Смотрите gtk_widget_modify_fg(), gtk_widget_modify_bg(), gtk_widget_modify_base(), и gtk_widget_modify_text(). Для дальнейшего обсуждения обратитесь в GTK+ resource files. Вы можете также менять цвет в файле настроек, анализируя его с помощью gtk_rc_add_default_file(). Преимущество файла настроек заключается в том, что пользователи могут отменять выбранные вами настройки.

Для изменения цвета фона виджетов, таких как GtkLabel которые не имеют фона, разместите данные виджеты в GtkEventBox и установите цвет фона для контейнера событий.

3.2.

Как поменять шрифт для виджета?

На это существует несколько ответов, в зависимости от того, что конкретно вам нужно. Один из возможных ответов, это gtk_widget_modify_font(). Заметьте, эта функция может использоваться только для изменения размера шрифта, как показано в примере:

 PangoFontDesc *font_desc = pango_font_description_new ();
 pango_font_description_set_size (font_desc, 40);
 gtk_widget_modify_font (widget, font);
 pango_font_description_free (font_desc);

Если вы хотите сделать текст ярлыка большим, используйте gtk_label_set_markup():

gtk_label_set_markup (label, "<big>big text</big>");

Это предпочтительно для многих приложений, потому что размер относителен к размеру шрифта выбранному пользователем. Смотрите g_markup_escape_text() если вы создаёте такие строки на лету.

Вы также можете изменить шрифт поместив

 gtk-font-name = "Sans 30"

в файл настройки и анализируя этот файл с помощью gtk_rc_add_default_file(). Преимущество файла настройки в том, что пользователи могут изменить выбранный вами шрифт. Для дальнейшего изучения смотрите GTK+ resource files.

3.3.

Как я могу отключить/сделать неактивным/нечувствительным виджет?

В GTK+ отключенные виджеты называются нечувствительными ("insensitive"). Смотрите gtk_widget_set_sensitive().



4. GtkTextView

4.1.

Как получить содержимое текстового виджета как например строка?

Смотрите gtk_text_buffer_get_bounds() и gtk_text_buffer_get_text() или gtk_text_iter_get_text().

  GtkTextIter start, end;
  GtkTextBuffer *buffer;
  char *text;

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
  gtk_text_buffer_get_bounds (buffer, &start, &end);
  text = gtk_text_iter_get_text (&start, &end);
  /* use text */
  g_free (text);

4.2.

Как заставить текстовый виджет отобразить его содержимое с использованием определённого шрифта?

Если вы используете gtk_text_buffer_insert_with_tags() с соответствующими тегами для выбора шрифта, вставленный текст будет иметь желательный внешний вид, но текст набранный пользователем до или после вставки блока будет иметь стиль по умолчанию.

Гарантирует внешний вид всего текста использование gtk_widget_modify_font()для изменения шрифта виджета по умоляанию.

4.3.

Как я могу сделать автоматическую прокрутку просмотра текста до конца буфера ?

Отметка (mark) "insert" отмечает точку вставки где gtk_text_buffer_insert() вставила новый текст в буфер. Текст вставленный перед (before) отметкой "insert", вообще остаётся в конце буфера. Если он явно перемещается в другую позицию, например когда пользователь выбирает некоторый текст используя gtk_text_buffer_move_mark(), чтобы установить в желательное положение перед вставкой большего текста. Отметка "insert" буфера может быть получена с помощью функции gtk_text_buffer_get_insert().

Гарантирует видимость конца буфера использование gtk_text_view_scroll_to_mark() , чтобы прокрутить до отметки "insert" после вставки нового текста.



5. GtkTreeView

5.1.

Как можно связать некоторые данные со строкой в дереве?

Запомните, столбцы GtkTreeModel могут не отображаться. Поэтому вы можете поместить данные не видимые для пользователя (non-user-visible) в вашу модель так же как любые другие данные и отыскать их используя gtk_tree_model_get(). Смотрите tree widget overview.

5.2.

Каков эквивалент GtkTreeView gtk_clist_find_row_from_data()?

Как и в GtkTreeModel нет никакого отдельного столбца данных, есть не встроенные функции поиска прохода для данных. Вы можете создать выборочную функцию поиска данных при проходе по дереву, или использовать gtk_tree_model_foreach().

5.3.

Как разместить изображение с некоторым текстом в одном столбце?

Вы можете упаковать больше одного GtkCellRenderer или один GtkTreeViewColumn используя gtk_tree_view_column_pack_start() или gtk_tree_view_column_pack_end(). Так упакуйте оба GtkCellRendererPixbuf и GtkCellRendererText внутрь столбца.

5.4.

Я могу легко установить данные в мои модели GtkTreeStore/GtkListStore используя gtk_list_store_set() и gtk_tree_store_set(), но не могу прочесть их обратно?

И GtkTreeStore, и GtkListStore осуществляют интерфейс GtkTreeModel. Следовательно, можно использовать любую функцию осуществляя этот интерфейс. Наиболее лёгкий путь чтения установленных данных обратно, использование gtk_tree_model_get().

5.5.

Как изменить направление номеров которыми отформатирован GtkTreeView?

Используйте gtk_tree_view_insert_column_with_data_func() или gtk_tree_view_column_set_cell_data_func() и выполните само преобразование номеров строк (например g_strdup_printf()).

Это демонстрируется следующим примером:

enum 
{
  DOUBLE_COLUMN,
  N_COLUMNS
};

GtkListStore *mycolumns;
GtkTreeView *treeview;

void 
my_cell_double_to_text (GtkTreeViewColumn *tree_column,
                        GtkCellRenderer   *cell, 
                        GtkTreeModel      *tree_model,
                        GtkTreeIter       *iter, 
                        gpointer           data)
{
  GtkCellRendererText *cell_text = (GtkCellRendererText *)cell;
  gdouble d;
  gchar *text;

  /* Получить двойное значение из модели. */
  gtk_tree_model_get (tree_model, iter, (gint)data, &d, -1);
  /* Теперь можно самостоятельно форматировать значение. */
  text = g_strdup_printf ("%.2f", d);
  g_object_set (cell, "text", text, NULL);
  g_free (text);
}

void 
set_up_new_columns (GtkTreeView *myview)
{
  GtkCellRendererText *renderer;
  GtkTreeViewColumn *column;
  GtkListStore *mycolumns;

  /* Создаём модель данных и связываем с TreeView */
  mycolumns = gtk_list_store_new (N_COLUMNS, G_TYPE_DOUBLE);
  gtk_tree_view_set_model (myview, GTK_TREE_MODEL (mycolumns));

  /* Создаём GtkCellRendererText */
  renderer = gtk_cell_renderer_text_new ();

  /* Создаём новый столбец имеющий заголовок("Example column"),
   * используем вышеупомянутый renderer который отдаст двойное
   * значение в текст из строк ассоциированной модели. 
   */
  column = gtk_tree_view_column_new ();
  gtk_tree_view_column_set_title  (column, "Example column");
  renderer = gtk_cell_renderer_text_new ();
  gtk_tree_view_column_pack_start (column, renderer, TRUE);

  /* Присоединить новый столбец после предыдущих столбцов GtkTreeView's. */
  gtk_tree_view_append_column (GTK_TREE_VIEW (myview), column);
  /* Так как мы создали столбец вручную, мы можем настроить его как нам
   * нужно, например установить minimum и maximum ширины, и т.д.
   */
  /* Устанавливаем выборочную функцию которую будем вызывать когда содержимое столбца
   * получено. Мы используем func_data pointer как перечень в нашей
   * модели. Это удобно когда используются множественные столбцы списка. 
   */
  gtk_tree_view_column_set_cell_data_func (column, renderer,
                                           my_cell_double_to_text, 
                                           (gpointer)DOUBLE_COLUMN, NULL);
}

5.6.

Как скрыть расширяющие стрелки в моём дереве ?

Установите свойство expander-column в дереве просмотра скрытых столбцов. Смотрите gtk_tree_view_set_expander_column() и gtk_tree_view_column_set_visible().



[1] Если загрузка файла не прошла, gtk_image_new_from_file() не отобразит ни какого изображения для самостоятельного обнаружения неудавшейся загрузки используйте непосредственно gdk_pixbuf_new_from_file(), gtk_image_new_from_pixbuf().




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру