javafx - JavaFX 图像视图操作
问题描述
我正在尝试构建 MineSweeper 的副本,为此我尝试将一些预制图像(在 Photoshop 中制作的 100x100 像素)设置到图像视图中,然后单击隐藏它(以显示下面的数字)。没有太多复杂性——只是图像变得可见和不可见,我发现了很多问题和困难。
这可能是由于完全缺乏对 Javafx 的一般知识,但我什至按照教程进行操作,我仍然无法实现此功能。我将附上我的 Main.Java 代码、我的sample.fxml
代码(虽然它不再被调用),然后是我试图在单击时隐藏的图像。
我对此(过去几天)进行了大量研究,但没有找到任何可以解决我问题的方法。
主.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);
}
}
示例.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>
在这个特定时刻,我的唯一目标是创建一个任意大小的窗口,我可以在其中将按钮放在任何地方,然后当用户单击该按钮时它就会消失。
解决方案
一种可能的解决方案是创建自己的解决方案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
自身中。
GridPane
现在,您可以在每个单元格中使用一个StackPane
容器填充您的雷区。允许您将StackPane
节点堆叠在一起。因此,Label
在每个中放置一个带有您想要的数字的数字StackPane
,然后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));
});
}
}
推荐阅读
- javascript - 系列工具提示中的 Echart 图标
- c - 多次重用原始套接字或创建新套接字
- ssis - 错误 Odatasource 编辑器 System.Net.HttpWebresponse
- angular - Angular 静态注入器错误 - 没有 API 提供者
- php - codeigniter 不返回 json/ajax 响应
- ios - UITableView 逐个单元格更改图像和标题位置
- javascript - 将元素添加到传递的 jQuery 选择器
- sockets - 如何使用 Overbyte ICS 获取 500 错误的详细信息
- react-native - 如何在本机反应中清除抽屉导航器内的屏幕
- javascript - 在一天中的某个时间自动在我的网站上播放多个视频