rustgtk4gtk-rs

GTK-rs getting input from GTK::Entry


I have a small gtk-rs application where I am trying to display an input field and get the input from the user. At the moment I can't get the input from the input field when the user clicks the button. I know button.connect_clicked is where I need to do this but I don't know how?

My build_ui method:

use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, Button, Orientation};

pub fn build_ui(app: &Application) {
    let button = Button::builder()
        .label("Submit")
        .margin_top(12)
        .margin_bottom(12)
        .margin_start(12)
        .margin_end(12)
        .build();

    let input = gtk::Entry::builder()
        .placeholder_text("input")
        .margin_top(12)
        .margin_bottom(12)
        .margin_start(12)
        .margin_end(12)
        .build();

    let gtk_box = gtk::Box::builder()
        .orientation(Orientation::Vertical)
        .build();
    gtk_box.append(&input);
    gtk_box.append(&button);

    button.connect_clicked(move | _button| {
        println!("{}", input.display()); 
    });

    let window = ApplicationWindow::builder()
        .application(app)
        .title("gtk-app")
        .child(&gtk_box)
        .default_height(720)
        .default_width(360)
        .build();

    window.present();
}

main.rs:

const APP_ID: &str = "org.my-gtk-app";

fn main() {
    // Create a new application
    let app = Application::builder().application_id(APP_ID).build();

    // Connect to "activate" signal of `app`
    app.connect_activate(home::build_ui);

    // Run the application
    app.run();
}

I have found this question which is almost exactly the same however when I try and implement the solution all of the .add methods throw an error stating:

the following trait bounds were not satisfied: `ApplicationWindow: IsA<CellArea>` which is required by `ApplicationWindow: gtk4::prelude::CellAreaExt`

EDIT: Also Gtk::Entry does not have a .get_text() method according to the compiler. After doing a bit more googling around this it seems that GTK3 had a get_text method for Gtk::Entry however Gtk4 does not.

So does anyone know how to get the text from a Gtk::Entry object when using Gtk4?

EDIT 2: I think I needed to use the .display() method however when I run the code now I don't get the text input from the user. input.display() just returns an empty string. I have updated the code samples to reflect these changes.


Solution

  • The Entry does have a text() method which gives you a GString (because Entry implements Editable), that can be converted to a rust str using as_str().

    So in order to get the current text from an entry, you can do the following:

    let my_input_value = my_input.text().as_str();
    

    For completeness, here is the updated build_ui function:

    pub fn build_ui(app: &Application) {
        let button = Button::builder()
            .label("Submit")
            .margin_top(12)
            .margin_bottom(12)
            .margin_start(12)
            .margin_end(12)
            .build();
    
        let input = gtk::Entry::builder()
            .placeholder_text("input")
            .margin_top(12)
            .margin_bottom(12)
            .margin_start(12)
            .margin_end(12)
            .build();
    
        let gtk_box = gtk::Box::builder()
            .orientation(Orientation::Vertical)
            .build();
        gtk_box.append(&input);
        gtk_box.append(&button);
    
        button.connect_clicked(move | _button| {
            println!("{}", input.text().as_str()); 
        });
    
        let window = ApplicationWindow::builder()
            .application(app)
            .title("gtk-app")
            .child(&gtk_box)
            .default_height(720)
            .default_width(360)
            .build();
    
        window.present();
    }
    

    Edit

    Because GString implements Display the following works as well:

    println!("{}", input.text());