How to pass widget and data from one file to another file in different class?

Beginner-level questions. I’m creating a counter application (first application from The 7 Tasks). I created this application in one file and it is working fine. Following is the code.

class Application : Gtk.Application {
  public int val = 0;

  public Application() {
    Object(
      application_id: "com.github.uname.counter",
      flags: ApplicationFlags.FLAGS_NONE
    );
  }
  
  protected override void activate() {
    var window = new Gtk.ApplicationWindow(this);
    window.default_height = 30;
    window.default_width = 300;
    window.title = "Counter";
    
    var grid = new Gtk.Grid();
    grid.column_homogeneous = true;
    grid.row_homogeneous = true;
    grid.row_spacing = 5;
    grid.column_spacing = 5;
    
    var entry = new Gtk.Entry();
    entry.text = val.to_string();
    entry.editable = false;
    grid.attach(entry, 0, 0, 1, 1);

    var button1 = new Gtk.Button.with_label("Counter");
    grid.attach(button1, 1, 0, 1, 1);
    
    button1.clicked.connect (() => {
      this.val = this.val + 1;
      entry.text = this.val.to_string();
    });

    window.add(grid);
    window.show_all();
  }
  
  public static int main(string[] args) {
    var application = new Application();
    return application.run(args);
  }
}

Now, I’m trying to divide the above code into separate files such as Application.vala, Entry.vala, and Button.vala. Here is the code for these files.

Code for Application.vala.

class Application : Gtk.Application {
  public int val = 0;

  public Application() {
    Object(
      application_id: "com.github.chauhankiran.counter",
      flags: ApplicationFlags.FLAGS_NONE
    );
  }
  
  protected override void activate() {
    var window = new Gtk.ApplicationWindow(this);
    window.default_height = 30;
    window.default_width = 300;
    window.title = "Counter";
    
    var grid = new Gtk.Grid();
    grid.column_homogeneous = true;
    grid.row_homogeneous = true;
    grid.row_spacing = 5;
    grid.column_spacing = 5;
    
    var entry = new Entry(val);
    grid.attach(entry, 0, 0, 1, 1);

    var button1 = new Button(val);
    grid.attach(button1, 1, 0, 1, 1);

    window.add(grid);
    window.show_all();
  }
  
  public static int main(string[] args) {
    var application = new Application();
    return application.run(args);
  }
}

Code for Entry.vala.

public class Entry : Gtk.Entry {
  public Entry(int val) {
    text = val.to_string();
  }

  construct {
    editable = false;
  }
}

Code for Button.vala.

public class Button : Gtk.Button {
  // Is it correct?
  public int val;

  public Button(int val) {
    this.val = val;
  }

  construct {
    label = "Counter";
  }

  // How to write this within Button.vala from Application.vala?
  // How to get entry widget in this class?
  button1.clicked.connect (() => {
    this.val = this.val + 1;
    entry.text = this.val.to_string();
  });
}

Now, I’ve the following questions.

  1. Entry.vala accepts val as initial value. I don’t know how to pass it in construct. So, I used public object method. Is it correct way?
  2. In Button.vala I need val as well access to entry so that I can get access to entry in Button.vala? Or this is incorrect way to do the code? If that is that is the case, please suggest correct way. Currently separate files code throws error as I don’t know how to connect and pass the information correctly.

There are actually two ways of writing constructors in Vala. You seem to be attempting to do GObject-Style Construction, so we’ll continue with that approach.

Here’s how I wrote the Entry class:

// Entry.vala
public class Entry : Gtk.Entry {
  public Entry (int val) {
    Object (
      editable: false,
      text: val.to_string ()
    );
  }
}

So now in your Application class, the code you write for creating and adding your entry widget to the grid is reduced to:

// Application.vala
var entry = new Entry (2);
grid.attach (entry, 0, 0, 1, 1);

With this issue you have, there isn’t a “correct way” but I recommend making things as easy as it can be for yourself.

Now in Button.vala, it looks like you’re trying to store the counter logic in the Button object itself and from what you’ve said, you want access to entry in Button.vala.

Since they are both “tied” to each other, it would make it easier if you created a widget that contained both a Button and Entry, with all the counter logic.

So you can replace Button.vala and Entry.vala with a new file called Counter.vala:

// Counter.vala
public class Counter : Gtk.Grid {
    public int val { get; set construct; }

    public Counter () {
        // Set counter to 0 by default
        Object (val: 0);
    }

    public Counter.with_initial_val_of (int val) {
        // Set intial value of counter
        Object (val: val);
    }

    construct {
        this.column_homogeneous = true;
        this.row_homogeneous = true;
        this.row_spacing = 5;
        this.column_spacing = 5;

        var entry = new Gtk.Entry () {
            text = this.val.to_string (),
            editable = false
        };

        this.attach (entry, 0, 0, 1, 1);

        var button = new Gtk.Button.with_label ("Counter");
        button.clicked.connect (() => {
            this.val = this.val + 1;
            entry.text = this.val.to_string ();
        });

        this.attach (button, 1, 0, 1, 1);
    }
}
// Application.vala
public class Application : Gtk.Application {
  public Application () {
    Object (
      application_id: "com.github.uname.counter",
      flags: ApplicationFlags.FLAGS_NONE
    );
  }

  protected override void activate () {
    var window = new Gtk.ApplicationWindow (this);
    window.default_height = 30;
    window.default_width = 300;
    window.title = "Counter";

    // Creates counter with an inital value of 0.
    // var counter = new Counter ();

    // Creates counter with an initial value of 2.
    var counter = new Counter.with_initial_val_of (2);

    window.add (counter);
    window.show_all ();
  }

  public static int main (string[] args) {
    var application = new Application ();
    return application.run (args);
  }
}

I hope that this helps!

Let us know if you have any more questions.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.