簡體   English   中英

JavafX和CSS-將節點移到最前面

[英]JavafX & CSS - Move Node to Front

作為標題基本上。 我在JavaFX中有一個節點,我希望根據某些CSS規則將其顯示在所有其他節點的前面。 我不希望這更改.toFront()似乎在做的VBox中節點的順序。 看到這個問題。

這有可能嗎?

編輯:澄清。 情況如下。 我有一個VBox其中包含一堆緊密包裝的ImageView 當我將鼠標懸停在上方時,我希望它略微增大以使圖像感覺脫離屏幕。 但是,由於ImageView的包裝非常緊密,因此只有頂部邊緣會明顯增長。 底邊增大,但在下圖下方,無法看到。

編輯2:根據要求,這里是我在做什么的屏幕截圖。

在此處輸入圖片說明

不同的顏色梯度是ImageView ,當我將鼠標懸停在其上時,它應隨着該圖像中頂部梯度的頂部邊緣而增大(仔細觀察X旁邊的右上角)。 但是,正如在此圖像中也可以看到的那樣,此ImageView的底部邊緣已被該VBox的下一個漸變隱藏,並且看不到增長。

這聽起來像使用完美的情況viewOrder的屬性Node在Java中9添加的viewOrder控制如何Node S IN相對於其他繪制Node相同第Parent不改變的順序Node的子列表秒。 這是Javadoc:

定義此Node在其父級中的渲染和拾取順序。

此屬性用於更改節點在其父級中的渲染和選取順序,而無需重新排序父級的子級列表。 例如,這可以用作實現透明度排序的更有效方法。 為此,應用程序可以將每個節點的viewOrder值分配給該節點與查看器之間的計算距離。

父級將以遞減的viewOrder順序遍歷其子級。 這意味着viewOrder較低的子項將在viewOrder較高的子項之前。 如果兩個子代具有相同的viewOrder,則父代將按照它們在父代的子代列表中出現的順序遍歷它們。

但是,viewOrder不會更改此Node在其父級中的布局和焦點遍歷順序。 進行布局或焦點遍歷時,父級始終按順序遍歷其子級列表。

這是使用此屬性的示例:

import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.util.ArrayList;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        var box = new HBox(createRectangles(Color.DARKBLUE, Color.FIREBRICK, 25));
        box.setAlignment(Pos.CENTER);
        box.setPadding(new Insets(50, 20, 50, 20));
        primaryStage.setScene(new Scene(box));
        primaryStage.show();
    }

    private Rectangle[] createRectangles(Color start, Color end, int count) {
        var list = new ArrayList<Rectangle>(count);
        for (double i = 0; i < count; i++) {
            var rect = new Rectangle(30, 60, start.interpolate(end, i / count));

            var scaleTrans = new ScaleTransition(Duration.millis(250), rect);
            scaleTrans.setFromX(1.0);
            scaleTrans.setFromY(1.0);
            scaleTrans.setToX(1.2);
            scaleTrans.setToY(1.2);

            rect.setOnMouseEntered(e -> {
                scaleTrans.stop(); // <--- doesn't seem necessary*
                scaleTrans.setRate(1.0);
                rect.setViewOrder(-1.0);
                scaleTrans.play();
            });
            rect.setOnMouseExited(e -> {
                scaleTrans.stop(); // <--- doesn't seem necessary*
                scaleTrans.setRate(-1.0);
                rect.setViewOrder(0.0);
                scaleTrans.play();
            });
            // *the "stop()"'s don't seem to be necessary. When I commented
            // them out the animation still worked. In fact, the animation
            // actually seems smoother in the situation where you move the
            // mouse over and then away quickly (before the zoom-in completes).

            list.add(rect);
        }
        return list.toArray(new Rectangle[0]);
    }

}

它使用Rectangle而不是ImageView但是概念是相同的。 當鼠標懸停在Rectangle它將視圖順序設置為低於其他Rectangle ,然后播放ScaleTransition使其變大。 鼠標退出時,它將視圖順序重置為0 ,然后反轉ScaleTransition

