Search code examples
rustgtk3

How to hide buttons in GTK3


I am new to GTK3 and Rust and I am unfamiliar with all the methods available, in this case to hide/show a button. I did find online a method of set_visible();, but when I tried to implement it like so:

let delete_button = button.create_button(self, "seating_delete_button");
delete_button.set_visible(false);
seating_box.add(&delete_button);

That did not work. I got no errors, I got no panic, it compiled, the server started and the button was still visible.

This is more or less my main.rs file exactly:

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

fn main() {
    let app = Application::builder()
        .application_id("org.example.HelloWorld")
        .build();

    app.connect_activate(|app| {
        // We create the main window.
        let win = ApplicationWindow::builder()
            .application(app)
            .default_width(320)
            .default_height(200)
            .title("Hello, World!")
            .build();

        let delete_button = gtk::Button::new();
        delete_button.set_label("Delete Me!");

        win.set_child(Some(&delete_button));

        // This is where all components are made visible (recursively).
        win.show_all();
    });

    app.run();
}

But the button I have to hide is in the sidebar_headings.rs file inside of sidebar_headings/component/sidebar_headings.rs.

use gtk::prelude::*;
use gtk::{Orientation, Widget, Button, ListBox};
use gtk_helpers::widgets::traits::{CptTrait, CptData};
use std::cell::RefCell;
use gtk_helpers::widgets::{button, boxx, frame, label};
use crate secure_superman_gtk::model::shared_data::*;

const TYPE_NAME &str = "SidebarHeadingsCpt";

#[derive(Debug, Clone)]
pub struct SidebarHeadingsCpt {
  cpt_data: CptData,
  shared_app_data: Rc<RefCell<SharedAppData>>

impl CptTrait for SidebarHeadingsCpt {
  // some logic here 
}

impl SidebarHeadingsCpt {
  pub fn new() {
    // some logic here
  }

  pub fn create_widget(&self) -> impl IsA<Widget> {
    let frame = frame::create_frame(self, "frame1");

    let box1 = boxx::create_box(self, "box1");
    box1.set_orientation(Orientation::Vertical);
    frame.add(&box1);

    let topology_box = boxx::create_box(self, "topology_box");
    box1.add(&topology_box);

    let label = label::create_text_label(self, "topology_label", "TOPOLOGY");
    label.set_halign(gtk::Align::Start);
    topology_box.add(&label);

    let delete_button = button::create_button(self, "topology_delete_button");
    delete_button.set_visible(false);
    topology_box.add(&delete_button);
  }
}
}

So, I tried importing the above to main.rs but Rust could not resolve the import statement. I may have been going down the wrong path anyway.


Solution

  • This could be due to a few things, but most likely one of the parent components are setting the visibility back to true after you set it to false.

    Here's the "Hello World" example from the gtk crate's README modified to account for your question:

    use gtk::prelude::*;
    use gtk::{Application, ApplicationWindow};
    
    fn main() {
        let app = Application::builder()
            .application_id("org.example.HelloWorld")
            .build();
    
        app.connect_activate(|app| {
            // We create the main window.
            let win = ApplicationWindow::builder()
                .application(app)
                .default_width(320)
                .default_height(200)
                .title("Hello, World!")
                .build();
    
            let delete_button = gtk::Button::new();
            delete_button.set_label("Delete Me!");
    
            win.set_child(Some(&delete_button));
    
            // This is where all components are made visible (recursively).
            win.show_all();
    
            // After the window has changed everything to visible, we can now set
            // the button to the desired visibility.
            delete_button.set_visible(false);
        });
    
        app.run();
    }
    

    Take note of the comments. If I were to have put delete_button.set_visibility(false); before win.show_all();, delete_button would have been made visible again. win.show_all() recursively makes itself and its children visible so you can see your app. Not the most intuitive thing, but it's expected behavior, which is why you didn't get any warnings or errors. Just keep the order in which your code is executed in mind and you should be good to go.

    Hope this helps.