GTK+ в примерах (создание главного меню приложения)

Модератор: Модераторы разделов

Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

GTK+ в примерах

Сообщение sergeyvp »

Здравствуйте!
Согласно статистическим данным очень много людей интересуются созданием меню изучая http://linfoline.homedns.org/gtk/x1716.html
но данный способ считается устаревшим и поэтому решил написать простой пример создания основного меню приложения с использованием менеджера меню http://linfoline.homedns.org/gtk-2.10-refe...kUIManager.html
Для создания меню будет использоваться xml описание в виде отдельного файла menu.xml, хотя xml-описание можно включить непосредственно в код программы.

Пример:

Код:

#include <gtk/gtk.h> // Функция формирования окна верхнего уровня GtkWidget* toplevel_window(); // Функция формирования панели меню GtkWidget* get_main_menu(); // Функция сообщающая об активации пункта меню void action_activate(); int main( int argc, char *argv[] ) { // Обязательный вызов для всех GTK+ программ gtk_init (&argc, &argv); // Создаём окно верхнего уровня GtkWidget *top_window = toplevel_window(); // Создаём основную панель меню GtkWidget *main_menu = get_main_menu(); // Вертикальный контейнер для упаковки панели меню GtkWidget *vbox = gtk_vbox_new(FALSE, 0); // Упаковываем вертикальный контейнер в основное окно gtk_container_add( GTK_CONTAINER(top_window), vbox); // Упаковываем панель меню в вертикальный контейнер gtk_box_pack_start( GTK_BOX(vbox), main_menu, FALSE, FALSE, 2); // Отображаем сформированные виджеты gtk_widget_show( vbox); gtk_widget_show( main_menu); gtk_widget_show( top_window); // Основной цикл GTK+ программ gtk_main (); return 0; } GtkWidget* toplevel_window() { // Создаём новый виджет - окно верхнего уровня GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); // Устанавливаем заголовок окна gtk_window_set_title( (GtkWindow*)window, "Пример создания меню"); // Устанавливаем размер окна по умолчанию в пикселах gtk_window_set_default_size((GtkWindow*)window, 300, 100); // Подключаем обработчик к сигналу delete_event // то есть когда пользователь нажимает кнопку закрытия // в верхнем правом углу окна программы будет вызвана // функция gtk_main_quit для выхода из приложения g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (gtk_main_quit), NULL); return (GtkWidget*)window; } GtkWidget* get_main_menu() { // Менеджер конструирования меню из xml описания GtkUIManager *ui = gtk_ui_manager_new(); // Действие для главных пунктов меню GtkActionGroup *menuactions; // Действие для подпунктов меню GtkAction *action; // Переменная для хранения произошедшей ошибки GError *error = NULL; // Панель меню GtkWidget *menubar; // Новая группа действий основного меню <Файл> menuactions = gtk_action_group_new("FileActions"); // Основное меню <Файл> action = gtk_action_new("FileAction", "Файл", NULL, NULL); // Добавляем действие в группу gtk_action_group_add_action(menuactions, action); // Освобождаем переменную для создания следующего действия g_object_unref (action); // Дополнительное действие выводящее подменю <Создать> action = gtk_action_new("SubMenuAction", "Создать", NULL, NULL); // Добавляем дополнительное действие в группу gtk_action_group_add_action(menuactions, action); // Освобождаем переменную для создания следующего действия g_object_unref (action); // Дополнительное действие выводящее пункт подменю <Новая вкладка> action = gtk_action_new("NewNotebookAction", "Новая вкладка", NULL, NULL); // Подключаем обработчик сигнала активизации меню g_signal_connect_swapped (G_OBJECT (action), "activate", G_CALLBACK (action_activate), "Новая вкладка"); // Добавляем в группу gtk_action_group_add_action(menuactions, action); // Освобождаем переменную для создания следующего действия g_object_unref (action); // Дополнительное действие выводящее пункт <Сохранить> action = gtk_action_new("SaveAction", "Сохранить", NULL, NULL); // Подключаем обработчик сигнала активизации меню g_signal_connect_swapped (G_OBJECT (action), "activate", G_CALLBACK (action_activate), "Сохранить"); // Добавляем в группу gtk_action_group_add_action(menuactions, action); // Освобождаем переменную для создания следующего действия g_object_unref (action); // Дополнительное действие выводящее пункт <Выход> action = gtk_action_new("QuitAction", "Выход", NULL, NULL); // Подключаем обработчик сигнала активизации меню g_signal_connect_swapped (G_OBJECT (action), "activate", G_CALLBACK (gtk_main_quit), NULL); // Добавляем в группу gtk_action_group_add_action(menuactions, action); // Освобождаем переменную для создания следующего действия g_object_unref (action); // Добавляем группу действий в менеджер меню gtk_ui_manager_insert_action_group(ui, menuactions, 0); // Освобождаем переменную для создания следующего действия g_object_unref (menuactions); // Новая группа действий <Вид> menuactions = gtk_action_group_new("ViewMenuAction"); // Основное меню <Вид> action = gtk_action_new("ViewMenuAction", "Вид", NULL, NULL); // Добавляем действие в группу gtk_action_group_add_action(menuactions, action); // Дополнительное действие выводящее пункт <Подменю> action = gtk_action_new("SubMenuViewAction", "Подменю", NULL, NULL); // Добавляем в группу gtk_action_group_add_action(menuactions, action); // Освобождаем переменную для создания следующего действия g_object_unref (action); // Дополнительное действие выводящее пункт <Вид> action = gtk_action_new("ItemSubMenuAction", "Пункт подменю", NULL, NULL); // Подключаем обработчик сигнала активизации меню g_signal_connect_swapped (G_OBJECT (action), "activate", G_CALLBACK (action_activate), "Пункт подменю"); // Добавляем в группу gtk_action_group_add_action(menuactions, action); // Освобождаем переменную для создания следующего действия g_object_unref (action); // Дополнительное действие выводящее пункт <Вид> action = gtk_action_new("ViewAction", "Вид", NULL, NULL); // Подключаем обработчик сигнала активизации меню g_signal_connect_swapped (G_OBJECT (action), "activate", G_CALLBACK (action_activate), "Пункт меню <Вид>"); // Добавляем в группу gtk_action_group_add_action(menuactions, action); // Освобождаем переменную для создания следующего действия g_object_unref (action); // Добавляем группу действий в менеджер меню gtk_ui_manager_insert_action_group(ui, menuactions, 0); // Освобождаем переменную g_object_unref (menuactions); // Формируем меню из xml описания gtk_ui_manager_add_ui_from_file(ui, "menu.xml", &error); menubar = gtk_ui_manager_get_widget( ui, "/menubar"); return menubar; } void action_activate(gchar *action) { // Создаём информационный диалог GtkWidget *dialog = gtk_message_dialog_new( NULL,\ GTK_DIALOG_DESTROY_WITH_PARENT,\ GTK_MESSAGE_INFO,\ GTK_BUTTONS_CLOSE,\ "%s",\ action); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); }


