Добавление EventHandler в ImageView, содержащийся в метке - PullRequest
0 голосов
/ 30 сентября 2018

Я недавно начал изучать Java FX и хочу создать собственную метку, внутри которой будет ImageView.

Это код для моей настраиваемой метки.

Image image = new Image(getClass().getResourceAsStream("/img/remove.png"), 20, 20, true, true);
ImageView removeImageView = new ImageView(image);

Label customLabel = new Label(labelText, removeImageView);
customLabel.setFont(Font.font("Arial", FontWeight.BOLD, 20));

ЭтоВот как выглядит мой пользовательский ярлык.

enter image description here

Теперь я хочу добавить щелчок мыши EventHandler в ImageView.Это мой код для обработки щелчков мыши.

removeImageView.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
      @Override
      public void handle(MouseEvent event) {
        System.out.println("Imageview Clicked");
      }
    });

Но когда я нажимаю на изображение cross, событие не захватывается.

Я немного поэкспериментировал и попыталсядобавить EventHandler к customLabel.Метка смогла зафиксировать щелчок мыши.

Мне кажется, что я сталкиваюсь с этой проблемой, потому что ImageView содержится внутри метки.Я хочу знать, является ли это ограничением для JFX или есть какой-то альтернативный способ достижения этой функциональности.Спасибо.

Ответы [ 3 ]

0 голосов
/ 30 сентября 2018

Еще один обходной путь для ImageView - прозрачность мыши (см. Ответ Slaw ) - это обработка события на ImageView родительском (Lable) и повторное его запуск:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class PropegateEvent extends Application {

    @Override
    public void start(Stage stage) {

        Image image = new Image("https://addons-media.operacdn.com/media/extensions/65/165965/1.1.0.0-rev1/icons/icon_64x64_6dd346d4c61d287ae74c612622d1353f.png");
        ImageView removeImageView = new ImageView(image);
        Label customLabel = new Label("rito", removeImageView);
        Pane root = new Pane(customLabel);
        stage.setScene(new Scene(root));

        //////////////////////////////////////////////////////////////
        //handle mouse event click on label -  refire it as image view event:
        customLabel.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> removeImageView.fireEvent(event));
        ///////////////////////////////////////////////////////////////

        removeImageView.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
              @Override
              public void handle(MouseEvent event) {
                System.out.println("Imageview Clicked");
                event.consume();
              }
            });
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
0 голосов
/ 30 сентября 2018

Один из способов справиться с этой ситуацией - использовать HBox.Вместо передачи ImageView в конструктор Label установите ImageView и Label в качестве дочерних узлов HBox

ImageView removeImageView = new ImageView(image); 
Label customLabel = new Label("rito");
customLabel.setFont(Font.font("Arial", FontWeight.BOLD, 20));


HBox hbox = new HBox(removeImageView,customLabel);
root.getChildren().add(hbox);

removeImageView.setOnMouseClicked(e->{
            System.out.println("ImageView clicked");
        });


customLabel.setOnMouseClicked(e->{
            System.out.println("Lable clicked");
        });
0 голосов
/ 30 сентября 2018

Похоже, это следствие исправления JDK-8117199 . fix добавил следующее к LabeledSkinBase#updateChildren():

// RT-19851 Only setMouseTransparent(true) for an ImageView.  This allows the button
// to be picked regardless of the changing images on top of it.
if (graphic instanceof ImageView) {
    graphic.setMouseTransparent(true);
}

Как вы можете видеть, когда графический элемент управления Labeled представляет собой ImageView, он устанавливается как мышьпрозрачный.Обходным путем будет установить прозрачность мыши ImageView обратно в false.

ImageView view = new ImageView();
view.mouseTransparentProperty().addListener((observable, oldVal, newVal) -> {
    if (newVal) {
        view.setMouseTransparent(false);
    }
});

Поскольку вы не используете CSS для изменения изображения в зависимости от состояния наведения / режима охраны, это не должно вызыватьпроблемы, связанные с ошибкой.Я был бы осторожен, хотя;на всякий случай.


Лучший обходной путь, упомянутый @fabian, - это обернуть ImageView в какой-то другой Node (например, Pane).

Label customLabel = new Label(labelText, new Pane(removeImageView));

Это делает изображение Pane, что означает, что специальная обработка ImageView в updateChildren() не выполняется.

...