【问题标题】:The Button.connect syntax in GenieGenie 中的 Button.connect 语法
【发布时间】:2015-10-31 09:04:25
【问题描述】:

我想将某种行为应用于标签。单击横向按钮时,相应的标签应旋转 90 度。在 vala 中可以轻松完成,但我在 genie 上找不到特定的语法。

我试图重现的vala代码来自基本操作系统getting started guide

hello_button.clicked.connect(() =>
{ 
hello_label.label = "Hello World!";
hello_button.sensitive = false;
});


rotate_button.clicked.connect(() =>
{ 
rotate_label.angle = 90;
rotate_label.label = "Verbal";
rotate_button.sensitive = false;
});

我实际上设法几乎完全重现了 Genie 中的代码,但轮换除外。这是我走了多远:

/* ANOTHER GTK EXPERIMENT WITH GENIE BASED ON ELEMENTARY INTRODUCTORY PAGE
**   compile with valac --pkg gtk+03.0 layoutgtkexample.gs */

[indent=4]
uses Gtk

init
    Gtk.init (ref args)
    var window = new Gtk.Window()
    window.title = "Hello World!"
    window.set_border_width(12)

    var layout = new Gtk.Grid ()
    layout.column_spacing = 6
    layout.row_spacing = 6

    var hello_button = new Gtk.Button.with_label("Say Hello")
    var hello_label = new Gtk.Label("Hello")

    var rotate_button = new Gtk.Button.with_label ("Rotate")
    var rotate_label = new Gtk.Label("Horizontal")

    // add first row of widgets

    layout.attach (hello_button, 0, 0, 1,1)
    layout.attach_next_to (hello_label, hello_button, PositionType.RIGHT, 1, 1)

    // add second row of widgets

    layout.attach(rotate_button, 0,1,1,1)
    layout.attach_next_to(rotate_label, rotate_button, PositionType.RIGHT, 1, 1)

    window.add(layout)

    hello_button.clicked.connect(hello_pushed)
    rotate_button.clicked.connect(rotate_pushed)

    window.destroy.connect(Gtk.main_quit)
    window.show_all ()
    Gtk.main ()

def hello_pushed (btn:Button)
    btn.label = "Hello World!"
    btn.sensitive = false

def rotate_pushed (btn:Button)
    btn.label = "Vertical"
    //btn.angle = 90
    btn.sensitive = false

【问题讨论】:

    标签: linux gtk3 genie


    【解决方案1】:

    问题在于标识符在哪里有效并且被称为“范围”。

    Vala 示例使用了一个匿名函数,在 Vala 中也称为 lambda 表达式。当定义匿名函数的范围内的变量在匿名函数中也可用时,匿名函数可以是“闭包”。这很有用,因为回调发生在原始代码块运行之后,但变量在回调中仍然可用。因此在 Vala 示例中,按钮和标签都定义在封闭范围内,按钮和标签在回调匿名函数中也可用。

    不幸的是,Genie 无法将匿名函数解析为函数参数,在这种情况下是在 connect() 调用中。虽然some work has been done on this in 2015。所以你正确地使用了一个函数名。问题是回调仅将按钮作为参数传递,而不是相邻的标签。因此,为了使标签在回调函数中可用,我们可以使用一个类:

    /* ANOTHER GTK EXPERIMENT WITH GENIE BASED ON ELEMENTARY INTRODUCTORY PAGE
    **   compile with valac --pkg gtk+-3.0 layoutgtkexample.gs */
    
    [indent=4]
    uses Gtk
    
    init
        Gtk.init (ref args)
        new RotatingButtonWindow( "Hello World!" )
        Gtk.main ()
    
    class RotatingButtonWindow:Window
        _hello_label:Label
        _rotate_label:Label
    
        construct( window_title:string )
            title = window_title
            set_border_width(12)
    
            var layout = new Grid ()
            layout.column_spacing = 6
            layout.row_spacing = 6
    
            // add 'hello' row of widgets
            var hello_button = new Button.with_label("Say Hello")
            _hello_label = new Label("Hello")
            layout.attach (hello_button, 0, 0, 1,1)
            layout.attach_next_to (_hello_label, hello_button, PositionType.RIGHT, 1, 1)
    
            // add 'rotate' row of widgets
            var rotate_button = new Button.with_label ("Rotate")
            _rotate_label = new Label("Horizontal")
            layout.attach(rotate_button, 0,1,1,1)
            layout.attach_next_to(_rotate_label, rotate_button, PositionType.RIGHT, 1, 1)
    
            add(layout)
    
            hello_button.clicked.connect(hello_pushed)
            rotate_button.clicked.connect(rotate_pushed)
    
            destroy.connect(Gtk.main_quit)
            show_all ()
    
        def hello_pushed (btn:Button)
            _hello_label.label = "Hello World!"
            btn.sensitive = false
    
        def rotate_pushed (btn:Button)
            _rotate_label.label = "Vertical"
            _rotate_label.angle = 90
            btn.sensitive = false
    

    几点说明:

    • 通过将_hello_label_rotate_label 的定义放在类的范围内,它们可用于类中定义的所有函数。像这样的定义通常被称为“字段”。下划线表示它们在课堂外不可用,因此在示例中您无法从 init 访问它们
    • construct() 在创建对象时被调用,在示例中,new RotatingButtonWindow( "Hello World!" ) 行实例化了对象。如果您重复该行,您将有两个单独的窗口,即RotatingButtonWindow 数据类型的两个实例
    • 您会注意到RotatingButtonWindow 类型也被定义为Window 类型。这意味着它为Gtk.Window 类添加了更多细节。这就是titleset_border_width() 可以在新类中使用的原因。它们是从父 Gtk.Window 类“继承”而来的
    • 通过使用带有uses Gtk 的Gtk 命名空间,我们不需要在所有内容前加上Gtk

    随着您的 Gtk 应用程序变得越来越复杂,您可能需要查看 GtkBuilder。这允许在外部文件中布置窗口和小部件。然后使用GResource 将文件构建到应用程序的二进制文件中,因此无需单独分发 UI 文件。

    【讨论】:

    • 我想知道是否存在像 GResource 这样的东西,它可以从 Gtkbuilder css 中生成二进制文件。谢谢。
    • 旧的、过时的 Genie 教程会产生关于语法错误的错误。上面的代码构建干净:-)
    猜你喜欢
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    相关资源
    最近更新 更多