Efekt Matowego Szkła w JavaFX?

Robię projekt JavaFX2/FXML o tematyce iOS7 i zastanawiałem się, jak sprawić, by obiekt prostokątny miał efekt matowego szkła iOS7.

Chciałbym też mieć mały cień. Jest to trudne, ponieważ możesz zobaczyć cień za półprzezroczystym obiektem. Chciałbym, żeby była obecna na brzegach.

Czy to możliwe? Oto zdjęcie pokazujące pożądany efekt (nie wliczając małego cienia):

Chciałbym, żeby to wyglądało tak

UPDATE: Oto kontynuacja numeru. To będzie wyglądać niesamowicie: D.

Author: Community, 2014-03-25

1 answers

Przykładowy Roztwór

mróz

Uruchom poniższy program i przewiń lub przesuń palcem w górę, aby wyświetlić szybę.

Celem programu jest tylko próba technik zaangażowanych nie działać jako biblioteka ogólnego przeznaczenia dla efektu mrozu.

import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.Rectangle2D;
import javafx.scene.*;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

// slides a frost pane in on scroll or swipe up; slides it out on scroll or swipe down.
public class Frosty extends Application {

    private static final double W = 330;
    private static final double H = 590;

    private static final double BLUR_AMOUNT = 60;
    private static final Duration SLIDE_DURATION = Duration.seconds(0.4);

    private static final double UPPER_SLIDE_POSITION = 100;

    private static final Effect frostEffect =
        new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3);

    @Override public void start(Stage stage) {
        DoubleProperty y = new SimpleDoubleProperty(H);

        Node background = createBackground();
        Node frost      = freeze(background, y);
        Node content    = createContent();
        content.setVisible(false);

        Scene scene = new Scene(
                new StackPane(
                        background,
                        frost,
                        content
                )
        );

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

        addSlideHandlers(y, content, scene);
    }

    // create a background node to be frozen over.
    private Node createBackground() {
        Image backgroundImage = new Image(
                getClass().getResourceAsStream("ios-screenshot.png")
        );
        ImageView background = new ImageView(backgroundImage);
        Rectangle2D viewport = new Rectangle2D(0, 0, W, H);
        background.setViewport(viewport);

        return background;
    }

    // create some content to be displayed on top of the frozen glass panel.
    private Label createContent() {
        Label label = new Label("The overlaid text is clear and the background below is frosty.");

        label.setStyle("-fx-font-size: 25px; -fx-text-fill: midnightblue;");
        label.setEffect(new Glow());
        label.setMaxWidth(W - 20);
        label.setWrapText(true);

        return label;
    }

    // add handlers to slide the glass panel in and out.
    private void addSlideHandlers(DoubleProperty y, Node content, Scene scene) {
        Timeline slideIn = new Timeline(
                new KeyFrame(
                        SLIDE_DURATION,
                        new KeyValue(
                                y,
                                UPPER_SLIDE_POSITION
                        )
                )
        );

        slideIn.setOnFinished(e -> content.setVisible(true));

        Timeline slideOut = new Timeline(
                new KeyFrame(
                        SLIDE_DURATION,
                        new KeyValue(
                                y,
                                H
                        )
                )
        );

        scene.setOnSwipeUp(e -> {
            slideOut.stop();
            slideIn.play();
        });

        scene.setOnSwipeDown(e -> {
            slideIn.stop();
            slideOut.play();
            content.setVisible(false);
        });

        // scroll handler isn't necessary if you have a touch screen.
        scene.setOnScroll((ScrollEvent e) -> {
            if (e.getDeltaY() < 0) {
                slideOut.stop();
                slideIn.play();
            } else {
                slideIn.stop();
                slideOut.play();
                content.setVisible(false);
            }
        });
    }

    // create a frosty pane from a background node.
    private StackPane freeze(Node background, DoubleProperty y) {
        Image frostImage = background.snapshot(
                new SnapshotParameters(),
                null
        );
        ImageView frost = new ImageView(frostImage);

        Rectangle filler = new Rectangle(0, 0, W, H);
        filler.setFill(Color.AZURE);

        Pane frostPane = new Pane(frost);
        frostPane.setEffect(frostEffect);

        StackPane frostView = new StackPane(
                filler,
                frostPane
        );

        Rectangle clipShape = new Rectangle(0, y.get(), W, H);
        frostView.setClip(clipShape);

        clipShape.yProperty().bind(y);

        return frostView;
    }

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

Źródło obrazu

Zapisz Ten obraz równolegle do źródła Javy jako plik o nazwie ios-screenshot.png i poproś system kompilacji o skopiowanie go do katalogu docelowego, aby uzyskać binarne wyjście buduj.

ios-zrzut ekranu

Odpowiedzi na dodatkowe pytania

"JDK 8", czy to byłby warunek tego?

Powyższy przykładowy kod jest napisany przeciwko JDK 8. Przeniesienie go z powrotem do JDK 7 poprzez zastąpienie wywołań lambda anonimowymi klasami wewnętrznymi jest dość trywialne.

Ogólnie Rzecz Biorąc, Java 7 jest dość przestarzała jak na pracę JavaFX. Radzę jak najszybciej uaktualnić do pracy z minimum Java 8 wersja.

Inicjowanie paneli argumentami

Wygodniejszym konstruktorem dla większości węzłów macierzystych jest funkcja Java 8. Możesz łatwo przekonwertować format Java 8:

 StackPane stack = new StackPane(child1, child2);

Do Java 7:

 StackPane stack = new StackPane();
 stack.getChildren().setAll(child1, child2);

Czy to zadziała, jeśli pulpit jest za mroźną szybą?

Nie bezpośrednio, możesz utworzyć nowe pytanie.

Aktualizacja: Pytania Pokrewne

User created: JavaFX effect on tło umożliwiające zastosowanie efektu matowego do okna na tle pulpitu.

Inny użytkownik utworzony: Jak utworzyć przezroczysty etap JavaFX z cieniami tylko na granicy? Aby zastosować efekt halo shadow wokół tego okna.

 18
Author: jewelsea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:53:02