Что не так с моим обработчиком сигналов?

Я пытаюсь понять, почему мой код выводит «1» при первом вызове из статической основной функции и какое-то явно случайное значение при последующих вызовах из Gtk.Button.

gtkdream.вала:

using GLib;
using Gtk;

public class Main : Object {
    public int pc = 1;

    public Main () {
        var builder = new Builder ();
        builder.add_from_file ("gtkdream.ui");
        builder.connect_signals (this);
        var window = builder.get_object ("window") as Window;
        window.show_all ();
    }

    public void step_clicked () {
        stderr.printf("%d\n", pc);          
    }

    static int main (string[] args) {
        Gtk.init (ref args);
        var app = new Main ();
        app.step_clicked ();
        Gtk.main ();
        return 0;
    }
}

gtkdream.ui:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <object class="GtkWindow" id="window">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="title" translatable="yes">window</property>
    <property name="window_position">center</property>
    <property name="default_width">500</property>
    <property name="default_height">400</property>
    <child>
      <object class="GtkButton" id="step">
        <property name="use_action_appearance">False</property>
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="use_action_appearance">False</property>
        <property name="label" translatable="yes">Schritt ausführen</property>
        <property name="use_underline">True</property>
        <signal name="clicked" handler="main_step_clicked" swapped="no"/>
      </object>
    </child>
  </object>
</interface>

Я использую эту командную строку для ее компиляции:

valac gtkdream.vala --pkg gtk+-3.0 --pkg gmodule-2.0

Что-то не так с подключением сигнала?


person Jens Mühlenhoff    schedule 03.05.2013    source источник


Ответы (1)


Vala не может обеспечить безопасность типов для обратных вызовов, которые автоматически подключаются с помощью GtkBuilder, поэтому вы должны быть осторожны, предоставляя правильное определение. См. раздел Загрузка пользовательского интерфейса из XML-файла в примерах GTK+ на вики Vala. В частности, эта часть:

Внимание: При использовании функции автоматического подключения сигнала Gtk.Builder все обработчики должны иметь полные подписи соответствующих сигналов, включая отправителя сигнала в качестве первого параметра. В противном случае вы получите ошибки сегментации во время выполнения.

Итак, ваш метод должен быть:

public void step_clicked (Gtk.Button button) {
  stderr.printf("%d\n", pc);          
}

Вы можете сделать параметр кнопки обнуляемым, если хотите, чтобы вы все равно могли вызывать его из main(), передав null.

Однако экземпляр все еще находится не в том месте, что также объясняется в этой ссылке:

Если вы хотите, чтобы методы обратного вызова были методами экземпляра, а не статическими, вы должны аннотировать их атрибутом [CCode(instance_pos=-1)] и передать экземпляр в connect_signals(...) вместо null:

Вы передаете экземпляр в connect_signals, но вам не хватает аннотации CCode. Так что на самом деле вы хотите:

[CCode (instance_pos = -1)]
public void step_clicked (Gtk.Button button) {
  stderr.printf("%d\n", pc);          
}
person nemequ    schedule 04.05.2013
comment
Это то, что я получаю от нетерпения... Я вызывал метод из main только из отчаяния, но приятно знать, что аргумент кнопки может быть нулевым. - person Jens Mühlenhoff; 04.05.2013