如何在JavaFX上的场景上绘制渐变?

时间:2014-07-02 20:39:52

标签: java javafx javafx-2 javafx-8

有没有办法在JavaFX舞台的整个场景中绘制从黑色到透明的径向渐变? 我希望实现这样的目标: Example

2 个答案:

答案 0 :(得分:6)

这是一个快速回答,它使用StackPane作为场景根,以允许添加具有从黑色到透明的径向渐变背景的叠加层。

  • 您可以调整径向渐变颜色或半径,例如制作内部颜色Color.BLACK.deriveColor(0, 1, 1, 0.2),以更改效果中的高光和强度。
  • 这样的渐变也可以在CSS中设置,因此如果您愿意,可以使用CSS而不是Java代码来设置效果的样式。
  • 此实现的输出受到径向渐变的束缚(不确定如何进一步改善)的影响,但根据您的容差,它可以正常。

shaded

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.effect.BoxBlur;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.stage.Stage;

// java 8
// click on the scene to place a shaded lens effect over the scene.
public class ShadedScene extends Application {
    @Override
    public void start(Stage stage) {
        StackPane layout = new StackPane(
                new Label("Click to shade/unshade")
        );
        layout.setPrefSize(400, 300);

        Scene scene = new Scene(layout);
        makeShadeable(scene);

        stage.setScene(scene);
        stage.show();
    }

    /**
     * Applies a lens effect gradient to a scene root node.
     * The effect is kind of like a flashlight shining against the wall in the dark.
     *
     * For the gradient to be applied, the scene's root must be defined and a Pane
     * to which the effect can added and removed as a child.
     * 
     * @param scene the scene to have the effect applied.
     */
    private void makeShadeable(Scene scene) {
        if (scene.getRoot() == null ||
            !(scene.getRoot() instanceof Pane)) {
            return;
        }

        Pane shade = new Pane();
        RadialGradient shadePaint = new RadialGradient(
                0, 0, 0.5, 0.5, 1, true, CycleMethod.NO_CYCLE,
                new Stop(1, Color.BLACK),
                new Stop(0, Color.TRANSPARENT)
        );

        shade.setBackground(
                new Background(
                        new BackgroundFill(
                                shadePaint, null, new Insets(-10)
                        )
                )
        );

        // blur helps reduce visible banding of the radial gradient.
        shade.setEffect(new BoxBlur(5, 5, 3));

        Pane root = (Pane) scene.getRoot();
        scene.setOnMouseClicked(event -> {
            if (root.getChildren().contains(shade)) {
                root.getChildren().remove(shade);
            } else {
                root.getChildren().add(shade);
            }
        });
    }

    public static void main(String[] args) {
        launch(args);
    }
}

还有其他方法可以达到类似于预期效果的效果。例如,下面的技术直接将内部阴影和颜色调整应用于根窗格,因此不需要额外的节点。

shaded inner shadow

private void makeShadeableByInnerShadow(Scene scene) {
    InnerShadow shade = new InnerShadow();
    shade.setWidth(120);
    shade.setHeight(120);
    shade.setInput(new ColorAdjust(0, 0, -0.3, 0));

    Parent root = scene.getRoot();
    scene.setOnMouseClicked(event -> {
        if (root.getEffect() == null) {
            root.setEffect(shade);
        } else {
            root.setEffect(null);
        }
    });
}

答案 1 :(得分:2)

考虑您的示例,您可以在http://pt.stackoverflow.com上发布此内容。因为您的大部分界面都是巴西葡萄牙语。

答案正是jewelsea发布的内容。但是,当我收到通知时我也回答时,我也发了一个答案。

<强> Test.java

package br;

    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;


    public class Test extends Application {

            public static Stage thisStage;
            @Override
            public void start(Stage stage) throws Exception {
                thisStage = stage;
                Parent root = FXMLLoader.load(getClass().getResource("doc.fxml"));
                Scene scene = new Scene(root);
                scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
                stage.setScene(scene);
                stage.setTitle("Happy Client - Overlay");
                stage.show();

            }
            public static void main(String[] args) {
                launch(args);
            }
    }

<强> TestController.java

package br;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;

    public class TestController implements Initializable{
        @FXML Pane mainPane;
        @FXML Pane overlayPane;
        @Override
        public void initialize(URL arg0, ResourceBundle arg1) {
            overlayPane.getStyleClass().add("grad");
            overlayPane.toFront();
            overlayPane.addEventHandler(MouseEvent.MOUSE_PRESSED,
                    new EventHandler<MouseEvent>(){
                        @Override
                        public void handle(MouseEvent arg0) {
                            overlayPane.toBack();
                        }
            });
        }
    }

<强> doc.fxml

<?xml version="1.0" encoding="UTF-8"?>

    <?import java.lang.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.scene.shape.*?>

    <StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="br.TestController">
        <children>
        <Pane fx:id="mainPane" prefHeight="98.0" prefWidth="600.0">
        <children>
            <TableView layoutX="-2.0" layoutY="99.0" prefHeight="300.0" prefWidth="600.0">
                <columns>
                    <TableColumn prefWidth="75.0" text="Nome" />
                    <TableColumn prefWidth="75.0" text="RG" />
                    <TableColumn prefWidth="75.0" text="CPF" />
                    <TableColumn prefWidth="75.0" text="Idade" />
                </columns>
            </TableView>
            <Label layoutX="162.0" layoutY="41.0" style="-fx-font-size: 32;" text="Informe o cliente" />
            <Line endX="500.0" layoutX="100.0" layoutY="98.0" startX="-100.0" />
        </children>
        </Pane>
        <Pane fx:id="overlayPane" opacity="0.8" prefHeight="200.0" prefWidth="200.0" />
    </children>
    </StackPane>

<强>的style.css

.grad{
    -fx-padding: 40;
    -fx-background-color:  radial-gradient(center 50% 50%, radius 140%, rgba(200,200,200,70) 5%,rgba(0,0,0,100) 35%);
}

enter image description here

请注意,您必须使用StackPane而不是其他如AnchorPane,因为如果您直接在AnchorPane上设置样式,则样式将不适用于您的表格上方的元素,如下所示:< / p>

enter image description here