Java 将EventHandler添加到标签中包含的ImageView

Java 将EventHandler添加到标签中包含的ImageView,java,javafx,imageview,eventhandler,mouseclick-event,Java,Javafx,Imageview,Eventhandler,Mouseclick Event,我最近开始探索JavaFX,并希望创建一个自定义标签,其中包含一个ImageView 这是我的自定义标签的代码 Image image = new Image(getClass().getResourceAsStream("/img/remove.png"), 20, 20, true, true); ImageView removeImageView = new ImageView(image); Label customLabel = new Label(labelText, remove

我最近开始探索JavaFX,并希望创建一个自定义标签,其中包含一个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));
这就是我的自定义标签的外观

现在我想向ImageView添加鼠标单击事件处理程序。这是我处理鼠标点击的代码

removeImageView.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
      @Override
      public void handle(MouseEvent event) {
        System.out.println("Imageview Clicked");
      }
    });
removeImageView.addEventHandler(MouseEvent.MOUSE_单击,新建事件处理程序(){
@凌驾
公共无效句柄(MouseeEvent事件){
System.out.println(“单击Imageview”);
}
});
但是,当我单击
十字
图像时,事件没有被捕获

我做了一点实验,试图向
customLabel
添加一个EventHandler。标签能够捕捉鼠标点击


在我看来,我面临这个问题是因为ImageView包含在标签中。我想知道的是,这是对JFX的限制,还是有其他方法可以实现这一功能。谢谢。

这似乎是修复的结果。将以下内容添加到
LabeledSkinBase#updateChildren()

如您所见,当标签为的控件的图形为图像视图时,它被设置为鼠标透明。解决方法是将
ImageView
的鼠标透明度设置回false

ImageView view = new ImageView();
view.mouseTransparentProperty().addListener((observable, oldVal, newVal) -> {
    if (newVal) {
        view.setMouseTransparent(false);
    }
});
由于您没有使用CSS根据悬停/待命状态更改图像,因此不应导致与错误相关的问题。不过,我会谨慎行事;以防万一


@fabian提到的一个更好的解决方法是将
图像视图
包装在其他一些
节点
(例如
窗格
)中


这使图形成为一个
窗格
,这意味着
updateChildren()
中的特殊
ImageView
处理不会发生。

这似乎是修复的结果。将以下内容添加到
LabeledSkinBase#updateChildren()

如您所见,当标签为的控件的图形为图像视图时,它被设置为鼠标透明。解决方法是将
ImageView
的鼠标透明度设置回false

ImageView view = new ImageView();
view.mouseTransparentProperty().addListener((observable, oldVal, newVal) -> {
    if (newVal) {
        view.setMouseTransparent(false);
    }
});
由于您没有使用CSS根据悬停/待命状态更改图像,因此不应导致与错误相关的问题。不过,我会谨慎行事;以防万一


@fabian提到的一个更好的解决方法是将
图像视图
包装在其他一些
节点
(例如
窗格
)中


这使得图形成为一个
窗格
,这意味着在
updateChildren()
中不进行特殊的
ImageView
处理。

另一个鼠标透明的
ImageView
解决方法是处理
ImageView
父级(
标签
)上的事件并重新触发它:

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);
    }
}
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.control.Label;
导入javafx.scene.image.image;
导入javafx.scene.image.ImageView;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.Pane;
导入javafx.stage.stage;
公共类PropegateEvent扩展应用程序{
@凌驾
公众假期开始(阶段){
图像=新图像(“https://addons-media.operacdn.com/media/extensions/65/165965/1.1.0.0-rev1/icons/icon_64x64_6dd346d4c61d287ae74c612622d1353f.png");
ImageView removeImageView=新的ImageView(图像);
标签customLabel=新标签(“rito”,removeImageView);
窗格根=新窗格(自定义标签);
舞台场景(新场景(根));
//////////////////////////////////////////////////////////////
//处理鼠标事件单击标签-将其重新刷新为图像视图事件:
customLabel.addEventHandler(MouseEvent.MOUSE_单击,事件->removeImageView.fireEvent(事件));
///////////////////////////////////////////////////////////////
removeImageView.addEventHandler(单击MouseEvent.MOUSE_,新建EventHandler()){
@凌驾
公共无效句柄(MouseeEvent事件){
System.out.println(“单击Imageview”);
event.consume();
}
});
stage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}

另一个鼠标透明的
ImageView
解决方案(请参阅)是处理
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);
    }
}
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.control.Label;
导入javafx.scene.image.image;
导入javafx.scene.image.ImageView;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.Pane;
导入javafx.stage.stage;
公共类PropegateEvent扩展应用程序{
@凌驾
公众假期开始(阶段){
图像=新图像(“https://addons-media.operacdn.com/media/extensions/65/165965/1.1.0.0-rev1/icons/icon_64x64_6dd346d4c61d287ae74c612622d1353f.png");
ImageView removeImageView=新的ImageView(图像);
标签customLabel=新标签(“rito”,removeImageView);
窗格根=新窗格(自定义标签);
舞台场景(新场景(根));
//////////////////////////////////////////////////////////////
//处理鼠标事件单击标签-将其重新刷新为图像视图事件:
customLabel.addEventHandler(MouseEvent.MOUSE_单击,事件->removeImageView.fireEvent(事件));
///////////////////////////////////////////////////////////////
removeImageView.addEventHandler(单击MouseEvent.MOUSE_,新建EventHandler()){
@凌驾
公共无效句柄(MouseeEvent事件){
System.out.println(“单击Imageview”);
event.consume();
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");
        });