signal.connect语法 [英] The signal.connect syntax
问题描述
我试图用两个 FileChooserButtons
创建一个窗口。第一个应该可以帮助用户选择一个目录,因此我使用的是Select_folder操作;第二个是允许用户选择一个文件。
问题在于我想让第二个文件夹根据用户在第一个文件夹中所做的选择更改当前文件夹。
我最初的想法是使用Signal.connect,如下所示:
Signal.connect(chooser1 ,selection_changed,folder_changed,null)
但是,这给我带来了以下编译错误: / p>
exercise4_1.gs:62.55-62.68:错误:无法创建委托对象没有实例方法或闭包
Signal.connect (chooser1,selection_changed,folder_changed,null)
^^^^^^^^^^^^^^
编译失败:1个错误,0个警告
我也试着根据这个邮件沟通在vala邮件列表中,无济于事。
这是整个代码:
$ b使用
Gtk
GLib
class TestWindow:Window
chooser1:Gtk.FileChooserButton
chooser2:Gtk.FileChooserButton
构造()
//窗口的一般特性
title =文件选择器
window_position = WindowPosition.CENTER
destroy.connect(Gtk.main_quit)
chooser1 = new FileChooserButton(
选择一个文件夹,
FileChooserAction.SELECT_FOLDER
)
chooser2 =新建FileChooserButton(
选择一个文件夹,
FileChooserAction.OPEN
)
chooser1.set_current_folder(Environment.get_h ome_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)
添加(box)
def folder_changed()
var folder = chooser1.get_filename()
chooser2.set_current_folder(文件夹)
init
Gtk.init(ref args)
var test = new TestWindow()
test.show_all()
Gtk.main()
-
当然,我对这个特定语法缺乏理解,但是因为我卡住了,我会欣赏一个指针,让我摆脱它。
-
作为一个额外的,不太重要的点,最佳实践是什么:分割和缩进长行或在代码中允许它们?
Gtk的回调需要包含生成信号的对象的参数。另外,Genie和Vala对GLib信号的语法支持使信号更容易处理。这是一个基于你的代码的例子:
pre $ code $ [$ indent = 4]
使用
Gtk
$ b $ class TestWindow:Window
_file_chooser:FileChooserButton
$ b $ construct()
title =文件选择器
window_position = WindowPosition.CENTER
destroy.connect(Gtk.main_quit)
var folder_chooser = new FileChooserButton(
选择一个文件夹,
FileChooserAction.SELECT_FOLDER
)
folder_chooser .set_current_folder(Environment.get_home_dir())
folder_chooser.selection_changed.connect(folder_changed)
$ b _file_chooser = new FileChooserButton(
选择文件,
FileChooserAction。 OPEN
)
_file_choos er.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)
$ b $ def folder_changed(folder_chooser_widget:FileChooser)
folder:string = folder_chooser_widget.get_uri()
_file_chooser.set_current_folder_uri(文件夹)
初始化
Gtk.init(ref args)
var test = new TestWindow()
test.show_all()
Gtk.main()
需要注意的几点:
- 信号名称
selection_changed
已成为folder_chooser
然后你连接
到。 Vala编译器在编译时转换为GLib.Signal
FileChooserButton , folder_chooser
,已从类的范围中删除。它现在通过作为参数传递给回调来访问。所以它被定义为回调函数的参数。
- 您会注意到回调参数需要
FileChooser
类型,而不是FileChooserButton
类型。这是因为selection_changed
信号是FileChooser
接口的一部分,FileChooserButton
然后执行。这实际上给出了FileChooserButton
多于一个类型
- 虽然声明了
_file_chooser
所以它可以在整个类的范围内使用,它只能在类内通过使用下划线来访问
使用 Signal.connect()
更接近Gtk的C API。如果您需要这样做,那么下面的工作基于您的原始代码:
[indent = 4]
$
使用
Gtk
$ b $ class TestWindow:Window
chooser1:FileChooserButton
chooser2:FileChooserButton $ b $ construct()
//一般特性窗口
title =文件选择器
window_position = WindowPosition.CENTER
destroy.connect(Gtk.main_quit)
chooser1 = new FileChooserButton(
Choose a文件夹,
FileChooserAction.SELECT_FOLDER
)
chooser2 =新FileChooserButton(
选择一个文件夹,
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)]
//或[CCode(instance_pos = -1)] to总是最后
def folder_changed(folder_chooser:Widget)
folder:string = chooser1.get_uri()
chooser2.set_current_folder_uri(文件夹)
初始化
Gtk.init(ref args)
var test = new TestWindow()
test.show_all()
Gtk.main()
需要注意的几点:将回调转换为
GLib.Callback
,就像您在链接到的邮件中找到的那样
Window
对象创建了 FileChooserButton
,因此将 null
更改为 self
在此工作 CCode
属性,即 Widget
类型,但您可以将其更改为 FileChooser
以使用 get_uri ()
call 正如你所看到的,对于你的代码格式问题,我更喜欢分割长线。我不确定Genie是否已经达成了一致的最佳做法。
I am trying to create a window with two FileChooserButtons
. The first one should help the user pick a directory, thus I am using the action Select_folder; the second is to allow the user pick a file.
The problem is that I wanted the second one to change the current folder depending on the choice the user made in the first one.
My initial idea was to use Signal.connect, as in the line:
Signal.connect(chooser1, "selection_changed", folder_changed, null)
However, this is getting me the following compilation error:
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)
I've also tried adding (callback)folder_changed as per this mail communication at vala mailing list, to no avail.
This is the whole code:
[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 ()
It is certainly my lack of understanding about this particular syntax, but since I am stuck, I would appreciate a pointer to get me out of it.
As an extra, less important point, what is the best practice: to split and indent long lines or to allow them in the code?
A callback for Gtk needs to include a parameter for the object that generated the signal. Also Genie and Vala have syntax support for GLib signals to make signals easier to work with. Here is an example based on your code:
[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()
A few points to note:
- The signal name,
"selection_changed"
has become an attribute offolder_chooser
which you thenconnect
to. The Vala compiler does the conversion toGLib.Signal
at compile time - The
FileChooserButton
,folder_chooser
, has been removed from the scope of the class. It is now accessed by being passed as an argument to the callback. So it is defined as a parameter of the callback function - You will notice the parameter for the callback expects a
FileChooser
type and not aFileChooserButton
type. This is because theselection_changed
signal is part of theFileChooser
interface that theFileChooserButton
then implements. This effectively gives aFileChooserButton
more than one type - Although
_file_chooser
is declared so it is available within the whole scope of the class, it has been made only accessible within the class by using the underscore
Using Signal.connect()
is much closer to the C API for Gtk. If you need to do this then the following works based on your original code:
[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()
A few points to note:
- Yes you do need to cast the callback to
GLib.Callback
as you found in the mail message you linked to - The instance data you need is the
Window
object you have created theFileChooserButton
for, so changingnull
toself
works here - Vala will put instance data as the first parameter, so to override the default you have to use a
CCode
attribute, that is[CCode( instance_pos = 2 )]
in this case - The object generating the signal is still expected to be the first parameter of the callback function, so it is there in the definition even though it is unused in this example. This is defined as
Widget
type, but you can change this toFileChooser
to use theget_uri()
call
For your code formatting question I prefer to split long lines, as you can see. I'm not sure there is an agreed "best practise" for Genie as yet.
这篇关于signal.connect语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!