2010-08-10 4 views
2

Я пишу приложение GTK + в C (хотя принцип здесь широко применим), который содержит GtkComboBox. GtkComboBox является частью большей структуры, возвращенной другой функцией и упакованной в главное окно.Возможно ли избежать использования глобальной переменной в этой ситуации?

Я не вижу, как я могу получить значение того, что выбрано в GtkComboBox, кроме как установив глобальную переменную из своей функции обратного вызова. Или есть еще какой-то способ ссылаться на GtkComboBox позже в программе, вне функции, которая его объявила?

Или мне не следует объявлять его внутри функции (кроме main()) в первую очередь?

ответ

1

Если функция, объявляющая переменную стека в C, вернулась, эта переменная больше не существует. Если вам нужен GtkComboBox (или другой объект) упорствовать, у вас есть несколько вариантов:

  • Используйте таНос выделить место для него и пройти вокруг указателя (который должен быть освобожден, когда вам больше не нужно).
  • Использовать глобальную переменную
  • Не используйте обратные вызовы и объявляйте ее во внешней функции и передавайте ее.

Я бы, вероятно, пошел с malloc/pass вокруг подхода указателя, но не могу быть уверен, не зная о вашей ситуации.

+0

Я думаю, что это в основном то, но malloc() меня смущает. GtkComboBox объявляется только как указатель (то есть GtkWidget * combo_box, а затем combo_box = gtk_combo_box_new (...)). Должен ли я использовать malloc() здесь, чтобы увидеть его позже, или GTK + может обрабатывать все это для меня ? – tsvallender

+0

Ах, вот откуда я не знаю из GTK. Если поле со списком уже передано как указатель, вам просто нужно либо сделать ваш указатель глобальным, либо передать указатель на ваши функции. Не нужно «malloc» указатель на указатель. Если вы не можете передать указатель (из-за ограничений параметров функции), вам придется пройти глобальный маршрут. – nmichaels

+0

Это звучит прямо для меня, спасибо большое. – tsvallender

0

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

GtkComboBox *getComboBox() 
{ 
    static GtkComboBox gcb = NULL; 

    if (NULL != gcb) 
    return gcb; 

    // Initialise gcb 
    return gcb; 
} 
4

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

gtk_combo_box_new() использует malloc() внутренне, чтобы выделить указатель, который он возвращает. (Ну, строго говоря, это неправда, но давайте не будем путать здесь.) Таким образом, ваш GtkComboBox будет жив, пока его родительский виджет не будет уничтожен или он не будет удален из его родительского виджета или пока вы его не уничтожите вручную (с помощью gtk_widget_destroy(), не free()). Таким образом, виджет живет в фоновом режиме, но проблема заключается в том, что указатель на него доступен там, где он вам нужен.

Обычно вам нужно манипулировать полем со списком в ответ на сигнал, так как большая часть работы в программе GTK выполняется в обработчиках сигналов. Если это один из собственных сигналов в поле со списком, как и в changed сигнала, то обратного вызова будет зависеть, как это:

void on_combo_box_changed(GtkComboBox *combo_box, gpointer user_data) 

и combo_box будет указатель на комбо-поле.

Если вы хотите, чтобы манипулировать поле со списком в ответ на сигнал другого виджета, скажем clicked сигнала кнопки, а затем обратный вызов будет зависеть, как это:

void on_button_clicked(GtkButton *button, gpointer user_data) 

Как вы можете видеть, есть здесь нет указателя на поле со списком. Здесь находится параметр user_data.Я предполагаю, что вы подключаете свои сигналы в функции, где вы создаете свои виджеты и упаковываете их в основное окно. (Если вы этого не сделаете, вы должны быть.) В этой функции у вас будут указатели на кнопку и доступную поле со списком. Подключите ваш сигнал, как это ...

g_signal_connect(button, "clicked", G_CALLBACK(on_button_clicked), combo_box); 

... проходя combo_box в качестве параметра user_data в g_signal_connect(). Затем указатель на поле со списком будет передан в обратный вызов on_button_clicked(), замаскированный под параметр user_data. Вы можете получить доступ к нему, как это:

void on_button_clicked(GtkButton *button, gpointer user_data) 
{ 
    GtkComboBox *combo_box = GTK_COMBO_BOX(user_data); 
    gint item = gtk_combo_box_get_active(combo_box); 
    etc. 

или, из-за способа стек вызовов работает в C, даже объявив свой обратный вызов, как это:

void on_button_clicked(GtkButton *button, GtkComboBox *combo_box) 

... хотя тогда вы теряете тип проверки проверки, который дает GTK_COMBO_BOX().

Смежные вопросы