问题
I want to put a linear gradient on a line(width wise ie across it's stroke width). This line is a child of a Group node. When I apply linear gradient on line, the color stops are calculated using Group's bounds not the lines bounds. In my code below, linear gradient will show up properly when added length-wise ie "to bottom", but not when added width wise, ie "to right". Can anyone tell me what can be work around for this? Here is the SSCCE
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class Test extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Group group = new Group();
primaryStage.setScene(new Scene(group, 200, 350));
Line line = new Line(100, 50, 100, 300);
group.getChildren().add(line);
line.setStyle("-fx-stroke-width:3em; -fx-stroke:linear-gradient(to right, red, green);");
//line.setStyle("-fx-stroke-width:3em; -fx-stroke:linear-gradient(to bottom, red, green);");
primaryStage.show();
}
public static void main(String[] args) {
launch();
}
}
回答1:
The assumption it takes the group's bounds is not correct. In fact, it's taking the line's bound. And here is the problem.
If you go to com.sun.prism.j2d.J2DPrismGraphics
you'll see that for a shape with a gradient, this is how fill()
is done:
void fill(java.awt.Shape shape) {
if (paintWasProportional) {
if (nodeBounds != null) {
g2d.setPaint(toJ2DPaint(paint, nodeBounds));
} else {
g2d.setPaint(toJ2DPaint(paint, shape.getBounds2D()));
}
}
g2d.fill(shape);
}
The paintWasProportional
check gave me a hint to approach your problem with another perspective.
Let's start by using a LinearGradient
object, by code instead of using CSS. Then this will be your starting point:
@Override
public void start(Stage primaryStage) throws Exception {
Group group = new Group();
primaryStage.setScene(new Scene(group, 200, 350));
Line line = new Line(100, 50, 100, 300);
LinearGradient linearGradient = new LinearGradient(0d, 0d, 0d, 1d, true,
CycleMethod.NO_CYCLE, new Stop(0,Color.RED),new Stop(1,Color.GREEN));
line.setStrokeWidth(36); // 3em
line.setStroke(linearGradient);
group.getChildren().add(line);
primaryStage.show();
}
With the expected result (the black line is just for reference):
Now, to get the gradient to right
, let's change the way we create the gradient, using a non proporcional one:
LinearGradient linearGradient = new LinearGradient(0d, 50d, 0d, 300d,
false, CycleMethod.REFLECT,new Stop(0,Color.RED), new Stop(1,Color.GREEN));
This will have the same result.
And if you want to change the direction, this is what you need:
LinearGradient linearGradient = new LinearGradient(100-18d, 0d, 100+18d, 0d,
false, CycleMethod.REFLECT,new Stop(0,Color.RED), new Stop(1,Color.GREEN));
With this result:
Note you could try now to get this done also by CSS.
来源:https://stackoverflow.com/questions/28026986/linear-gradients-bounds-computation-takes-parents-bounds-in-account-not-the-n