【问题标题】:Reusing signal handlers?重用信号处理程序?
【发布时间】:2018-10-31 00:35:53
【问题描述】:

在 Vala 中有没有办法让多个信号处理程序执行相同的代码,同时它们可以访问本地范围?

使用委托定义 lambda 有效,但需要委托定义并给出警告“不支持复制委托”:

delegate void ChangeHandler ();
void test () {
 var answer = 42;

 ChangeHandler handler = () => {
   debug("size or position changed. answer: %i", answer);
 };
 size_changed.connect (handler);
 position_changed.connect (handler);
}

据我所知,也没有办法将信息传递给处理程序?类似:

void test () {
 var answer = 42;
 size_changed.connect (handler, answer);
 position_changed.connect (handler, answer);
}
void handler (answer) {
 debug("size or position changed. answer: %i", answer);
}

我可以这样做,但这需要很多额外的代码,尤其是当有很多参数时。

void test () {
 var answer = 42;
 size_changed.connect (handler, answer);
 position_changed.connect (() => handler(answer));
}
void handler (answer) {
 debug("size or position changed. answer: %i", answer);
}

有没有办法将多个信号连接到一个匿名函数?比如:

void test () {
 var answer = 42;

 multi_connect(size_changed, position_changed, () => {
   debug("size or position changed. answer: %i", answer);
 });
}

【问题讨论】:

    标签: vala


    【解决方案1】:

    使用this传递数据怎么样:

    public class Test : GLib.Object {
    
        public signal void sig_1 ();
    
        public signal void sig_2 ();
    
        private int answer = 42;
    
        private void sig_handler (Test t) {
            stdout.printf("sig_1 or sig_2 triggered. answer: %d\n", answer);
        }
    
        public static int main(string[] args) {
            Test t1 = new Test();
    
            t1.sig_1.connect(t1.sig_handler);
            t1.sig_2.connect(t1.sig_handler);
    
            t1.sig_1();
            t1.sig_2();
    
            return 0;
        }
    }
    

    也许使用两个类更具可读性:

    public class SignalRaiser : GLib.Object {
        public signal void sig_1 ();
        public signal void sig_2 ();
    }
    
    public class SignalReceiver : GLib.Object {
        private int answer = 42;
    
        public void sig_handler (SignalRaiser sender) {
            stdout.printf("sig_1 or sig_2 triggered. answer: %d\n", answer);
        }
    }
    
    int main(string[] args) {
        var raiser = new SignalRaiser();
        var receiver = new SignalReceiver();
    
        raiser.sig_1.connect(receiver.sig_handler);
        raiser.sig_2.connect(receiver.sig_handler);
    
        raiser.sig_1();
        raiser.sig_2();
    
        return 0;
    }
    

    【讨论】:

    • 感谢您的想法。额外的挑战是它是一大段代码,额外的属性或单独的类会丢失。
    • 你认为可以写一个connect_multiple函数吗?我还没弄清楚如何将信号作为参数传递。
    • 在 C API 中,GObject 信号通过其名称来引用,例如 g_signal_connect_object (raiser, "sig-1", …。所以在 C 领域应该可以实现connect_multiple 函数。在 Vala 土地上,您不能将信号作为函数参数传递。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 2017-11-13
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    • 2012-06-04
    相关资源
    最近更新 更多