#c #callback #gtk #widget
#c #обратный вызов #gtk #виджет
Вопрос:
Практически в каждом примере кода GTK , который я видел до сих пор, все виджеты графического интерфейса определены внутри функции main. Сначала я принял это, но затем обнаружил, что это очень неудобно, например, при управлении несколькими виджетами из одной функции обратного вызова. Конечно, я мог бы просто использовать для этого gpointer ‘data’, но разве мне не нужно было бы сначала обернуть каждый виджет, которым я хочу манипулировать, в какую-то структуру, чтобы передать его в качестве аргумента ‘data’?
В любом случае, чтобы не быть связанным этим, я только начал определять все виджеты вне основной функции, поэтому я могу легко получить к ним доступ по всем функциям. Есть ли какие-либо недостатки у этого стиля?
Ответ №1:
Недостатки те же, что и при использовании любой глобальной переменной. На этой странице представлен хороший обзор ситуаций, когда не следует (и когда следует) использовать глобальные переменные. Если вы посмотрите ближе к низу, вы увидите раздел «Действительно плохие причины для использования глобальных переменных»:
Я не хочу постоянно передавать его.
Боюсь, это похоже на то, как звучит ваше возражение. Однако, как также упоминается на странице, на которую я ссылался, если вы просто пишете короткие или одноразовые программы, то простота использования глобальных переменных, вероятно, перевешивает недостатки.
Обычный способ в программах среднего размера — создать структуру, заполнить ее main()
и передать обратным вызовам:
typedef struct {
GtkWidget *window, *button, *textfield;
} Widgets;
int main(int argc, char **argv) {
gtk_init(amp;argc, amp;argv);
Widgets *w = g_slice_new0(Widgets);
w->window = gtk_window_new(... etc...
...
g_signal_connect(w->button, "clicked", G_CALLBACK(on_clicked), w);
...etc...
gtk_main();
g_slice_free(Widgets, w);
return 0;
}
В больших программах лучшим способом является создание собственных классов, представляющих основные окна, диалоговые окна настроек и т. Д., И передача этих классов различным обратным вызовам.
Комментарии:
1. Спасибо за ответ! Я думаю, в конце концов, самый простой способ сделать обе стороны счастливыми — это, как вы и предлагали, поместить каждый виджет с самого начала в одну большую структуру, а затем передавать ее каждый раз. (Хотя, что делать, если мне нужны как виджеты, так и идентификатор обработчика сигналов? Похоже, что виджеты всегда будут блокировать ‘gpointer userdata’)
2. Ничто не мешает вам также ввести идентификатор обработчика сигналов в структуру.