注意:我使用了Java 10中添加的var關鍵字。

這是實際示例的GIF:

實際應用程序的GIF

編輯:由於您帶來了CSS,所以我去檢查了是否可以從樣式表中設置視圖順序。 看起來可以。 查看《 CSS參考指南》,有一個為Node定義的CSS屬性,名為-fx-view-order

這是一個這樣的解決方案,它創建了一個新的階段來顯示放大的圖像。

我沒有在此示例中設置適當的坐標,但這可以作為概念證明。

簡而言之:捕獲onMouseEnteredonMouseExited事件並隱藏或顯示新階段。

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        FlowPane root = new FlowPane();
        root.setHgap(5);
        root.setVgap(5);
        for (int i = 0; i < 25; i++) {
            root.getChildren().add(getImagePane());
        }

        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    private VBox getImagePane() {

        VBox pane = new VBox() {{
            setAlignment(Pos.CENTER);
            setPadding(new Insets(5));
            setWidth(50);
            setHeight(50);
            setStyle("-fx-border-color: black");
        }};

        ImageView img = new ImageView("sample/imageGallery/cerulean.png") {{
            setFitWidth(50);
            setFitHeight(50);
            setPreserveRatio(true);

            Stage stage = zoomedStage(pane, this);

            setOnMouseEntered(mouseEvent -> stage.show());
            setOnMouseExited(mouseEvent -> stage.hide());

        }};

        pane.getChildren().add(img);
        return pane;

    }

    private Stage zoomedStage(VBox parent, ImageView img) {

        Stage stage = new Stage();
        stage.setWidth(110);
        stage.setHeight(110);

        VBox pane = new VBox() {{
            setAlignment(Pos.CENTER);
            setPadding(new Insets(5));
            setWidth(110);
            setHeight(110);
            setStyle("-fx-border-color: black");
        }};

        pane.setPickOnBounds(false);

        ImageView zoomedImage = new ImageView(img.getImage());
        zoomedImage.setFitHeight(100);
        zoomedImage.setFitWidth(100);

        pane.getChildren().add(zoomedImage);

        stage.setScene(new Scene(pane));
        stage.initStyle(StageStyle.UNDECORATED);
        return stage;
    }
}

從這里開始,應該只是固定或固定舞台坐標以將其居中放置在圖像上,然后移除舞台裝飾。

已知的問題:

您還需要通過新階段阻止鼠標光標來解決此問題。 這將導致鼠標不斷進入和退出圖像縮略圖的循環,從而導致放大的舞台閃爍。

從我的角度來看,您有一個VBox,間距為0,因此每個ImageView彼此緊密包裝在一起,因此輝光效果在每個圖像中都不清晰可見。 在這種情況下,您每次想要選擇ImageView時都可以添加邊距,以“幫助”發光效果出現。

對於Java 8:

可悲的是,這不可能從CSS發生,因為ImageView沒有提供任何用於設置邊距或填充的規則。 因此(我認為)您或多或少必須通過代碼編寫該行為。

private Node createImageView(String imageLink) {
        // Setting the image view
        ImageView imageView = new ImageView(imageLink);

        // setting the fit width of the image view
        imageView.setFitWidth(400);

        // Setting the preserve ratio of the image view
        imageView.setPreserveRatio(true);

        // Instantiating the Glow class
        Glow glow = new Glow();

        imageView.setOnMouseEntered(e -> {
            // setting level of the glow effect
            glow.setLevel(0.9);
            // Adding a margin on TOP and Bottom side just to make the 
            // glowing effect visible
            VBox.setMargin(imageView, new Insets(2,0,2,0));
        });

        imageView.setOnMouseExited(e -> {
            // remove the glow effect
            glow.setLevel(0.0);
            // remove the margins 
            VBox.setMargin(imageView, new Insets(0));
        });

        // Applying bloom effect to text
        imageView.setEffect(glow);

        return imageView;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM