rustgtk4gtk-rs

What is the gtk-rs design pattern for changing the widgets on a page?


I am using gtk-rs to build a small application and I am struggling with the concept of changing the widgets displayed on a page. So far I have been working through this guide but I have not found the information I am looking for.

An example would be you open the app and you start on the landing page, you then click a button and it takes you to another page/view which has different widgets on it.

I know how to build a page with a single set of widgets, I can update the contents of those widgets but I don't know how to either load a completely new layout or remove widgets and replace them.

Has anyone got a link to a guide or something similar detailing how to do this? If this isn't the way we're supposed to do this with gtk-rs can you point me to something detailing how we should be doing this?

I have been googling things like gtk-rs redraw window, gtk-rs change widgets, gtk-rs new view but none of these have returned an explanation of how to handle this problem.

An example from the guide is below. Assuming we pressed the button in this application I would then want to load a page with different buttons on it.

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

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

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

fn build_ui(app: &Application) {
    // Create a button
    let button = Button::builder()
        .label("Press me!")
        .margin_top(12)
        .margin_bottom(12)
        .margin_start(12)
        .margin_end(12)
        .build();

    // Connect to "clicked" signal of `button`
    button.connect_clicked(move |_| {
        println!("The button was pressed!");
    });

    // Create a window
    let window = ApplicationWindow::builder()
        .application(app)
        .title("My GTK App")
        .child(&button)
        .build();

    // Present window
    window.present();
}

Solution

  • I use Stack for this purpose. Here, have a look at this link. Use StackPage to add pages.

    Here's an example.

    use gtk::Application;
    use gtk::{prelude::*, ApplicationWindow};
    use gtk::StackTransitionType::SlideLeftRight;
    
    fn main() {
    
        let app = Application::builder()
            .application_id("com.artognak.markiv")
            .build();
    
        app.connect_activate(build_ui);
    
        app.run();
    }
    
    fn build_ui(app: &Application) {
    
        let window = ApplicationWindow::builder()
            .application(app)
            .default_width(360)
            .default_height(360)
            .build();
    
        let container = gtk::Box::new(gtk::Orientation::Vertical, 100);
        window.set_child(Some(&container));
    
        let stack = gtk::Stack::new();
    
        stack.set_transition_type(SlideLeftRight);
        stack.set_transition_duration(200);
    
        let page_1_label = gtk::Label::new(Some("Page 1"));
        stack.add_titled(&page_1_label, Option::<&str>::None, "Page 1");
    
        let page_2_label = gtk::Label::new(Some("Page 2"));
        stack.add_titled(&page_2_label, Option::<&str>::None, "Page 2");
    
        let stack_switcher = gtk::StackSwitcher::new();
        stack_switcher.set_stack(Some(&stack));
    
        container.append(&stack_switcher);
        container.append(&stack);
    
        window.present();
    }
    

    You can also switch pages by setting the visible child name for the Stack. This way you won't need StackSwitcher.