LINUX.ORG.RU

GTK, Callback или я дурак или одно из двух?


0

0

суть такая... есть glade-файл, с диалогом, там есть кнопка, также на этой форме есть виджет GtkTreeView. В глэйде я установил имя колбэк-функции на "clicked" у кнопки и указал параметром колбека имя GtkTreeView виджета.

Дальше я создаю диалог из глейда. Делаю автоконнект сигналов. Собственно в коде есть обработчик на clicked у этой кнопки:

void
on_pref_plugins_configure_button_clicked (GtkButton *conf_button,
gpointer user_data)
{
GtkTreeView *tv;
GtkButton * bt;
printf ("configure button clicked\n");

tv = GTK_TREE_VIEW (user_data);
bt = GTK_BUTTON(conf_button);

return;
}

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

configure button clicked

(gsql:7401): GLib-GObject-WARNING **: invalid cast from `GtkButton' to `GtkTreeView'

(gsql:7401): GLib-GObject-WARNING **: invalid cast from `GtkTreeView' to `GtkButton'


Т.е. получается колбек вызывается с обратным порядком следования параметров. Согласно документации, у меня колбэк описан правильно... но на выходе я имею вот такую картину. Может кто знающий сможет объяснить сей феномен? Или я дурак, или бага в библиотеки глейда, или даже не знаю что еще может быть.

Deleted
Ответ на: комментарий от Deleted

Вот кой чаво нашел, но чуток другое...

http://glade.gnome.org/FAQ


4.5 How do I get a pointer to a widget from within a signal handler?

If you have a pointer to any widget in a window, you can get a pointer to
any other widget in the window using the lookup_widget() function that Glade
provides (in support.c).

You pass it a pointer to any widget in a window, and the name of the widget
that you want to get. Usually in signal handlers you can use the first argument
to the signal handler as the first parameter to lookup_widget(), e.g.

void
on_button1_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *entry1;

entry1 = lookup_widget (GTK_WIDGET (button), "entry1");

...
}


Note that this does not work if you are using libglade. The corresponding
code for libglade would be:

void
on_button1_clicked (GtkButton *button,
gpointer user_data)
{
GladeXML* xml;
GtkWidget* entry1;

xml = glade_get_widget_tree (GTK_WIDGET (button1));
entry1 = glade_xml_get_widget (xml, "entry1");

...
}

Deleted
()

У обработчиков сигналов большинства виджетов при наличие
передаваемого объекта в аргументах происходит инвертирование
аргументов в обратном порядке.

Это нормальное явление. Ты можешь убедиться в этом, в явном
виде сгенерировав код с помощью Glade (такая возможность есть
только в серии 2.x).
Обработчик будет подключаться через g_signal_connect_swapped.

Где-то в документации это описано.

ttnl ★★★★★
()
Ответ на: комментарий от ttnl

А можно для примера еще какиенть виджеты привести? Ладно, предположим, что это так, вот только мне не понятно, какова цель так поганить стек вызова? Если я объявляю колбэк, то я делаю это следуя документации. Если функционал позволяет мне к колбеку прицепить еще какие-то данные, то я этим пользуюсь... Весело получается, это ж получается надо документацию писать в нескольких ипостасьях :) маразм.

Честно говоря, никогда на эти грабли не наступал, странно, хотя вообще-то да, раньше я глейд не юзал, разве что для простенького диалога, безо всяких там ухищрений. А тут ёпрст решил поюзать. Мать его... или их (девелоперов глейда).

Deleted
()
Ответ на: комментарий от Deleted

Я сейчас не вспомню, а посмотреть негде.
Возможно, такое явление происходит лишь с малой частью виджетов.
Навскидку это, например, обработчик key_press_event.
Я могу ошибаться - привык и уже не обращаю внимание.

Если нужно использовать один обработчик одновременно с передачей
объекта в параметрах и без неё, то во втором случае можно
передавать NULL.

ttnl ★★★★★
()

Просто в свойствах сигнала галочка стоит, наверное, чтобы аргументы переупорядочивать. Можно просто .glade файл отредактировать.

welkam ★★
()
Ответ на: комментарий от welkam

там где указывается имя сигнала, есть галочка, но совсем для другого. что же касается какой-то галочки а-ка "глобальная каша в стеке вызова" я не нашел :)

Deleted
()
Ответ на: комментарий от Deleted

При чём здесь каша, это называется connect_swapped, удобно, если нужно методами TreeView обрабатывать события вроде clicked.b

welkam ★★
()

http://www.gnome.org/~newren/tutorials/developing-with-gnome/html/re07.html

Там в example 3:

/* Libglade uses G_CONNECT_SWAPPED when an Object is specified for a
 * signal handler which causes the parameters to be swapped.  This
 * means that the widget that receives the event (where in this case
 * the event is a click) is the second parameter instead of the first,
 * while the first parameter is the Object specified in the xml file.
 */

k_andy ★★★
()
Ответ на: комментарий от Deleted

>>вот вы мне скажите, какая практическая ценность этого? :)

Если есть функция вида user_func (gpointer data),
а указатель на виджет, породивший сигнал, не нужен,
то её тоже можно использовать как обработчик.

Кроме того, функция получает меньше параметров,
возможно, от этого программа быстрее работает.

ttnl ★★★★★
()
Ответ на: комментарий от Deleted

Я могу только предполагать. :) Возможно, таким образом присоединяются методы других объектов.

k_andy ★★★
()
Ответ на: комментарий от k_andy

Вот собсно и само объяснение:

A wrong method to use to connect signals is libglade autoconnection. The reason that it is the wrong method to use is that it tends to make people structure their code in horrible ways. For example, because useful user_data cannot be passed to the signal handlers with autoconnection, people end up using global variables. Also, handler candidates for autoconnection need to be of global scope, which is suboptimal. For large programs, these two issues can cause headaches. Of course, these problems are not very important for small programs, so for such programs this method may make sense. Unfortunately, since all programs start out small, this has led to autoconnection being severely overused.

собсно, ответ найден, тема исчерпана. :)

2 k_andy: спасибо за урлу... прям в 10-ку :).

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.