xml-описание нашего меню в виде отдельного файла menu.xml

Код:

<ui> <menubar> <menu name="Файл" action="FileAction"> <menu name="Создать" action="SubMenuAction"> <menuitem name="Новая вкладка" action="NewNotebookAction" /> </menu> <menuitem name="Сохранить" action="SaveAction" /> <separator/> <menuitem name="Выход" action="QuitAction" /> </menu> <menu name="Вид" action="ViewMenuAction"> <menu name="Подменю" action="SubMenuViewAction"> <menuitem name="Пункт подменю" action="ItemSubMenuAction" /> </menu> <menuitem name="View" action="ViewAction" /> </menu> </menubar> </ui>


Скомпилировать пример можно командой
gcc `pkg-config --cflags --libs gtk+-2.0` menu.c -o menu
при условии что вы его поместили в файл menu.c и в вашей системе установлено всё необходимое ;)
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

Кто-бы написал коротенький примерчик с GtkDrawArea, а то я за#хался уже с этим GTK+2
И пример вроде есть перед глазами (правда на Gtk-1.2 и компилился на gcc) и доки (у GTK доки - победитель в номинации "Самая бестолковая и бесполезная документация") - не рисует прямоугольник и хоть тресни.
assert'ы какие-то показывает...

P.S.
Не верю я в разумность разработчиков библиотеки, которые заполнение обычного выпадающего списка реализовали через... меню.
Спасибо сказали:
Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

