I am trying to write a small app in gtk-rs that takes an input and checks if it is correct against a value and displays an error if it is not. I am struggling with handling the code to display the error.
I have seen a number of questions covering similar subjects however I have not been able to successfully implement any of the suggestions.
There is also this thread that suggests using glib::MainContext::default()
however I am already using that and I am not sure what they are doing differently to me.
A working example of my problem is below:
use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, Button, Orientation};
use std::time::Duration;
use std::sync::{Arc, Mutex};
use glib;
use fragile;
const APP_ID: &str = "org.my_gtk_app.app";
fn main() {
let app = Application::builder().application_id(APP_ID).build();
app.connect_activate(build_ui);
app.run();
}
pub fn build_ui(app: &Application) {
let button = Button::builder()
.label("Submit")
.build();
let input = gtk::Entry::builder()
.placeholder_text("input")
.build();
let failed_attempt = gtk::Label::new(Some("Attept failed."));
failed_attempt.set_visible(false);
failed_attempt.add_css_class("failed_login");
let failed_clone = fragile::Fragile::new(failed_attempt.clone());
let this_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
this_box.append(&input);
this_box.append(&failed_attempt);
this_box.append(&button);
let guess = Arc::new(Mutex::new(String::new()));
let guess_clone = Arc::clone(&guess);
let window = ApplicationWindow::builder()
.application(app)
.title("my_gtk_app")
.child(&this_box)
.build();
window.show();
let window_clone = fragile::Fragile::new(window.clone());
std::thread::spawn(move || loop {
//let failed_clone = fragile::Fragile::new(failed_attempt.clone()); // Moving this inside the loop causes a *mut c_void` cannot be shared between threads safely error
std::thread::sleep(Duration::from_millis(100));
if guess_clone.lock().unwrap().to_string() == String::from("Guess!") {
glib::MainContext::default().invoke(move || {
window_clone.get().maximize();
});
break;
}
else if guess_clone.lock().unwrap().to_string().len() > 0 {
glib::MainContext::default().invoke(move || {
failed_clone.get().set_visible(true);
});
//break; //Adding this break in causes the program to run successfully but only for one iteration.
}
});
}
The answer I have seen most commonly in other questions is to move the assignment of the variable to be worked on inside the loop however this is causing a separate error.
I have also tried wrapping an if statement around the glib::MainContext::default()
in the else block to ensure it can only run once however that did not work either.
What I need to know is how do I conditionally make a GtK::Label visible based on user input? If there is a completely different method than what I am trying to achieve here that would be easier than rectifying what I have or a fix for this example code that would be great.