基本上我有以下布局:Image of the GUI layout 这是一个BorderBane(黑色),带有一个菜单栏(红色),一个包含一些东西的容器,在左侧边栏(绿色)和一个嵌套在中心(橙色)内部的GridPane(灰色)
网格窗格的单元格充满了可以消失的图像视图(蓝色),重新填充后,它们可能堆叠在一起,通过平行转换从顶部掉入其位置。到目前为止,一切都很好,但是我想在网格窗格和菜单栏之间隐藏图像的一部分,但无法使其正常工作。有人知道如何解决这个问题吗?我也不会介意仅在部分内容突出时隐藏整个图片。
//编辑:
答案 0 :(得分:2)
如果检查GridPane的JavaDoc,您将看到:
GridPane默认情况下不会裁剪其内容,因此,如果孩子的最小尺寸使其无法适应其空间,则孩子的边界可能会超出其自身的边界。
对于Pane
类的每个孩子也是如此。因此,您将需要手动处理裁剪,为此需要使用方法setClip()
。
一种简单的实现方法是将Rectangle
与窗格的尺寸一起用于剪切。下面是一个完全符合此要求的代码:
public void clipChildren(Region region) {
final Rectangle clipPane = new Rectangle();
region.setClip(clipPane);
region.layoutBoundsProperty().addListener((ov, oldValue, newValue) -> {
clipPane.setWidth(newValue.getWidth());
clipPane.setHeight(newValue.getHeight());
});
}
说实话,我也不知道这一点。您可以阅读一篇很棒的文章,其中详细介绍了所有内容:JavaFX Pane Clipping
现在在我举一个完整的例子之前,我建议您使用Pane
而不是GridPane
。主要原因是您可以更好地操纵(单击,拖动等)控件。此外,一些免责声明,我不是游戏开发人员,因此下面的示例只是一个示例。
MainApp.java
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class MainApp extends Application {
@Override
public void start(Stage stage) throws Exception {
GameBoard gameBoard = new GameBoard();
BorderPane mainPane = new BorderPane();
Button restartButton = new Button("Restart");
restartButton.setOnAction(e -> {
gameBoard.restartGame();
});
FlowPane controlPane = new FlowPane();
controlPane.setAlignment(Pos.CENTER);
controlPane.getChildren().add(restartButton);
mainPane.setCenter(gameBoard);
mainPane.setBottom(controlPane);
stage.setScene(new Scene(mainPane, 600, 600));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
GameBoard.java
import java.util.ArrayList;
import java.util.Random;
import javafx.animation.ParallelTransition;
import javafx.animation.RotateTransition;
import javafx.animation.TranslateTransition;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
public class GameBoard extends StackPane {
private final int TILE_WIDTH = 60;
private final int TILE_HEIGHT = 60;
private final int WIDTH;
private final int HEIGHT;
private int rows;
private int columns;
private ArrayList<Image> tileImages = new ArrayList<Image>();
private final Pane gamePane = new Pane();
public GameBoard() {
this(9, 9);
}
public GameBoard(int rows, int columns) {
this.rows = rows;
this.columns = columns;
WIDTH = columns * TILE_WIDTH;
HEIGHT = rows * TILE_HEIGHT;
// set the Clipping
clipChildren(gamePane);
// set the background color and also fix the dimensions
gamePane.setStyle("-fx-background-color : #52033D");
gamePane.setMinSize(WIDTH, HEIGHT);
gamePane.setPrefSize(WIDTH, HEIGHT);
gamePane.setMaxSize(WIDTH, HEIGHT);
getChildren().add(gamePane);
initTilesImages();
fillTiles();
}
public void clipChildren(Region region) {
final Rectangle clipPane = new Rectangle();
region.setClip(clipPane);
// In case we want to make a resizable pane we need to update
// our clipPane dimensions
region.layoutBoundsProperty().addListener((ov, oldValue, newValue) -> {
clipPane.setWidth(newValue.getWidth());
clipPane.setHeight(newValue.getHeight());
});
}
public void restartGame() {
gamePane.getChildren().clear();
fillTiles();
}
private void initTilesImages() {
tileImages.add(new Image(this.getClass().getResource("/resources/redTile.png").toExternalForm()));
tileImages.add(new Image(this.getClass().getResource("/resources/greenTile.png").toExternalForm()));
tileImages.add(new Image(this.getClass().getResource("/resources/blueTile.png").toExternalForm()));
tileImages.add(new Image(this.getClass().getResource("/resources/purpleTile.png").toExternalForm()));
tileImages.add(new Image(this.getClass().getResource("/resources/whiteTile.png").toExternalForm()));
tileImages.add(new Image(this.getClass().getResource("/resources/yellowTile.png").toExternalForm()));
}
// Fill with random images
private void fillTiles() {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
ImageView tile = createTile(j, i);
gamePane.getChildren().add(tile);
}
}
}
// Create the ImageView which I call "tile"
private ImageView createTile(int x, int y) {
Random rand = new Random();
int index = rand.nextInt(tileImages.size());
ImageView img = new ImageView(tileImages.get(index));
img.setFitWidth(TILE_WIDTH);
img.setFitHeight(TILE_HEIGHT);
img.setTranslateX(x * TILE_WIDTH);
// set some rotation and transition
RotateTransition rt = new RotateTransition(Duration.millis(2000));
rt.setFromAngle(0);
rt.setToAngle(360);
TranslateTransition tt = new TranslateTransition(Duration.millis(2000));
tt.setFromY(TILE_HEIGHT * (y - rows));
tt.setToY(y * TILE_HEIGHT);
tt.play();
ParallelTransition pt = new ParallelTransition(img, tt, rt);
pt.play();
return img;
}
}
结果:
答案 1 :(得分:0)
这是JKostikiadis使用绑定的解决方案的简化版本:
private void clipChildren(Region region) {
Rectangle clip = new Rectangle();
clip.widthProperty().bind(region.widthProperty());
clip.heightProperty().bind(region.heightProperty());
region.setClip(clip);
}