Re: GTK+ в примерах

Сообщение sergeyvp »

Zeus писал(а):
04.07.2007 18:57
Не верю я в разумность разработчиков библиотеки, которые заполнение обычного выпадающего списка реализовали через... меню.

Так может более "разумными" библиотеками воспользоваться?
У меня ассерты тоже иногда выскакивают, но это вроде помогает решить проблему а не наоборот :)

P/S Это тоже не помогает? http://linfoline.homedns.org/gtk/c2438.html
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

sergeyvp писал(а):
04.07.2007 20:01
Zeus писал(а):
04.07.2007 18:57
Не верю я в разумность разработчиков библиотеки, которые заполнение обычного выпадающего списка реализовали через... меню.

Так может более "разумными" библиотеками воспользоваться?

Какими?

sergeyvp писал(а):
04.07.2007 20:01
У меня ассерты тоже иногда выскакивают, но это вроде помогает решить проблему а не наоборот :)

assert bla-bla-bla !GDK_IS_GC
Хотя код написан "по-мотивам" работавшей программы.
Понятно, что "в консерватории" что-то не так.
Но ЧТО не так - я понять не могу.

sergeyvp писал(а):
04.07.2007 20:01
P/S Это тоже не помогает? http://linfoline.homedns.org/gtk/c2438.html

Вот это должно бы помочь: http://linfoline.homedns.org/gtk/x1749.html
Но... про документацию GTK я уже писал.

Вот это: http://linfoline.homedns.org/gtk/x2486.html я уже читал.
У меня, например, вываливается assert на gdk_pixmap_new если глубину цвета задать -1 (как в примере).

И ещё: я рисую не в обработчиках событий, а прямо в функции, где я собираю все потроха в окно.
Думаю это не должно быть критичным?
А ведь не рисует жеж!
Спасибо сказали:
Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

Re: GTK+ в примерах

Сообщение sergeyvp »

Zeus писал(а):
04.07.2007 20:48
Вот это должно бы помочь: http://linfoline.homedns.org/gtk/x1749.html
Но... про документацию GTK я уже писал.

Так вам и карты в руки http://linfoline.homedns.org/gtk/c1720.html
Разберётесь с виджетом и напишите туториал :)
У меня, например, вываливается assert на gdk_pixmap_new если глубину цвета задать -1 (как в примере).

Так это в GDK документации нужно ответ искать, а не в GTK+.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

sergeyvp писал(а):
04.07.2007 20:59
Zeus писал(а):
04.07.2007 20:48
Вот это должно бы помочь: http://linfoline.homedns.org/gtk/x1749.html
Но... про документацию GTK я уже писал.

Так вам и карты в руки http://linfoline.homedns.org/gtk/c1720.html
Разберётесь с виджетом и напишите туториал :)

Как разбираться-то? В h'никах ковыряться? Константы перебирать?
Зашибись занятие.

sergeyvp писал(а):
04.07.2007 20:59
У меня, например, вываливается assert на gdk_pixmap_new если глубину цвета задать -1 (как в примере).

Так это в GDK документации нужно ответ искать, а не в GTK+.

Это тоже зашибись.
Сел я писать прогу и начинается: ты туда не смотри - ты сюда смотри.

