JavaFX Dialog.showAndWait () в обработчике ButtonEvent.MOUSE_PRESSED кнопки отменяет следующие события MOUSE_RELEASED и MOUSE_CLICKED - PullRequest
1 голос
/ 28 апреля 2019

Проблема кодирования (это ошибка?) Обобщена:

Если пользовательское взаимодействие в форме Dialog.showAndWait() используется внутри MouseEvent.MOUSE_PRESSED из Button, кажется, что следующие MouseEvents (MOUSE_RELEASED, MOUSE_CLICKED) как-то "отменены". Действие кнопки не вызывается, визуально кнопка заблокирована в псевдоклассе «нажата» или «нажата / активирована».

Вариант использования (как я столкнулся с проблемой): я разрабатываю более сложный табличный элемент управления в JavaFX. Мне нужна некоторая проверка отдельных простых элементов управления (например, TextField и т. Д.) Для предотвращения незаконного контента. Чтобы быть более точным: мне нужна проверка группы элементов управления , практически «ряд» различных элементов управления (в табличном виде), то есть действительность зависит от содержания (значения) более элементы управления различного типа (текстовые поля, комбо, флажки и т. д.). Моя идея заключалась в том, что было бы хорошо сделать проверку в focusedProperty ChangeListener. Просто: недопустимое состояние в порядке, когда элемент управления все еще имеет фокус, и пользователь использует элемент управления; как только пользователь «покидает» элемент управления (фокус теряется), это может быть подходящее время для проверки. Или, в моем случае, точно: проверка должна выполняться, когда фокус перемещается за пределы проверенной группы / ряда элементов управления (на другую строку, другие элементы управления и т. Д.). Проблема в том, что когда проверка использует взаимодействие с пользователем с использованием модального диалога - javafx.scene.control.Dialog, это каким-то образом портит обработку MouseEvent в элементе управления, которая получила фокус (щелчок мыши) от проверенного элемента управления.

См. Очень простую демонстрацию (не проверки каждого ряда, а) того факта, что выполнение Dialog.showAndWait () во время обработки события MOUSE_PRESSED портит (отменяет?) Следующую обработку MouseEvent:

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class MouseEventsTest extends Application {    
    @Override public void start(Stage primaryStage) {
        TextField textField = new TextField("Test");
        textField.focusedProperty().addListener((ob, ov, nv) -> {
            if (!nv) {
                System.out.println("TextField: focus lost");
                (new Alert(AlertType.INFORMATION, "Focus lost", ButtonType.OK)).showAndWait();
            }        
        });        

        Button button = new Button("Button 1");
        button.setStyle("-fx-pressed-base: red;"); // to visually demonstrate "pressed" pseudocl. lock (in Modena)
        // to debug MouseEvents:
        button.addEventHandler(MouseEvent.ANY, e -> {
            if (e.getEventType() != MouseEvent.MOUSE_MOVED) {   // MOUSE_MOVED events too frequent and irrelevant
                System.out.println("Button 1 - MouseEvent handled: " + e.getEventType());
            }
        });
        button.setOnAction(e -> {
            System.out.println("Button 1 action");
        });

        VBox root = new VBox(5);
        root.setPadding(new Insets(5));
        root.getChildren().addAll(textField, button, new Button("Button 2"));
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setTitle("Test App");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Первоначально TextField имеет фокус. Нажмите Button 1: фокус на TextField потерян (поскольку событие MousePressed кнопки приводит к requstFocus() на этой кнопке, что приводит к «событию потери фокуса» - focusedProperty меняется на false - в TextField), появится диалоговое окно, нажмите ОК. Как вы можете видеть, информация отладки из обработчика MouseEvent событий Button 1, MOUSE_RELEASED и MOUSE_CLICKED не попадает в обработчик. Визуально кнопка заблокирована в нажатом состоянии (красная подсветка используется для демонстрации).

Затем попробуйте: нажмите Button 2, Button 2, чтобы получить фокус, затем нажмите Button 1 - MOUSE_RELEASED и MOUSE_CLICKED события обрабатываются OK в этом случае. Ничто, вероятно, не «прерывается» диалогом .showAndWait().

EDIT:

В целях отладки я добавил Dialog.showAndWait() непосредственно к Button 1 addEventHandler(MouseEvent.MOUSE_PRESSED...), удалив его из focusProperty ChangeListener, и поведение такое же, но, что удивительно, кнопка заблокирована не в нажатом состоянии ", но в состоянии" нажата + вооружена ".

Это ошибка?

Или по общему правилу никогда нельзя взаимодействовать с пользователем в ожидании MouseEvents?

Если это так, каково стандартное правильное решение или лучшее решение для проверки или другого взаимодействия с пользователем внутри обработчика MouseEvent?

Протестировано в JavaFX 11.

Пример кода, конечно, только очень упрощенная демонстрация ...

...