signal.connect 语法
The signal.connect syntax
我正在尝试用两个 FileChooserButtons
创建一个 window。第一个应该帮助用户选择一个目录,因此我正在使用操作 Select_folder;第二个是允许用户选择一个文件。
问题是我希望第二个根据用户在第一个中所做的选择更改当前文件夹。
我最初的想法是使用 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 邮件列表中按照此 mail communication 添加(回调)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 ()
这当然是我对这种特殊语法缺乏理解,但由于我被卡住了,我将不胜感激,请给我一个指导,让我摆脱它。
另外,不太重要的一点是,最佳做法是什么:拆分和缩进长行还是允许它们出现在代码中?
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
已从 class 的范围中删除。现在通过将其作为参数传递给回调来访问它。所以定义为回调函数的参数
- 您会注意到回调参数需要
FileChooser
类型而不是 FileChooserButton
类型。这是因为 selection_changed
信号是 FileChooserButton
随后实现的 FileChooser
接口的一部分。这有效地给出了 FileChooserButton
不止一种类型
- 虽然
_file_chooser
被声明为在 class 的整个范围内可用,但它已通过使用下划线[=56= 使其只能在 class 内访问]
使用 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
,正如您在链接到的邮件消息中找到的那样
- 您需要的实例数据是您为
FileChooserButton
创建的 Window
对象,因此将 null
更改为 self
在这里有效
- Vala 会将实例数据作为第一个参数,因此要覆盖默认值,您必须使用
CCode
属性,在本例中为 [CCode( instance_pos = 2 )]
- 生成信号的对象仍然应该是回调函数的第一个参数,所以它在定义中就在那里,尽管它在这个例子中没有被使用。这被定义为
Widget
类型,但您可以将其更改为 FileChooser
以使用 get_uri()
调用
对于您的代码格式问题,我更喜欢拆分长行,如您所见。我不确定是否已经就 Genie 达成一致 "best practise"。
我正在尝试用两个 FileChooserButtons
创建一个 window。第一个应该帮助用户选择一个目录,因此我正在使用操作 Select_folder;第二个是允许用户选择一个文件。
问题是我希望第二个根据用户在第一个中所做的选择更改当前文件夹。
我最初的想法是使用 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 邮件列表中按照此 mail communication 添加(回调)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 ()
这当然是我对这种特殊语法缺乏理解,但由于我被卡住了,我将不胜感激,请给我一个指导,让我摆脱它。
另外,不太重要的一点是,最佳做法是什么:拆分和缩进长行还是允许它们出现在代码中?
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
已从 class 的范围中删除。现在通过将其作为参数传递给回调来访问它。所以定义为回调函数的参数- 您会注意到回调参数需要
FileChooser
类型而不是FileChooserButton
类型。这是因为selection_changed
信号是FileChooserButton
随后实现的FileChooser
接口的一部分。这有效地给出了FileChooserButton
不止一种类型 - 虽然
_file_chooser
被声明为在 class 的整个范围内可用,但它已通过使用下划线[=56= 使其只能在 class 内访问]
使用 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
,正如您在链接到的邮件消息中找到的那样 - 您需要的实例数据是您为
FileChooserButton
创建的Window
对象,因此将null
更改为self
在这里有效 - Vala 会将实例数据作为第一个参数,因此要覆盖默认值,您必须使用
CCode
属性,在本例中为[CCode( instance_pos = 2 )]
- 生成信号的对象仍然应该是回调函数的第一个参数,所以它在定义中就在那里,尽管它在这个例子中没有被使用。这被定义为
Widget
类型,但您可以将其更改为FileChooser
以使用get_uri()
调用
对于您的代码格式问题,我更喜欢拆分长行,如您所见。我不确定是否已经就 Genie 达成一致 "best practise"。