Не удивительно, что Qt более популярно.
Спасибо сказали:
Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

Re: GTK+ в примерах

Сообщение sergeyvp »

Zeus писал(а):
04.07.2007 21:08
Как разбираться-то? В h'никах ковыряться? Константы перебирать?
Зашибись занятие.

Ну я примерно так и делаю :)
Сел я писать прогу и начинается: ты туда не смотри - ты сюда смотри.
Не удивительно, что Qt более популярно.

Ну так за чем дело встало?
Спасибо сказали:
CPU
Сообщения: 41
ОС: Fedora Core 6 x86_64

Re: GTK+ в примерах

Сообщение CPU »

Zeus писал(а):
04.07.2007 18:57
Кто-бы написал коротенький примерчик с GtkDrawArea, а то я за#хался уже с этим GTK+2
..
не рисует прямоугольник и хоть тресни

Zeus, тебе нужен пример просто отрисовки прямоугольника на GtkDrawArea?
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

CPU писал(а):
04.07.2007 22:33
Zeus писал(а):
04.07.2007 18:57
Кто-бы написал коротенький примерчик с GtkDrawArea, а то я за#хался уже с этим GTK+2
..
не рисует прямоугольник и хоть тресни

Zeus, тебе нужен пример просто отрисовки прямоугольника на GtkDrawArea?

Ну да.
Просто последовательность в 15-20 строчек.

sergeyvp писал(а):
04.07.2007 21:17
Zeus писал(а):
04.07.2007 21:08
Как разбираться-то? В h'никах ковыряться? Константы перебирать?
Зашибись занятие.

Ну я примерно так и делаю :)

Я не считаю, что это нормальный режим работы программиста.

sergeyvp писал(а):
04.07.2007 21:17
Сел я писать прогу и начинается: ты туда не смотри - ты сюда смотри.
Не удивительно, что Qt более популярно.

Ну так за чем дело встало?

Qt тоже не устраивает.
Я уже вообще в сторону XLib смотрел!
Но не знаю будет ли оно работать под работающими X'ами.
Ну и кроме собственно рисования сигнала нужна ещё тройка виджетов. А в XLib как я понимаю, их не будет.
Спасибо сказали:
CPU
Сообщения: 41
ОС: Fedora Core 6 x86_64

Re: GTK+ в примерах

Сообщение CPU »

Zeus писал(а):
04.07.2007 22:45
CPU писал(а):
04.07.2007 22:33

Zeus, тебе нужен пример просто отрисовки прямоугольника на GtkDrawArea?

Ну да.
Просто последовательность в 15-20 строчек.


Пойдет?

Код: Выделить всё

#include <gtk/gtk.h>

// функция перерисовки GtkDrawingArea
gboolean draw_area_expose_event(GtkWidget* widget, GdkEventExpose* event){

  //рисуем закрашенный черным прямоугольник, с верхним левым углом в точке (50, 50)
  // и с длинной/шириной, равными 200
  gdk_draw_rectangle(widget->window, widget->style->black_gc, TRUE, 50, 50, 200, 200);

  return TRUE;
}

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

  GtkWidget* window;
  GtkWidget* draw_area;

  //инициализация
  gtk_set_locale();
  gtk_init(&argc, &argv);

  // создаем окно
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_default_size(GTK_WINDOW(window), 300, 300);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_title(GTK_WINDOW(window), "GtkDrawArea example");
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
  gtk_widget_show(window);

  // добавляем GtkDrawingArea
  draw_area = gtk_drawing_area_new();
  gtk_container_add(GTK_CONTAINER(window), draw_area);
  // добавляем обработку события перерисовки GtkDrawingArea
  g_signal_connect(G_OBJECT(draw_area), "expose_event", G_CALLBACK(draw_area_expose_event), NULL);
  gtk_widget_show(draw_area);


  gtk_main();


  return 0;

}


(на всякий случай, в прикрепленном архиве исходник и makefile)
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

