Как определить, нажата ли клавиша в Диоксусе?

Я работаю над настольным приложением dioxus, в котором у меня длинный список флажков. Я хочу иметь возможность переключать выбор, чтобы отметить сразу несколько из них, но не могу понять, как определить, нажата ли клавиша Shift.

Основываясь на этом вопросе, я понял, что могу получать onkeydown события, если сфокусирован на флажке, но я могу сфокусировать флажок только с помощью вкладки, так что это не совсем то, что я ищу. Я пробовал использовать другие ящики web-sys, wasm-bindgen, global-hotkey, но безуспешно.

Моя логика работает, просто используя статическое логическое значение shift_pressed, поэтому, если бы кто-нибудь мог помочь мне вместо этого получить это логическое значение из состояния клавиши Shift, я был бы очень признателен.

#[component]
fn ChangeList(changes: Signal<Vec<ChangeItemInfo>>) -> Element {
    let mut last_clicked = use_signal(|| 0);
    let shift_pressed = true; // TODO: get this bool from the shift key

    let mut group_select = move |just_clicked: usize, check: bool| {
        // get the selection range indices
        let first = std::cmp::min(just_clicked, *last_clicked.read());
        let last = std::cmp::max(just_clicked, *last_clicked.read());
        println!("Group Selecting from {first} to {last}");
        // check or uncheck all the checkboxes in the range
        changes.write().iter_mut().skip(first).take(last - first + 1).for_each(|c| c.checked = check);
    };

    rsx! {
        div {class: "change-list",
            header { // Display the number of changes
                if changes.read().len() == 0 {
                    p {"No changes found"}
                } else {
                    // make a check box that checks off all changes when checked
                    label { class: "checkbox_container",
                        input { r#type: "checkbox", checked:"false",
                            onchange: move |evt: FormEvent| {
                                let checked = evt.value() == "true";
                                changes.write().iter_mut().for_each(|c| c.checked = checked);
                            },
                        }
                        span { class: "checkmark" }
                    }
                    p {"{changes.read().len()} Changed Files"}
                }
            }

            ul { // Display a check box, title, and symbol for each change
                for (index, change) in changes.read().iter().enumerate() {
                    li { title: "{&change.change}", key: "{&change:?}",
                        label { class: "checkbox_container",                            
                            input { r#type: "checkbox", checked:"{change.checked}",
                                onchange: move |evt: FormEvent| {
                                    let checked = evt.value() == "true";

                                    if shift_pressed {
                                        group_select(index, checked);
                                    } else if let Some(c) = changes.write().get_mut(index) {
                                        c.checked = checked; // check off the clicked check box
                                    }

                                    last_clicked.set(index);
                                },
                            }
                            span { class: "checkmark" }
                        }
                        p {"{change.change.path.file_name().unwrap().to_string_lossy()}"}
                        div { display:"flex", gap:"0.5rem", margin_left:"auto",
                            if change.conflict { img { src: mg!(file("assets/code_pull_request.svg")) } }
                            if change.change.r#type == ChangeType::New { img { src: mg!(file("assets/new.svg")) } }
                            if change.change.r#type == ChangeType::Modified { img { src: mg!(file("assets/modified.svg")) } }
                            if change.change.r#type == ChangeType::Deleted { img { src: mg!(file("assets/deleted.svg")) } }
                        }
                    }
                }
            }
        }
    }
}

Пожалуйста, обрежьте свой код, чтобы облегчить поиск проблемы. Следуйте этим рекомендациям, чтобы создать минимально воспроизводимый пример.

Community 14.07.2024 14:45
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
1
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я понял это, следуя этому примеру, который демонстрирует, как перехватывать события из wry. Вот что у меня получилось для тех, кто это найдет:

use dioxus::prelude::*;
use dioxus::desktop::tao::event::Event as WryEvent;
use dioxus::desktop::tao::event::WindowEvent;
use dioxus::desktop::use_wry_event_handler;
let mut shift_pressed = use_signal(|| false); 

use_wry_event_handler(move |event, _| {
    if let WryEvent::WindowEvent {
        event: WindowEvent::ModifiersChanged(state),
        ..
    } = event
    {
        match state.bits() {
            4 => shift_pressed.set(true),
            0 => shift_pressed.set(false),
            _ => {}
        }
    }
});

Другие вопросы по теме