【问题标题】:JavaFX imageview actionsJavaFX 图像视图操作
【发布时间】:2018-09-07 21:46:51
【问题描述】:

我正在尝试构建 MineSweeper 的副本,为此我正在尝试将一些预制图像(在 Photoshop 中制作的 100x100 像素)设置到图像视图中,然后单击隐藏它(以显示下面的数字)。没有太多复杂性——只是图像变得可见和不可见,我发现了很多问题和困难。

这可能是由于完全缺乏对 Javafx 的一般知识,但我什至按照教程进行操作,我仍然无法实现此功能。我将附上我的 Main.Java 代码、我的 sample.fxml 代码(虽然它不再被调用),然后是我试图在单击时隐藏的图像。

我(过去几天)对此进行了大量研究,但没有找到任何可以解决我问题的方法。

Main.java:

package sample;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

    ImageView button;
    @Override
    public void start(Stage primaryStage) throws Exception{
        primaryStage.setTitle("MineSweeper XP");
        button = new ImageView();

        button.setOnMouseClicked(new EventHandler<MouseEvent>)(){

            public void handle(MouseEvent event){

            }
        }

        StackPane layout = new StackPane();
        layout.getChildren().add(button);

        Scene scene = new Scene(layout,1000, 1000);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

sample.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="100.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <ImageView fx:id="button" fitHeight="150.0" fitWidth="100.0" pickOnBounds="true" preserveRatio="true">
         <image>
            <Image url="@../textures/Button_Custom.png" />
         </image>
      </ImageView>
   </children>
</AnchorPane>

The "Button" that will be used for all the MineSweeper keys

目前我的唯一目标是创建一个任意大小的窗口,我可以在其中将按钮放在任何地方,然后当用户单击该按钮时它就会消失。

【问题讨论】:

  • 您是否尝试将点击的ImageViewvisible 属性设置为false?如果你有,为什么这对你不起作用?
  • 您发布的代码毫无意义。你有FXML,没有Controller。带有Main 的代码不会加载FXML 或做任何事情。它只有一个空按钮处理程序。
  • 我之前的代码称为 .fxml 函数,但我删除了该部分以尝试创建按钮处理程序
  • 不要使用 ImageView 作为类似按钮的控件 - 而是使用带有 ImageView 作为图形的 Button 并在操作时更改它
  • @kleopatra 我个人认为使用 ImageView 作为按钮式控件没有任何问题。样式确实是唯一的区别,如果您想要的只是单击时消失的图像,则无需使用按钮...

标签: javafx imageview


【解决方案1】:

一种可能的解决方案是创建您自己的ImageView,其中包含用于鼠标点击的代码。

这是TileButton 类的示例:

class TileButton extends ImageView {

    public TileButton() {

        // Set parameters for the image
        Image graphic = new Image("minesweeper/tile.png");
        setImage(graphic);
        setFitWidth(24);
        setFitHeight(24);

        // When this button is click, set its visibility to false.
        setOnMouseClicked(e -> {
            setVisible(false);
        });
    }
}

使用这个自定义类,“按钮”的所有逻辑都包含在TileButton 本身中。

现在,您可以在每个单元格中使用 GridPaneStackPane 容器填充您的雷区。 StackPane 允许您将节点堆叠在一起。因此,在每个StackPane 中放置一个带有您想要的号码的Label,然后在其上添加新的TileButton

下面是一个完整的示例应用程序来演示。请注意,我在这里没有实现任何实际的游戏逻辑,只是提供一个示例,您可以复制/粘贴并查看实际操作。我也没有花时间对ImageView 进行格式化和样式设置,但您也可以使用 CSS 使其像标准按钮一样。

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // GridPane to hold the cells
        GridPane gridPane = new GridPane();
        gridPane.setGridLinesVisible(true);
        gridPane.setHgap(2);
        gridPane.setVgap(2);

        // Populate the Gridpane with a 10x10 grid
        int number = 0;
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {

                // Add a new StackPane for each grid cell. The Stackpane will hold a number and the
                // TileButton. When the TileButton is clicked, it disappears, revealing the number below
                StackPane pane = new StackPane();
                pane.getChildren().add(new Label(String.valueOf(number)));
                pane.getChildren().add(new TileButton());

                gridPane.add(pane, j, i);

                // Just increment our sample number
                number++;

            }
        }

        root.getChildren().add(gridPane);
        primaryStage.setScene(new Scene(root));

        primaryStage.show();
    }
}

class TileButton extends ImageView {

    public TileButton() {

        // Set parameters for the image
        Image graphic = new Image("minesweeper/tile.png");
        setImage(graphic);
        setFitWidth(24);
        setFitHeight(24);

        // When this button is click, set its visibility to false.
        setOnMouseClicked(e -> {
            setVisible(false);
        });
    }
}

上面的示例应用程序产生了这个:

注意我没有为此使用 FXML,因为在 Java 中创建多个自定义对象的网格比 FXML 简单得多。


根据 kleopatra 的建议,这可以改用自定义 Button 来完成。使用下面的新 TileButton 类,您可以使用 gridPane.add(new TileButton(String.valueOf(number)), j, i); 在我们的循环中添加按钮:

class TileButton extends Button {

    public TileButton(String text) {

        // Set the button's size
        setPrefSize(24,24);
        setStyle("-fx-padding: 0");

        // Set the graphic to our tile.png image
        setGraphic(new ImageView("sample/done/minesweeper/tile.png"){{
            setFitWidth(24);
            setFitHeight(24);
        }});

        // Set the button to display only our graphic initially
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

        // Set the action to remove the graphic when the button is clicked
        setOnAction(event -> {
            setGraphic(new Label(text));
        });

    }
}

【讨论】:

  • @kleopatra 这个问题是关于使用 ImageView 的。这可以很容易地使用带有 CSS 样式的 Button 来删除填充,但这不是 OP 所要求的。
  • 那是因为他/她是初学者,还不知道要使用哪些控件 - 你知道得更好;)
  • @kleopatra - 我已经更新了我的答案,包括一个自定义的Button 选项供您批评。 :P
  • 更好 - 但没有理由扩展 Button。只需配置它:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-09
  • 1970-01-01
  • 1970-01-01
  • 2011-11-15
相关资源
最近更新 更多