Спасибо. Утром попробую.

Опять этот expose_event...
Рисовать что-ли только в event'ах можно?
А просто в main'е код expose_event'а нельзя вписать?
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: GTK+ в примерах

Сообщение d_n_k »

expose-event

This is an event signal, initially emitted when the connected widget becomes fully visible on screen. Every widget can capture expose events; they are even synthesized for widgets that don't have a GdkWindow.

Expose events are also generated when a widget has been partially or fully covered by another widget, and is re-exposed. These events trigger a redraw internally; a GdkWindow that is not currently exposed is not currently drawn, and the same applies to any unexposed area of a window.

Following suit, the most likely reason to connect to an "expose-event" signal is that you have a drawing function in the callback.

See also: "event", GtkDrawingArea, GdkWindow, and the numerous GTK and GDK drawing functions filed under 'Misc'.
все сказанное есть имхо...
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

В общем, резюме:
1. assert'ы не вываливаются.
2. перенёс рисование в main - прямоугольник не появился. Получается рисовать можно только в event'ах. И где это написано?
3. Под g++ всё скомпилилось и работает.
Вопрос только: хранить ВСЁ в виде GtkWidget* - это такой стиль Gtk?
У меня хранятся указатели на те типы данных, коими объекты и являются - везде приведение типов используется и, подозреваю, много assert'ов из-за приведения "не туда" или "не того"...
Ладно, буду дальше эту, с позволения сказать, библиотеку ковырять.
Спасибо за помощь.
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: GTK+ в примерах

Сообщение d_n_k »

Вопрос только: хранить ВСЁ в виде GtkWidget* - это такой стиль Gtk?

да, в gtk все виджеты хранятся как указатели на них.
это всязано с объектной ориентацией gtk.

любой виджет можне создать не только с помощью функции типа gtk_<имя виджета>_new(...)
но и например так gtk_widget_new(GTK_WINDOW_TYPE, <далее идет инициализация свойств>)

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


2. перенёс рисование в main - прямоугольник не появился. Получается рисовать можно только в event'ах. И где это написано?

рисуется в событиях потому что все что рисуется не по событию не отображается. такова архитектура х-сервера.

http://developer.gnome.org/doc/API/2.0/gtk/gtk-General.html
Before using GTK+, you need to initialize it; initialization connects to the window system display, and parses some standard command line arguments. The gtk_init() function initializes GTK+. gtk_init() exits the application if errors occur; to avoid this, use gtk_init_check(). gtk_init_check() allows you to recover from a failed GTK+ initialization - you might start up your application in text mode instead.

Like all GUI toolkits, GTK+ uses an event-driven programming model. When the user is doing nothing, GTK+ sits in the main loop and waits for input. If the user performs some action - say, a mouse click - then the main loop "wakes up" and delivers an event to GTK+. GTK+ forwards the event to one or more widgets.

When widgets receive an event, they frequently emit one or more signals. Signals notify your program that "something interesting happened" by invoking functions you've connected to the signal with g_signal_connect(). Functions connected to a signal are often termed callbacks.

When your callbacks are invoked, you would typically take some action - for example, when an Open button is clicked you might display a GtkFileSelectionDialog. After a callback finishes, GTK+ will return to the main loop and await more user input.


если очень хочется рисовать не по событиям, тогда возвожно 3 пути:
1) генерировать события. те что типа "хочу рисоваться и прямо сейчас"
2) посмотри в дока в сторону умной канвы, которая будет запоминать что ты рисовал и будет это рисовать по событию
3) сделать нормальный виджет, который будет рисоваться сомостоятельно как ему хочется (см п.1), и ты им будешь управлять

самому мне больше нравится 3-й способ, тк рисовать где попало и как попало нужно только графическим редакторам и то не всегда.
примеры собственого виджета
http://www.gtkmm.org/docs/gtkmm-2.4/docs/t...ml/ch25s02.html
http://gtk.org/tutorial/c2182.html


