Java 自定义最小化按钮不调用MouseLeave事件

Java 自定义最小化按钮不调用MouseLeave事件,java,javafx,Java,Javafx,我有一个带有StageStyle.TRANSPARENT(没有默认按钮)的简单stage。 因此,我尝试创建自己的自定义按钮,每个按钮由一个ImageView表示,并激活下一个事件:setonmouseintered,setonmouseexted,当然还有setOnMouseClicked 问题在于最小化按钮。下面是一个简单的实现 ImageView.setOnMouseClicked((MouseEvent event) -> { stage.setIconified(true

我有一个带有
StageStyle.TRANSPARENT
(没有默认按钮)的简单stage。 因此,我尝试创建自己的自定义按钮,每个按钮由一个
ImageView
表示,并激活下一个事件:
setonmouseintered
setonmouseexted
,当然还有
setOnMouseClicked

问题在于最小化按钮。下面是一个简单的实现

ImageView.setOnMouseClicked((MouseEvent event) -> {
    stage.setIconified(true);
});
让我们假设我的ImageView是一个白色矩形。在鼠标进入事件时,它将其颜色更改为黑色。在鼠标退出时,它将返回到白色

单击
ImageView
时,窗口将最小化,直到现在一切都可以正常工作

问题是,当应用程序恢复(最大化)时,最小化的自定义按钮会使用颜色黑色(表示按钮的颜色悬停),而不是白色(未聚焦时的默认颜色)

另外,
重新定位
设置图像
onMouseClicked
处理程序中的所有内容似乎都被
设置无效(true)所剪切

任何帮助都将不胜感激

感谢您抽出时间阅读此文

更新以澄清一点问题

正如你所观察到的,一切都很完美。当按下“-”按钮(最小化按钮)时,当应用程序恢复时,它将保持在悬停模式,直到鼠标光标再次悬停该按钮(然后一切恢复正常)。遗憾的是,CSS方法或图像视图上的事件侦听器似乎都不能解决这个问题

更新加载的代码

这是一个简单的单源文件,只有一个调用最小化的按钮

package application;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;


public class Main extends Application {
    private Scene scene;
    private Stage stage;

    @Override
    public void start(Stage stage) {
        try {
            this.stage = stage;
            stage.initStyle(StageStyle.TRANSPARENT);
            stage.setAlwaysOnTop(true);

            stage.setFullScreen(true);
            stage.setFullScreenExitHint("");

            createScene(stage);

            stage.setScene(scene);
            stage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private void createScene(Stage stage) {
        Pane layer = new Pane();
        layer.setPickOnBounds(false);

        scene = new Scene(layer, 800, 600);
        scene.getStylesheets().add("application/application.css");

        layer.getChildren().add(buildMinimizeImage());
    }

    private ImageView buildMinimizeImage() {
        ImageView imv = new ImageView();
        int width = 43 ;
        int height = 36;

        imv.setId("myImage");

        imv.setFitWidth(width);
        imv.setFitHeight(height);

        imv.setOnMouseClicked((MouseEvent event) -> {
            stage.setIconified(true);
        });

        imv.relocate(100, 100);

        return imv;
    }

    public static void main(String[] args) {
        launch(args);
    }
}
而且application.css也非常简单

#myImage
{
    -fx-image: url("minimize.png");
}
#myImage:hover
{
    -fx-image: url("minimizeIn.png");
}
这个问题可以在Ubuntu 14.04和Windows 10上重现。我认为这不是操作系统的问题

已解决

请查找并附上Harry Mitchel解决方案(再次感谢)。这是完全可行的

如果您想通过添加setOnMousePressed事件来修复上面的代码,请执行以下操作

imv.setOnMousePressed((MouseEvent event) -> {
    imv.setImage(image);
});

你的问题不是很清楚(虽然不是很清楚),所以我将尝试解决你的问题

我假设您的颜色更改是通过
ImageView.setonmouseintered()
ImageView.setonmousexited()
完成的。如果是这样的话,你应该改用CSS

.myImageView
{
    -fx-image: url("my_white_image.png");
}
.myImageView:hovered
{
    -fx-image: url("my_black_image.png");
}

对于你的“PS”部分中的内容,我无法理解,因此我无法给出任何建议。

你可以听听Stage类的最大化属性。在changed()方法中,设置ImageView的图像

stage.maximizedProperty().addListener(new ChangeListener<Boolean>() {

    @Override
    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
        //Display the desired icon here.
    }
});
下面是一个使用MinimizeButton类的示例应用程序

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class CustomMinimize extends Application {
    @Override
    public void start(Stage stage) {        
        Image imgWhite = new Image(getClass().getResourceAsStream("imgWhite.png"));  //your image here
        Image imgGreen = new Image(getClass().getResourceAsStream("imgGreen.png"));  //your hover image here
        MinimizeButton btnMinimize = new MinimizeButton(imgWhite, imgGreen, stage);
        btnMinimize.setStyle("-fx-background-color: black;");
        btnMinimize.setPrefSize(50, 50);
        Button btnExit = new Button("X");
        btnExit.setMinSize(50,50);
        btnExit.setOnAction((ActionEvent event) -> {
            System.exit(0);
        });
        btnExit.setStyle("-fx-background-color: black;");
        HBox hBox = new HBox();
        hBox.setSpacing(2);
        hBox.getChildren().addAll(btnMinimize, btnExit);

        AnchorPane anchorPane = new AnchorPane();
        anchorPane.getChildren().addAll(hBox);
        AnchorPane.setRightAnchor(hBox, 5.0);
        AnchorPane.setTopAnchor(hBox, 5.0);

        Scene scene = new Scene(anchorPane);
        stage.initStyle(StageStyle.TRANSPARENT);

        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

嘿,洁,谢谢你的回复。不幸的是,即使使用css,这个问题仍然具有说服力。在再次最大化后,我仍然停留在悬停模式。即使在“setOnMouseClicked”处理程序中,我正在更改按钮位置(然后调用),更新(重新分配)也将在我再次悬停最小化按钮(在旧位置)后考虑。按钮保持冻结,直到它被悬停并且最小化之前的所有更新都被考虑在内。你需要发布所有与按钮事件处理程序相关的东西,任何css。如果在按钮的路由树中的其他节点中有事件处理程序,也包括该事件处理程序。当使用其他方法最小化窗口时,是否也存在此问题?(例如windows 10中的windows按钮+向下)。当我最小化它时,我的应用程序将显示“悬停”状态,但在恢复后,它将立即重新绘制。这可能是由于javafx中的一个bug造成的?你在用最新的JVM进行测试吗?我有javafx版本8.0.111-b14,Java8,运行在ubuntu 14.04上。悬停状态也会显示出来,但问题是当我恢复它时,对我来说,重新绘制不会被触发。在这种情况下,您应该测试基本的javafx悬停是否正常工作,例如正常按钮。这可能是javafx错误。我尝试使用按钮而不是ImageView。同样的效果。我将安装一台装有Windows 10的电脑,看看是否有同样的行为。非常感谢您的回答。我也试过:(不好……正如我问其他人的那样,如果你能给我一个定制最小化按钮的可行示例,我将不胜感激。我真的认为这是我的版本或错误的方法……非常感谢。你的解决方案是可行的,正是我所寻找的。我还不知道为什么这样做有效,为什么其他人不这样做,因为f假装我只是快速扫描并尝试一下。稍后我可能会回答为什么不工作。总体而言,非常感谢您提供了这个干净可行的解决方案。我很高兴我能提供帮助。在MinimizeButton类中,在ActionEvent中,我将按钮的悬停图像切换回原始图像。这就是区别。我喜欢JavaFX,希望查看它的使用情况。嘿,Harry,您的示例正在运行,并且是有效的,因为您扩展了按钮以进行最小化(这很好)。我的ImageView的setOnMouseClicked有点错误。为了解决这个问题,我还使用imv.setOnMousePressed((MouseeEvent事件)->{imv.setImage(image)欺骗了它; });
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class CustomMinimize extends Application {
    @Override
    public void start(Stage stage) {        
        Image imgWhite = new Image(getClass().getResourceAsStream("imgWhite.png"));  //your image here
        Image imgGreen = new Image(getClass().getResourceAsStream("imgGreen.png"));  //your hover image here
        MinimizeButton btnMinimize = new MinimizeButton(imgWhite, imgGreen, stage);
        btnMinimize.setStyle("-fx-background-color: black;");
        btnMinimize.setPrefSize(50, 50);
        Button btnExit = new Button("X");
        btnExit.setMinSize(50,50);
        btnExit.setOnAction((ActionEvent event) -> {
            System.exit(0);
        });
        btnExit.setStyle("-fx-background-color: black;");
        HBox hBox = new HBox();
        hBox.setSpacing(2);
        hBox.getChildren().addAll(btnMinimize, btnExit);

        AnchorPane anchorPane = new AnchorPane();
        anchorPane.getChildren().addAll(hBox);
        AnchorPane.setRightAnchor(hBox, 5.0);
        AnchorPane.setTopAnchor(hBox, 5.0);

        Scene scene = new Scene(anchorPane);
        stage.initStyle(StageStyle.TRANSPARENT);

        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}