Как сделать обработку событий мыши проще?
Иногда мне нужно реализовать такую функцию, как персонализированное перетаскивание. Код может выглядеть так:
bool mouse_down = false;
Vec2 mouse_pos;
void on_mouse_down() {
mouse_down = true;
mouse_pos = cursor_pos();
}
void on_mouse_move() {
if(mouse_down) {
Vec2f c = cursor_pos();
Vec2f d = c - mouse_pos;
// dragging. make objects tracing the cursor.
// ...
}
}
void on_mouse_up() {
mouse_down = false;
// dropped
// ...
}
Я знаю, что это прекрасно работает, но мне совсем не нравятся избыточные переменные и отдельные процедуры для чего-то подобного. В IP(императивное программирование), возможно, это неизбежно; у меня вопрос, есть ли лучший способ справиться с такой вещью в FP(функциональное программирование)? Любые идеи и предложения приветствуются, независимо от того, какие языки программирования, Lisp, Scheme, F#, Ruby и т. Д., Или какой-нибудь лучший способ сделать это в IP?
1 ответ
Поскольку никто не пытался ответить в течение дня, я сделаю это. Я понимаю проблему, которую вы обсуждаете, но ответ, вероятно, должен зависеть от операционной системы, языка и библиотеки времени выполнения.
Общая идея заключается в том, что когда мышь выходит из строя, вы запускаете асинхронные вычисления. Это вычисление "блокирует" события и обрабатывает их в своем собственном цикле при получении, делая то, что вам нужно; это существует, когда кнопка мыши работает. Хотя это выглядит как обязательный поток, в действительности, когда вычисление "блокируется", оно просто возвращает управление тому, откуда оно было запущено (основной поток GUI, по-видимому, вызывает событие нажатия мыши, предположительно). Таким образом, состояние инкапсулируется в то, что выглядит как лексически локальная область вычислений. Это волшебство должно быть обработано во время выполнения языка, так что это насколько мы можем получить с ответом в зависимости от языка и ОС.
Что касается примера такой реализации, проверьте этот ответ и статью Томаса Петричека, в которой обсуждается ваш вопрос, но в узких условиях Windows, .NET и F#. Существует книга того же Perticek, Функциональное программирование в реальном мире: с примерами на F# и C#, где те же самые идеи, как ни удивительно, выражены на C#, обычно не считаются функциональным языком. Глава 16, если мне не изменяет память, твоя.
Что касается инкапсуляции состояния в языковой программе IP/OO, вы можете создать экземпляр класса в вашем обработчике mouse_down. Экземпляр регистрируется в среде выполнения, чтобы получать другие события мыши и пользовательского интерфейса, обрабатывать их, выполнять всю работу и, когда необходимо (мышь поднимается или система управления окнами отменяет режим захвата), отменяет регистрацию и уничтожает себя. Не так элегантно, как это допускает функциональный язык, но все же намного лучше, чем сохранение изменяемого состояния в общем классе пользовательского интерфейса.