зы: еще посмотри в сторону gtkmm
все сказанное есть имхо...
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

d_n_k писал(а):
05.07.2007 11:35
Вопрос только: хранить ВСЁ в виде GtkWidget* - это такой стиль Gtk?

да, в gtk все виджеты хранятся как указатели на них.
это всязано с объектной ориентацией gtk.

Не, я не про это.
Я держу указатели на объекты в виде GtkButton*, GtkWindow* и т.п.
А где ни посмотрю: и та прога, по мотивам которой я пишу, и примеры - везде виджеты хранятся в GtkWidget*.
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: GTK+ в примерах

Сообщение d_n_k »

:)
это как тебе хочется, так и храни.
почти во всех функциях в качестве виджета принимается GtkWidget*, возможно поэтому автор пример не хочет чтобы компилятор выдавал предупреждения или выполнять преобразования к GtkWidget* явно.
все сказанное есть имхо...
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

Продолжаю "развлекаться" с gtk.
В GtkDrawArea нужно вывести текст (gdk_draw_string).
Функции нужно подсунуть объект "шрифт" GdkFont*
А где его взять?
Вот тут: http://developer.gnome.org/doc/API/2.0/gdk/gdk-Fonts.html всё отмечено как deprecated.

Может кто-нибудь дополнит пример, любезно приведённый выше CPU, выводом текста?

В сторону: неужели под линухами нет ни одной нормальной, лёгкой (во всех смыслах этого слова), хорошо задокументированной графической либы с виджетами?
Спасибо сказали:
CPU
Сообщения: 41
ОС: Fedora Core 6 x86_64

Re: GTK+ в примерах

Сообщение CPU »

Zeus писал(а):
05.07.2007 19:02
Продолжаю "развлекаться" с gtk.
В GtkDrawArea нужно вывести текст (gdk_draw_string).
Функции нужно подсунуть объект "шрифт" GdkFont*
А где его взять?
Вот тут: http://developer.gnome.org/doc/API/2.0/gdk/gdk-Fonts.html всё отмечено как deprecated.

Вместо gdk_draw_layout() используют gdk_draw_layout(), который отрисовывает PangoLayout.



Zeus писал(а):
05.07.2007 19:02
Может кто-нибудь дополнит пример, любезно приведённый выше CPU, выводом текста?


Код: Выделить всё

#include <gtk/gtk.h>

PangoLayout *layout;

// функция перерисовки GtkDrawingArea
gboolean draw_area_expose_event(GtkWidget* widget, GdkEventExpose* event){

  //рисуем закрашенный черным прямоугольник, с верхним левым углом в точке (50, 50)
  // и с длинной/шириной, равными 200
  gdk_draw_rectangle(widget->window, widget->style->black_gc, TRUE, 50, 50, 200, 200);

  //рисуем PangoLayout с левой верхней точкой в (10, 10)
  gdk_draw_layout(widget->window, widget->style->black_gc, 10, 10, layout);

  return TRUE;
}

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

  GtkWidget* window;
  GtkWidget* draw_area;
  //инициализация
  gtk_set_locale();
  gtk_init(&argc, &argv);

  // создаем окно
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_default_size(GTK_WINDOW(window), 300, 300);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_title(GTK_WINDOW(window), "GtkDrawArea example");
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
  gtk_widget_show(window);

  // добавляем GtkDrawingArea
  draw_area = gtk_drawing_area_new();
  gtk_container_add(GTK_CONTAINER(window), draw_area);
  // добавляем обработку события перерисовки GtkDrawingArea
  g_signal_connect(G_OBJECT(draw_area), "expose_event", G_CALLBACK(draw_area_expose_event), NULL);
  gtk_widget_show(draw_area);

  // создаем PangoLayout
  layout = gtk_widget_create_pango_layout(draw_area, "Just an example");
  if(!layout)
    return;

  gtk_main();

  g_object_unref(layout);


  return 0;

}
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

CPU
Спасибо большое. Утром скомпилю-запущу...

Смотрю исходник становится всё кучерявее и кучерявее. Какой-то Pango Layout появился. Всего лишь чтобы текст вывести...
Не, GTK точно наркоманы проектировали!
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

Есть класс "окна".
У него есть статическая функция scaleEvent которую я подвязываю на событие.
В качестве данных передаю указатель на объект класса (чтобы потом вызвать не статическую, а обычную функцию-член класса).

Код: Выделить всё

OscWindow::show ()
{
...
::g_signal_connect (G_OBJECT(scale_adj), "value_changed", G_CALLBACK(OscWindow::scaleEvent), this);
std::cout << "this=" << this << std::endl;
};

gboolean
OscWindow::scaleEvent (GtkWidget* _widget, GdkEvent* _event, gpointer _data)
{
std::cout << "data=" << _data << std::endl;
return reinterpret_cast<OscWindow*>(_data)->_scaleEvent_ (_widget, _event);
};

Так вот в scaleEvent указатель переданный парамтром - не равен this
Как так? :-/
Спасибо сказали:
CPU
Сообщения: 41
ОС: Fedora Core 6 x86_64

Re: GTK+ в примерах

Сообщение CPU »

Zeus писал(а):
09.07.2007 14:24
Так вот в scaleEvent указатель переданный парамтром - не равен this
Как так? :-/

Как проверял? Я пробовал передавать так объекты (через this) - все работало..
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

CPU писал(а):
10.07.2007 00:08
Zeus писал(а):
09.07.2007 14:24
Так вот в scaleEvent указатель переданный парамтром - не равен this
Как так? :-/

Как проверял? Я пробовал передавать так объекты (через this) - все работало..

При попытке передвинуть "бегунок" (который GtKScale) прога падает (segmentation fault).
Статическая функция класса вызывается.
Падает, если пытаться в этой функции разыменовать или получить какой-то иной доступ по указателю, переданному в параметре из "недр" GTK.
Ну а видно, что этот указатель не равен this - просто по выводу в std::cout.
Я в примере эти куски кода и привёл.
Спасибо сказали:
CPU
Сообщения: 41
ОС: Fedora Core 6 x86_64

Re: GTK+ в примерах

Сообщение CPU »

Что-то не то..
Вот, смотри - я переделал пример с отрисовкой квадрата под "ООП-стиль" (сорри за несколько топорную реализацию - сейчас ведь разговор о другом..):

Код:

#include <gtk/gtk.h> #include <iostream> class MyWindow { private: GtkWidget* window; GtkWidget* draw_area; PangoLayout* layout; public: MyWindow(); ~MyWindow(); static gboolean OnExposeEvent(GtkWidget* widget, GdkEventExpose* event, gpointer data); gboolean _OnExposeEvent(GdkEventExpose* event); }; MyWindow::MyWindow(){ // создаем окно window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window), 300, 300); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_title(GTK_WINDOW(window), "GtkDrawArea example"); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show(window); // добавляем GtkDrawingArea draw_area = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(window), draw_area); // создаем PangoLayout layout = gtk_widget_create_pango_layout(draw_area, "Just an example"); // добавляем обработку события перерисовки GtkDrawingArea g_signal_connect(G_OBJECT(draw_area), "expose_event", G_CALLBACK(MyWindow::OnExposeEvent), this); std::cout << "this=" << this << std::endl; gtk_widget_show(draw_area); } gboolean MyWindow::_OnExposeEvent(GdkEventExpose* event){ //рисуем закрашенный черным прямоугольник, с верхним левым углом в точке (50, 50) // и с длинной/шириной, равными 200 gdk_draw_rectangle(draw_area->window, draw_area->style->black_gc, TRUE, 50, 50, 200, 200); //рисуем PangoLayout с левой верхней точкой в (10, 10) gdk_draw_layout(draw_area->window, draw_area->style->black_gc, 10, 10, layout); return TRUE; } gboolean MyWindow::OnExposeEvent(GtkWidget* widget, GdkEventExpose* event, gpointer data){ std::cout << "data=" << data << std::endl; return reinterpret_cast<MyWindow*>(data)->_OnExposeEvent(event); } MyWindow::~MyWindow(){ g_object_unref(layout); } int main(int argc, char* argv[]){ //инициализация gtk_set_locale(); gtk_init(&argc, &argv); MyWindow window; gtk_main(); return 0; }


