3

I am working my way through the Vala GTK+3 tutorial provided by Elementary OS. I understand that this code:

var button_hello = new Gtk.Button.with_label ("Click me!");
button_hello.clicked.connect (() => {
    button_hello.label = "Hello World!";
    button_hello.set_sensitive (false);
});

uses a Lambda function to change the button's label when it's clicked. What I want to do is call this function instead:

void clicked_button(Gtk.Button sender) {
    sender.label = "Clicked. Yippee!";
    sender.set_sensitive(false);
}

I've tried this:

button.clicked.connect(clicked_button(button));

But I get this error from the Vala compile when I try to compile:

hello-packaging.vala:16.25-16.46: error: invocation of void method not allowed as expression
    button.clicked.connect(clicked_button(button));
                           ^^^^^^^^^^^^^^^^^^^^^^
Compilation failed: 1 error(s), 0 warning(s)

I'm new to both Vala and Linux so please be gentle but can someone point me in the right direction?

Garry Pettet
  • 8,096
  • 22
  • 65
  • 103

2 Answers2

5

You need to pass a reference to the function, rather than the result of the function. So it should be:

button.clicked.connect (clicked_button);

When the button is clicked GTK+ will invoke the clicked_button function with the button as an argument.

The error message invocation of void method not allowed as expression is telling you you are calling (invoking) the method and it has no result (void). Adding parentheses, (), to the end of a function name invokes that function.

AlThomas
  • 4,169
  • 12
  • 22
  • Does the instance that emits the signal always get passed to the function as the first argument? Is this the same for all GTK widgets? – Garry Pettet Apr 03 '17 at 15:14
  • Yes, because the callback has to have a function signature of GtkCallback, which in C is void (*GtkCallback) (GtkWidget *widget, gpointer data); See https://developer.gnome.org/gtk3/stable/GtkWidget.html#GtkCallback and https://valadoc.org/gtk+-3.0/Gtk.Callback.html. The user data part is usually hidden in Vala because it is either the class instance where the method is defined or the closure depending on whether the callback was passed as a function name or a lambda expression. – AlThomas Apr 03 '17 at 15:34
0

Managed to get it working. Here's the code in case others need it:

int main(string[] args) {
    //  Initialise GTK
    Gtk.init(ref args);

    // Configure our window
    var window = new Gtk.Window();
    window.set_default_size(350, 70);
    window.title = "Hello Packaging App";
    window.set_position(Gtk.WindowPosition.CENTER);
    window.set_border_width(12);
    window.destroy.connect(Gtk.main_quit);

    // Create our button
    var button = new Gtk.Button.with_label("Click Me!");
    button.clicked.connect(clicked_button);

    // Add the button to the window
    window.add(button);
    window.show_all();

    // Start the main application loop
    Gtk.main();
    return 0;
}

// Handled the clicking of the button
void clicked_button(Gtk.Button sender) {
    sender.label = "Clicked. Yippee!";
    sender.set_sensitive(false);
}
Garry Pettet
  • 8,096
  • 22
  • 65
  • 103