Event handling: sends key presss event eternally

44 views Asked by At

I just want to draw some object (white square) in the black frame and handle some events (left, down, right, up arrow is pressed). When some of these keys are pressed object moves in according direction. But window gets the same signal over and over until another key is pressed. I propose, we have some event buffer which keeps events and function event_key() returns last event happened. But how to handle event once until the key is pressed again.

use fltk::draw::*;
use fltk::{prelude::*, *};
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let app = app::App::default(); //create app
    let mut win = window::Window::default() //create window
        .with_size(350, 350);
    let mut frame = frame::Frame::default() //create frame
        .size_of_parent();

    let ww = win.w() / 2; //position of white square in thr middle of width
    let wh = win.h() / 2; //position of white square in the muddle of height
    let offset = Rc::new(RefCell::new(0)); //offset of white square
    let offset1 = offset.clone();

    //drawning wgite square
    frame.draw(move |f| {
        let offset = offset1.borrow();
        draw_rect_fill(0, 0, f.w(), f.h(), enums::Color::Black);
        draw_rect_fill(ww + *offset, wh, 10, 10, enums::Color::White);
    });

    //handle key press events
    frame.handle(move |frame, _| {
        use fltk::enums::Key;

        let mut offset = offset.borrow_mut();
        let key = app::event_key();

        match key {
            Key::Right => {
                //the right arrow is pressed
                println!("{:?}", key);
                *offset += 1;
                frame.redraw();
                app::sleep(0.0500);
                true
            }
            Key::Left => {
                //the left arrow is pressed
                println!("left");
                true
            }
            Key::Up => {
                //the up arrow is pressed
                println!("Up");
                true
            }
            Key::Down => {
                //the down arrow is presed
                println!("Down");
                true
            }
            _ => false, //ignore other events
        }
    });

    win.end();
    win.show();
    app.run().unwrap();
}
1

There are 1 answers

1
mo_al_ On

You will have to handle the event argument in the handle method:

frame.handle(move |frame, ev| {});

Can you try with the following code:

use fltk::draw::*;
use fltk::{prelude::*, *};
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let app = app::App::default(); //create app
    let mut win = window::Window::default() //create window
        .with_size(350, 350);
    let mut frame = frame::Frame::default() //create frame
        .size_of_parent();

    let ww = win.w() / 2; //position of white square in thr middle of width
    let wh = win.h() / 2; //position of white square in the muddle of height
    let offset = Rc::new(RefCell::new(0)); //offset of white square
    let offset1 = offset.clone();

    //drawning wgite square
    frame.draw(move |f| {
        let offset = offset1.borrow();
        draw_rect_fill(0, 0, f.w(), f.h(), enums::Color::Black);
        draw_rect_fill(ww + *offset, wh, 10, 10, enums::Color::White);
    });

    //handle key press events
    frame.handle(move |frame, ev| {
        use fltk::enums::Key;

        let mut offset = offset.borrow_mut();
        
        match ev {
            enums::Event::KeyDown => {
                let key = app::event_key();
                println!("{:?}", key);
                match key {
                    Key::Right => {
                        //the right arrow is pressed
                        *offset += 1;
                        frame.redraw();
                        true
                    }
                    Key::Left => {
                        *offset -= 1;
                        frame.redraw();
                        true
                    }
                    _ => false, //ignore other events
                }
            }
            enums::Event::Focus => true,
            enums::Event::Unfocus => true,
            _ => false,
        }
    });

    win.end();
    win.show();
    app.run().unwrap();
}

Notice we also handle Focus and Unfocus since normally a frame doesn't respond to KeyDown, as can be found in the FLTK documentation: https://www.fltk.org/doc-1.4/events.html