2016-01-09 4 views
1

Я пытаюсь создать окно с двумя FileChooserButtons. Первый должен помочь пользователю выбрать каталог, поэтому я использую действие Select_folder; вторая - позволить пользователю выбрать файл.Синтаксис signal.connect

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

Моя первоначальная идея состояла в том, чтобы использовать Signal.connect, как в строке:

Signal.connect(chooser1, "selection_changed", folder_changed, null) 

Однако это становится мне следующее сообщение об ошибке компиляции:

exercise4_1.gs:62.55-62.68: error: Cannot create delegate without target for instance method or closure 
     Signal.connect(chooser1, "selection_changed", folder_changed, null) 
                 ^^^^^^^^^^^^^^ 
Compilation failed: 1 error(s), 0 warning(s) 

Я также попытался добавить (callback) folder_changed в соответствии с этим mail communication в списке рассылки vala, но безрезультатно.

Это весь код:

[indent=4] 

uses 
    Gtk 
    GLib 

class TestWindow : Window 
    chooser1:Gtk.FileChooserButton 
    chooser2:Gtk.FileChooserButton 
    construct() 

     // General characteristics of the window 
     title = "File chooser" 
     window_position = WindowPosition.CENTER 
     destroy.connect(Gtk.main_quit) 
     chooser1 = new FileChooserButton(
              "Choose a Folder", 
              FileChooserAction.SELECT_FOLDER 
              ) 
     chooser2 = new FileChooserButton(
              "Chooser a Folder", 
              FileChooserAction.OPEN 
              ) 
     chooser1.set_current_folder(Environment.get_home_dir()) 
     chooser2.set_current_folder(Environment.get_home_dir()) 

     Signal.connect(chooser1, "selection_changed", folder_changed, null) 

     var box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0) 
     box.pack_start(chooser1, true, true,0) 
     box.pack_start(chooser2, true, true,0) 
     add(box) 


    def folder_changed() 
     var folder = chooser1.get_filename() 
     chooser2.set_current_folder(folder) 


init 
    Gtk.init (ref args) 
    var test = new TestWindow() 
    test.show_all() 
    Gtk.main() 
  1. Это, конечно, мое отсутствие понимания этого конкретного синтаксиса, но так как я застрял, я был бы признателен за указатель, чтобы получить меня из него.

  2. В качестве дополнительного, менее важного момента, какова наилучшая практика: разделять и отступать длинные строки или разрешать их в коде?

ответ

3

Обратный вызов для Gtk должен включать параметр для объекта, который генерировал сигнал. Также у Genie и Vala есть синтаксическая поддержка сигналов GLib, чтобы облегчить работу с сигналами. Вот пример, основанный на коде:

[indent=4] 
uses 
    Gtk 

class TestWindow:Window 
    _file_chooser:FileChooserButton 

    construct() 
     title = "File chooser" 
     window_position = WindowPosition.CENTER 
     destroy.connect(Gtk.main_quit) 

     var folder_chooser = new FileChooserButton(
             "Choose a Folder", 
             FileChooserAction.SELECT_FOLDER 
             ) 
     folder_chooser.set_current_folder(Environment.get_home_dir()) 
     folder_chooser.selection_changed.connect(folder_changed) 

     _file_chooser = new FileChooserButton(
             "Chooser a File", 
             FileChooserAction.OPEN 
             ) 
     _file_chooser.set_current_folder(Environment.get_home_dir()) 

     var box = new Box(Orientation.VERTICAL, 0) 
     box.pack_start(folder_chooser, true, true, 0) 
     box.pack_start(_file_chooser, true, true, 0) 
     add(box) 

    def folder_changed(folder_chooser_widget:FileChooser) 
     folder:string = folder_chooser_widget.get_uri() 
     _file_chooser.set_current_folder_uri(folder) 

init 
    Gtk.init(ref args) 
    var test = new TestWindow() 
    test.show_all() 
    Gtk.main() 

Несколько пунктов отметить:

  • Имя сигнала, "selection_changed" стал атрибутом folder_chooser который затем connect к. Компилятор Vala делает преобразование в GLib.Signal во время компиляции
  • FileChooserButton, folder_chooser, был удален из сферы действия класса. Теперь к нему обращаются, будучи переданным в качестве аргумента для обратного вызова. Таким образом, он определяется как параметр функции обратного вызова
  • Вы заметите, что параметр для обратного вызова ожидает тип FileChooser, а не тип FileChooserButton. Это связано с тем, что сигнал selection_changed является частью интерфейса FileChooser, который затем реализует FileChooserButton. Это фактически дает FileChooserButton более чем один тип
  • Хотя _file_chooser объявляется так что он доступен в течение всей области видимости класса, это было сделано доступным только в классе, используя подчеркивание

Использование Signal.connect() является гораздо ближе к C API для Gtk.Если вам нужно сделать это, то следующие работы на основе исходного кода:

[indent=4] 
uses 
    Gtk 

class TestWindow:Window 
    chooser1:FileChooserButton 
    chooser2:FileChooserButton 
    construct() 

     // General characteristics of the window 
     title = "File chooser" 
     window_position = WindowPosition.CENTER 
     destroy.connect(Gtk.main_quit) 
     chooser1 = new FileChooserButton(
             "Choose a Folder", 
             FileChooserAction.SELECT_FOLDER 
             ) 
     chooser2 = new FileChooserButton(
             "Chooser a Folder", 
             FileChooserAction.OPEN 
             ) 
     chooser1.set_current_folder(Environment.get_home_dir()) 
     chooser2.set_current_folder(Environment.get_home_dir()) 

     Signal.connect( 
         chooser1, 
         "selection_changed", 
         (GLib.Callback)folder_changed, 
         self 
        ) 

     var box = new Box(Orientation.VERTICAL, 0) 
     box.pack_start(chooser1, true, true, 0) 
     box.pack_start(chooser2, true, true, 0) 
     add(box) 

    [CCode(instance_pos = 2)] 
    // or [CCode(instance_pos = -1)] to always be last 
    def folder_changed(folder_chooser:Widget) 
     folder:string = chooser1.get_uri() 
     chooser2.set_current_folder_uri(folder) 

init 
    Gtk.init(ref args) 
    var test = new TestWindow() 
    test.show_all() 
    Gtk.main() 

Несколько пунктов отметить:

  • Да вы должны бросить обратный вызов GLib.Callback как вы нашли в сообщение электронной почты вы связаны с
  • данных экземпляра вам нужно это Window объекта, который вы создали для FileChooserButton, поэтому изменение null к self работе здесь
  • Вала поместит экземпляр в качестве первого параметра, поэтому для переопределения значения по умолчанию вам необходимо использовать атрибут CCode, то есть [CCode(instance_pos = 2)] в этом случае
  • Объект, генерирующий сигнал, по-прежнему должен быть первым параметром функции обратного вызова, поэтому там, в определении, хотя он не используется в этом примере. Это определяется как Widget типа, но вы можете изменить это FileChooser использовать get_uri() вызов

Для вашего кода форматирования вопроса, который я предпочитаю, чтобы разделить длинные линии, как вы можете видеть. Я не уверен, что для Genie существует согласованная «лучшая практика».