Как видно из вывода на консоль - указатели одинаковые. И приложение не вываливается в segmentation fault.
Возможно, ошибка где-то в другом месте?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

expose_event и у меня работает.
Не работает (пока с чем столкнулся) "value_changed" для GtkAdjustment'а.
Спасибо сказали:
CPU
Сообщения: 41
ОС: Fedora Core 6 x86_64

Re: GTK+ в примерах

Сообщение CPU »

Может, тогда прикрепишь цельный пример, который падает?
Так лень с нуля писать :)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

Он на работе. С утра прикреплю.

Только, боюсь, если общение с Gtk пойдёт таким путём - я на Qt перейду, пока в прогу ещё не сильно углубился.
Спасибо сказали:
CPU
Сообщения: 41
ОС: Fedora Core 6 x86_64

Re: GTK+ в примерах

Сообщение CPU »

Zeus писал(а):
10.07.2007 01:26
Он на работе. С утра прикреплю.

Только, боюсь, если общение с Gtk пойдёт таким путём - я на Qt перейду, пока в прогу ещё не сильно углубился.


Любой инструмент требует того, чтобы его сначала изучили.. ;)
С другой стороны, каждому свое.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

CPU писал(а):
10.07.2007 01:29
Любой инструмент требует того, чтобы его сначала изучили.. ;)

Согласен. Это, в общем-то, моя первая программа с GUI под линухами.
Но учиться-то по чему?
В Qt - нормальня дока.
А в Gtk...

Хотел, было, на gtkmm.
Ей надо libsigc++. Нашёл. Скомпилил-поставил.
Теперь версия atk не нравится.
Тут я подумал, что это не дело на объектовые компы кучу хрени всякой компилить-гемороиться ради графики на Gtk.
Решил: если не срастётся у меня с "чистым" Gtk, то альтернатива только в виде Qt - её хоть дистрибутив федоры ставит и доки нормальные.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: GTK+ в примерах

Сообщение Zeus »

Вот файл с "проектом".
Если "двинуть" бегунок scale_hscale, то вывалится segmentation_fault и в консоли будет видно, что адреса разные.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
d_n_k
Сообщения: 636
ОС: Gentoo GNU/Linux

Re: GTK+ в примерах

Сообщение d_n_k »

науке неизвестно что находится в стеке в момент вызова функции обработки события

у вас

Код: Выделить всё

...
::g_signal_connect            (G_OBJECT(scale_adj), "value_changed", G_CALLBACK(OscWindow::scaleEvent), this);
...

gboolean
OscWindow::scaleEvent (GtkWidget* _widget, GdkEvent* _event, gpointer _data)
{
    std::cout << "scaleEvent: data="<< _data << std::endl;
    return reinterpret_cast<OscWindow*>(_data)->_scaleEvent_ (_widget, _event);
}


в то время как http://developer.gnome.org/doc/API/2.0/gtk...e-value-changed

The "value-changed" signal

void user_function (GtkRange *range,
gpointer user_data) : Run Last



или для http://developer.gnome.org/doc/API/2.0/gtk...t-value-changed
void user_function (GtkAdjustment *adjustment,
gpointer user_data) : Run First / No Recursion


в вашем случае _data содежит мусор, тк ничто в это место сетека ничего не ложило
все сказанное есть имхо...
Спасибо сказали: