Linear gradient's bounds computation takes parent's bounds in account, not the node on which it is applied on

。_饼干妹妹 提交于 2019-12-31 04:23:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!