JavafX和CSS-将节点移至最前

时间:2018-06-27 20:42:02

标签: css javafx bringtofront

基本上是标题。我在JavaFX中有一个节点,我希望根据某些CSS规则将其显示在所有其他节点的前面。我不希望这改变VBox似乎在.toFront()中执行的节点的顺序。请参阅this问题。

这有可能吗?

编辑:进行澄清。情况如下。我有一个VBox,其中包含一堆紧凑的ImageView。当我将鼠标悬停在上方时,我希望它略微增大以使图像感觉脱离屏幕。但是,由于ImageView的排列如此紧密,因此只有顶部边缘会明显增长。底部边缘会增大,但位于下图下方,无法看到。

编辑2:根据要求,以下是我在做什么的屏幕截图。

enter image description here

不同的颜色渐变是ImageView s,当我将鼠标悬停在一个颜色渐变上时,它应该随着该图像中顶部渐变的顶部边缘而增大(紧密观察X旁边的右上角)。但是,正如在此图像中也可以看到的那样,ImageView的底边已被该VBox中的下一个渐变隐藏,并且看不到增长。

3 个答案:

答案 0 :(得分:3)

这听起来像是使用Java 9中添加的Node的{​​{3}}属性的理想情况。viewOrder控制着相对于其他{相同Node的{​​1}},而不会更改子列表中Node的顺序。这是Javadoc:

  

定义此Node在其父级中的渲染和拾取顺序。

     

此属性用于更改对象的渲染和拾取顺序   父节点中的节点,而无需重新排序父节点的子节点列表。   例如,这可以用作更有效的实施方式   透明度排序。为此,应用程序可以分配   每个节点的viewOrder值到之间的计算距离   节点和查看器。

     

父级将以递减的viewOrder顺序遍历其子级。   这意味着viewOrder较低的孩子将在   viewOrder较高的孩子。如果两个孩子相同   viewOrder,父级将按照它们出现的顺序遍历它们   父母的子女名单。

     

但是,viewOrder不会更改布局和焦点遍历顺序   该节点在其父节点中的位置。父母总是横穿孩子   进行布局或焦点遍历时按顺序列出。

下面是使用此属性的示例:

Parent

它使用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,然后反转ScaleTransition

注意:我使用了Java 10中添加的0关键字。

这是实际示例的GIF:

viewOrder

编辑:自从您带来CSS以来,我去检查了是否可以从样式表中设置视图顺序。看起来可以。查看the GIF of the application in action,有一个为ScaleTransition定义的CSS属性,名为var

答案 1 :(得分:1)

这是一个这样的解决方案,它创建了一个新的舞台来显示放大的图像。

我没有在此示例中设置适当的坐标,但这是概念的证明。

简而言之:捕获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;
    }
}

从这里开始,应该只是固定或固定舞台坐标以将其居中放置在图像上,然后移除舞台装饰。

已知问题:

您还需要通过新阶段阻止鼠标光标来解决此问题。这将导致一个循环,在该循环中,鼠标将不断进入和退出图像的缩略图,从而导致放大的舞台闪烁。

答案 2 :(得分:1)

从我的角度来看,您有一个间距为0的VBox,因此每个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;
    }