我有一个JavaFX 2
GUI,其中包含HBox
填充GridPane
的一个单元格。我的所有组件都是动态调整大小的。这显示没问题。
第一个问题:我想将HBox
的内容剪切到它们所在的GridPane
单元格的边缘,这样就不会显示任何溢出,但我可以'弄清楚如何。我已经尝试将我的HBox
的剪辑设置为相同大小的矩形,但这不起作用。我猜是因为它使用了用于布局的尺寸,而不是显示的尺寸。我应该修剪GridPane
本身,还是至少使用其属性?
第二个问题(奖励点):剪辑如何与Node
的翻译和缩放相互作用?
感谢您的帮助。
答案 0 :(得分:3)
我尝试了一些简短的程序,尝试在GridPane中剪切节点。 没有任何剪辑尝试实现我真的非常喜欢这一点,虽然它们大多数以某种方式或其他方式工作,取决于要求。
最接近您的描述的剪辑尝试是最后一个将剪切的节点包装在具有自己的大小说明符的区域中,以便剪切区域的布局与应用于节点的剪辑节点的大小相匹配。
class ClippedNode extends Region {
private final Node content;
private final double width;
private final double height;
ClippedNode(Node content, double width, double height) {
this.content = content;
this.width = width;
this.height = height;
content.setClip(new Rectangle(width, height));
getChildren().setAll(content);
}
@Override protected double computeMinWidth(double d) { return width; }
@Override protected double computeMinHeight(double d) { return height; }
@Override protected double computePrefWidth(double d) { return width; }
@Override protected double computePrefHeight(double d) { return height; }
@Override protected double computeMaxWidth(double d) { return width; }
@Override protected double computeMaxHeight(double d) { return height; }
}
下面提供了演示各种剪辑方法的完整可执行示例:
import java.util.Iterator;
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class GridClipping extends Application {
String buttonText[] = "The quick brown fox jumped over the lazy dog".split(" ");
String[] colors = { "aqua", "coral", "cornsilk", "cornflowerblue" };
@Override public void start(Stage stage) throws Exception {
final GridPane grid = new GridPane();
grid.addRow(0, createHBox("aqua"), createHBox("coral"));
grid.addRow(1, createHBox("cornsilk"), createHBox("cornflowerblue"));
grid.setStyle("-fx-border-color: red;");
final GridPane gridWithClippedBoxes = new GridPane();
gridWithClippedBoxes.addRow(0, createClipWrappedHBox("aqua"), createClipWrappedHBox("coral"));
gridWithClippedBoxes.addRow(1, createClipWrappedHBox("cornsilk"), createClipWrappedHBox("cornflowerblue"));
gridWithClippedBoxes.setStyle("-fx-border-color: red;");
final RadioButton noClip = new RadioButton("No Clip");
final RadioButton restrictGridSize = new RadioButton("Restrict Max Grid Size (doesn't work)");
final RadioButton clipGrid = new RadioButton("Clip Grid");
final RadioButton clipHBoxes = new RadioButton("Clip HBoxes");
final RadioButton clipWrappedHBoxes = new RadioButton("Clip Wrapped HBoxes");
final ToggleGroup clipRadios = new ToggleGroup();
clipRadios.getToggles().setAll(
noClip,
restrictGridSize,
clipGrid,
clipHBoxes,
clipWrappedHBoxes
);
final Rectangle gridClip = new Rectangle(0, 0, 100, 25);
clipGrid.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override public void changed(ObservableValue<? extends Boolean> ov, Boolean wasClipped, Boolean clipped) {
if (clipped != null) {
if (clipped) {
grid.setClip(gridClip);
} else {
grid.setClip(null);
}
}
}
});
restrictGridSize.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override public void changed(ObservableValue<? extends Boolean> ov, Boolean wasClipped, Boolean clipped) {
if (clipped != null) {
if (clipped) {
// this does not work in our case.
// the minimum size of the grid components > the max size of the grid.
// so the grid expands in size to fit the minimum size of it's components anyway.
grid.setMaxSize(100, 25);
} else {
grid.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
}
}
}
});
clipHBoxes.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override public void changed(ObservableValue<? extends Boolean> ov, Boolean wasClipped, Boolean clipped) {
if (clipped != null) {
if (clipped) {
for (Node gridCell: grid.getChildren()) {
Rectangle cellClip = new Rectangle(100, 12);
gridCell.setClip(cellClip);
}
} else {
for (Node gridCell: grid.getChildren()) {
gridCell.setClip(null);
}
}
}
}
});
final VBox layout = new VBox(10);
clipWrappedHBoxes.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override public void changed(ObservableValue<? extends Boolean> ov, Boolean wasClipped, Boolean clipped) {
if (clipped != null) {
if (clipped) {
layout.getChildren().set(0, gridWithClippedBoxes);
} else {
layout.getChildren().set(0, grid);
}
}
}
});
noClip.fire();
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
layout.getChildren().setAll(
grid,
noClip,
restrictGridSize,
clipGrid,
clipHBoxes,
clipWrappedHBoxes
);
stage.setScene(new Scene(layout));
stage.show();
}
private Region createHBox(String webColor) {
HBox box = new HBox(5);
box.setStyle("-fx-background-color: " + webColor + ";");
for (String text: buttonText) {
box.getChildren().add(new Text(text));
}
box.setOpacity(0.5);
return box;
}
private Region createClipWrappedHBox(String webColor) {
return new ClippedNode(createHBox(webColor), 100, 12);
}
class ClippedNode extends Region {
private final Node content;
private final double width;
private final double height;
ClippedNode(Node content, double width, double height) {
this.content = content;
this.width = width;
this.height = height;
content.setClip(new Rectangle(width, height));
getChildren().setAll(content);
}
@Override protected double computeMinWidth(double d) { return width; }
@Override protected double computeMinHeight(double d) { return height; }
@Override protected double computePrefWidth(double d) { return width; }
@Override protected double computePrefHeight(double d) { return height; }
@Override protected double computeMaxWidth(double d) { return width; }
@Override protected double computeMaxHeight(double d) { return height; }
}
public static void main(String[] args) { Application.launch(args); }
}