Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to implement a event similar to on show #9

Open
Maikel1963 opened this issue Feb 5, 2024 · 7 comments
Open

How to implement a event similar to on show #9

Maikel1963 opened this issue Feb 5, 2024 · 7 comments

Comments

@Maikel1963
Copy link

When watching the tutorial to this crate I was hoping for methods similar to on_create and on_show in delphi.
I would like to initialize and configure my app when window is already visible, to display progress of this initialization.
how do I implement an event which only will be triggered once on first display of window and is non blocking (should fire events which lead to changes in display and behavior of app during the excution)

@MoAlyousef
Copy link
Contributor

on_<event> methods were removed at some point due to their overhead:
#2

I might try to bring them back in at some point if I can fix the overhead issue.

@MoAlyousef
Copy link
Contributor

I have updated fltk-evented to 0.5, can you try on your system whether window.on_show() works without consuming a lot of overhead. I have changed the implementation and on my system, it no longer does.

@Maikel1963
Copy link
Author

This does not work at all. Even worse I can't close the window anymore.
I just wrote a short app to check if I did something unforeseen. But even here the printed line does not appear.

use fltk::{prelude::*, *};
use fltk_evented::Listener;

fn main() {
  let a = app::App::default();
  let mut win:Listener<_> = window::Window::default().with_size(400,300).into();
  let mut btn:Listener<_> = button::Button::new(160,200,80,30,"Click").into();
  win.end();
  win.show();
  
  win.on_show(|_| {
    println!("Here we are!");
  });
  
  a.run().unwrap();
}

@Maikel1963
Copy link
Author

Maikel1963 commented Feb 6, 2024

But to make things simpler again: I do not need the syntactic sugar with the keyword on_show (or anything else starting with "on_"). I just wanted to know how to implement a non blocking routine called once during startup but with visible window which does have effect on the widgets in the window.
E.g. in this example to change color and text of the button (or even better remove this button and insert a different one at a different position)
Maybe even without using the evented crate

@MoAlyousef
Copy link
Contributor

Without fltk-evented, you can use a timeout with 0.0 as a wait time. This is non-blocking and is one-shot:

use fltk::{app, enums::*, button::Button, frame::Frame, prelude::*, window::Window};

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let app = app::App::default();
    let mut wind = Window::default().with_size(400, 300);
    let mut frame = Frame::default().with_size(200, 100).center_of(&wind);
    let mut but = Button::new(160, 210, 80, 40, "Click me!");
    wind.end();
    wind.show();

    but.set_callback(move |_| frame.set_label("Hello world"));

    app::add_timeout3(0.0, move |_| {
        if let Some(btn_col) = args.get(1) {
            but.set_color(Color::from_hex_str(btn_col).unwrap_or(Color::Background));
            but.redraw();
        }
    });

    app.run().unwrap();
}

Run with: cargo run -- "#ff0000"

@Maikel1963
Copy link
Author

Ok, this runs. But I have to do some computations which will take a while in the timeout call.
To simulate this I started a loop in the timeout which shall change the button color every second.
And now the window is not displayed correctly

    let mut color_number = 0xFF0000;
    let pause = time::Duration::from_millis(1000);
    
    app::add_timeout3(0.0, move |_| {
      loop {
        color_number = (color_number + 0xF7) & 0xFFFFFF;
        but.set_color(Color::from_hex(color_number));
        but.redraw();
        thread::sleep(pause);
      };
    });

It seems as if the timeout computation is blocking. To overcome this I tried to spawn a thread around the loop. But I couldn't manage to get this working.

@MoAlyousef
Copy link
Contributor

You can use repeat_timeout inside the timeout function:

    let mut color_number = 0xFF0000;
    
    app::add_timeout3(0.0, move |h| {
        color_number = (color_number + 0xF7) & 0xFFFFFF;
        but.set_color(Color::from_hex(color_number));
        but.redraw();
        app::repeat_timeout3(1.0, h);
    });

Using threads requires calling app::awake, see: https://fltk-rs.github.io/fltk-book/Animations.html#spawning-threads

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants