如何在 JavaFX 中显示非矩形的窗格?
How to display Pane with non-rectangle shape in JavaFX?
我在 JavaFX 中遇到了问题。
这是Jasperserver(一种服务器)、Adhoc-Model(一种服务器型号)中显示的内容。
Image: Jasperserver Adhoc Layout
Image: Inner HTML Code
如你所见,粉色区域,是一种HTML
标签。它可以显示 UI 非矩形。喜欢俄罗斯方块吗?
但是,我试图在 JavaFX 中做同样的事情但失败了。
我用了一个FlowPane作为Pane A,然后在Pane A中放了一些Label。然后我用了一点FlowPane作为Pane B,也将一些Label放入Pane B。最后,我将Pane B放入Pane A。
如下图所示
Image: Shown in JavaFX
如您所见,我无法显示非矩形的窗格 B。而且我认为做到这一点并不容易。
有人可以帮助我吗?您的回答将不胜感激。非常感谢。
如果有人需要我的代码,请告诉我。我会重写一些简单的代码放在这里
非常感谢@James_D。
我编写了一个自定义窗格,它扩展了 FlowPane,并覆盖了 layoutChildren() 函数。
有效!
以下是我的代码:
import java.util.ArrayList;
import java.util.List;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
public class LayoutFlowPane extends FlowPane {
private class Child {
Node node;
double x, y, w, h;
double blft, midy;
public Child(Node node,
double x, double y, double w, double h,
double blft, double midy) {
super();
this.node = node;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.blft = blft;
this.midy = midy;
}
}
private List<Child> children = new ArrayList<>();
private List<Double> midys = new ArrayList<>();
public LayoutFlowPane() {
super();
}
@Override protected void layoutChildren() {
super.layoutChildren();
Insets insets = getInsets();
double width = getWidth();
double height = getHeight();
double top = insets.getTop();
double left = insets.getLeft();
double bottom = insets.getBottom();
double right = insets.getRight();
double maxw = width - left - right;
double maxh = height - top - bottom;
double hgap = snapSpace(this.getHgap());
double vgap = snapSpace(this.getVgap());
storeChildren();
adjustChildren(maxw, maxh, hgap, vgap);
children.forEach(child -> {
layoutInArea(
child.node, child.x, child.y,
child.w, child.h, child.blft, getMargin(child.node),
getColumnHalignmentInternal(), getRowValignmentInternal()
);
});
}
private void storeChildren() {
children = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i ++) {
Node child = getChildren().get(i);
double x = child.getLayoutX();
double y = child.getLayoutY();
double w = 0;
double h = 0;
if (child instanceof Region) {
Region region = (Region) child;
w = region.getWidth();
h = region.getHeight();
} else {
throw new UnknowTypeException("Unknow type found.");
}
double blft = child.getBaselineOffset();
double midy = (y + y + h) / 2;
Child newChild = new Child(child, x, y, w, h, blft, midy);
children.add(newChild);
}
midys = new ArrayList<>();
for (int i = 0; i < children.size(); i ++) {
Child child = children.get(i);
if (midys.isEmpty() || midys.get(midys.size()-1) != child.midy) {
midys.add(child.midy);
}
}
}
private void adjustChildren(double maxw, double maxh, double hgap, double vgap) {
for (int i = 1; i < children.size(); i ++) { // begin with 1
Child pc = children.get(i-1);
Child ch = children.get(i);
boolean bothGridPane = (pc.node instanceof GridPane) && (ch.node instanceof GridPane);
double x = pc.x + pc.w + (bothGridPane ? 0 : hgap);
double midy;
if (x + ch.w <= maxw) { // ThisLine
midy = pc.midy;
ch.x = x;
ch.y = gety(ch.y, ch.midy, midy);
ch.midy = midy;
} else { // NextLine
midy = getNextMidy(pc.midy);
ch.x = children.get(0).x;
ch.y = gety(ch.y, ch.midy, midy);
ch.midy = midy;
}
}
}
private double getNextMidy(double midy) {
for (int i = 0; i < midys.size(); i ++) {
if (i + 1 < midys.size() && midys.get(i) == midy && midys.get(i+1) != midy) {
return midys.get(i+1);
} else if (i + 1 == midys.size() && midys.get(i) == midy) {
return midys.get(i);
}
}
throw new NotFoundException("Next midy not found.");
}
private double gety(double oldy, double oldMidy, double newMidy) {
return oldy + (newMidy - oldMidy);
}
private HPos getColumnHalignmentInternal() {
HPos localPos = getColumnHalignment();
return null == localPos ? HPos.LEFT : localPos;
}
private VPos getRowValignmentInternal() {
VPos localPos = getRowValignment();
return null == localPos ? VPos.CENTER : localPos;
}
private class UnknowTypeException extends RuntimeException {
private static final long serialVersionUID = 1L;
public UnknowTypeException(String message) {
super(message);
}
}
private class NotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public NotFoundException(String message) {
super(message);
}
}
}
我在 JavaFX 中遇到了问题。
这是Jasperserver(一种服务器)、Adhoc-Model(一种服务器型号)中显示的内容。
Image: Jasperserver Adhoc Layout
Image: Inner HTML Code
如你所见,粉色区域,是一种HTML
但是,我试图在 JavaFX 中做同样的事情但失败了。
我用了一个FlowPane作为Pane A,然后在Pane A中放了一些Label。然后我用了一点FlowPane作为Pane B,也将一些Label放入Pane B。最后,我将Pane B放入Pane A。
如下图所示
Image: Shown in JavaFX
如您所见,我无法显示非矩形的窗格 B。而且我认为做到这一点并不容易。
有人可以帮助我吗?您的回答将不胜感激。非常感谢。
如果有人需要我的代码,请告诉我。我会重写一些简单的代码放在这里
非常感谢@James_D。
我编写了一个自定义窗格,它扩展了 FlowPane,并覆盖了 layoutChildren() 函数。
有效!
以下是我的代码:
import java.util.ArrayList;
import java.util.List;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
public class LayoutFlowPane extends FlowPane {
private class Child {
Node node;
double x, y, w, h;
double blft, midy;
public Child(Node node,
double x, double y, double w, double h,
double blft, double midy) {
super();
this.node = node;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.blft = blft;
this.midy = midy;
}
}
private List<Child> children = new ArrayList<>();
private List<Double> midys = new ArrayList<>();
public LayoutFlowPane() {
super();
}
@Override protected void layoutChildren() {
super.layoutChildren();
Insets insets = getInsets();
double width = getWidth();
double height = getHeight();
double top = insets.getTop();
double left = insets.getLeft();
double bottom = insets.getBottom();
double right = insets.getRight();
double maxw = width - left - right;
double maxh = height - top - bottom;
double hgap = snapSpace(this.getHgap());
double vgap = snapSpace(this.getVgap());
storeChildren();
adjustChildren(maxw, maxh, hgap, vgap);
children.forEach(child -> {
layoutInArea(
child.node, child.x, child.y,
child.w, child.h, child.blft, getMargin(child.node),
getColumnHalignmentInternal(), getRowValignmentInternal()
);
});
}
private void storeChildren() {
children = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i ++) {
Node child = getChildren().get(i);
double x = child.getLayoutX();
double y = child.getLayoutY();
double w = 0;
double h = 0;
if (child instanceof Region) {
Region region = (Region) child;
w = region.getWidth();
h = region.getHeight();
} else {
throw new UnknowTypeException("Unknow type found.");
}
double blft = child.getBaselineOffset();
double midy = (y + y + h) / 2;
Child newChild = new Child(child, x, y, w, h, blft, midy);
children.add(newChild);
}
midys = new ArrayList<>();
for (int i = 0; i < children.size(); i ++) {
Child child = children.get(i);
if (midys.isEmpty() || midys.get(midys.size()-1) != child.midy) {
midys.add(child.midy);
}
}
}
private void adjustChildren(double maxw, double maxh, double hgap, double vgap) {
for (int i = 1; i < children.size(); i ++) { // begin with 1
Child pc = children.get(i-1);
Child ch = children.get(i);
boolean bothGridPane = (pc.node instanceof GridPane) && (ch.node instanceof GridPane);
double x = pc.x + pc.w + (bothGridPane ? 0 : hgap);
double midy;
if (x + ch.w <= maxw) { // ThisLine
midy = pc.midy;
ch.x = x;
ch.y = gety(ch.y, ch.midy, midy);
ch.midy = midy;
} else { // NextLine
midy = getNextMidy(pc.midy);
ch.x = children.get(0).x;
ch.y = gety(ch.y, ch.midy, midy);
ch.midy = midy;
}
}
}
private double getNextMidy(double midy) {
for (int i = 0; i < midys.size(); i ++) {
if (i + 1 < midys.size() && midys.get(i) == midy && midys.get(i+1) != midy) {
return midys.get(i+1);
} else if (i + 1 == midys.size() && midys.get(i) == midy) {
return midys.get(i);
}
}
throw new NotFoundException("Next midy not found.");
}
private double gety(double oldy, double oldMidy, double newMidy) {
return oldy + (newMidy - oldMidy);
}
private HPos getColumnHalignmentInternal() {
HPos localPos = getColumnHalignment();
return null == localPos ? HPos.LEFT : localPos;
}
private VPos getRowValignmentInternal() {
VPos localPos = getRowValignment();
return null == localPos ? VPos.CENTER : localPos;
}
private class UnknowTypeException extends RuntimeException {
private static final long serialVersionUID = 1L;
public UnknowTypeException(String message) {
super(message);
}
}
private class NotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public NotFoundException(String message) {
super(message);
}
}
}