1

2 つのウィンドウを作成しようとしていますFileChooserButtons。最初のものは、ユーザーがディレクトリを選択するのに役立つはずなので、アクション Select_folder を使用しています。2 つ目は、ユーザーがファイルを選択できるようにすることです。

問題は、ユーザーが最初のフォルダーで行った選択に応じて、2 番目のフォルダーを現在のフォルダーに変更したかったことです。

私の最初のアイデアは、次のように 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)

また、valaメーリングリストでのこのメール通信に従って (callback)folder_changed を追加しようとしましたが、役に立ちませんでした。

これはコード全体です:

[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. 余分な、あまり重要ではない点として、ベスト プラクティスは何ですか: 長い行を分割してインデントするか、コード内でそれらを許可するか?

4

1 に答える 1

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コンパイル時に への変換を行います
  • FileChooserButtonfolder_chooserクラスのスコープから削除されました。コールバックに引数として渡されることでアクセスできるようになりました。したがって、コールバック関数のパラメーターとして定義されます
  • FileChooserコールバックのパラメーターが型ではなく型を期待していることに気付くでしょうFileChooserButton。これは、selection_changed信号がthen が実装するFileChooserインターフェイスの一部であるためです。FileChooserButtonこれにより、効果的にFileChooserButton複数のタイプが得られます
  • クラスのスコープ全体で使用できるように宣言されてい_file_chooserますが、アンダースコアを使用してクラス内でのみアクセスできるようにしています。

を使用Signal.connect()すると、Gtk の C API に非常に近くなります。これを行う必要がある場合は、元のコードに基づいて次のように機能します。

[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
  • Vala はインスタンス データを最初のパラメーターとして配置するため、デフォルトをオーバーライドするには、CCode属性を使用する必要があり[CCode( instance_pos = 2 )]ます。
  • シグナルを生成するオブジェクトは、コールバック関数の最初のパラメーターであると想定されるため、この例では使用されていませんが、定義には含まれています。Widgetこれはタイプとして定義されていますが、これを変更して呼び出しFileChooserを使用できますget_uri()

コードのフォーマットに関する質問については、ご覧のとおり、長い行を分割することを好みます。Genie について合意された「ベスト プラクティス」がまだあるかどうかはわかりません。

于 2016-01-09T18:37:18.660 に答える