javafx - JavaFX:如何在具有阴影效果的舞台上正确滑动窗格?
问题描述
我在“ JavaFX:如何为窗格(透明舞台内)创建动画效果幻灯片”中看到了这个问题。
而且我不明白 John Astralidis 发布的最后一条评论的部分代码。它似乎解决了我的问题。我想滑动带有阴影阶段的窗格。现在我的问题是幻灯片动画在我的可视根窗格绑定之外播放,它只是在舞台(或实际根窗格)绑定的情况下播放。
我的视觉根窗格是实际根窗格的子窗格,我使用填充和 Corlor.TRANSPARENT 设置实际根窗格以实现我的视觉根窗格阴影效果。
这是我从 John Astralidis 和 Felipe Guizar Diaz 修改的代码。起始代码:
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
stage.initStyle(StageStyle.TRANSPARENT);
Scene scene = new Scene(root);//
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
FXMLDocument.fxml:
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" fx:id="anchorPane" prefWidth="500" prefHeight="500" style="-fx-background-color: transparent;"
fx:controller="leftslidemenusample.FXMLDocumentController">
<children>
<ToolBar AnchorPane.topAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" minHeight="56.0" >
<Button text="menu" fx:id="menu" />
</ToolBar>
<StackPane fx:id="mainContent" style="-fx-background-color:rgba(0,0,0,0.30)" AnchorPane.bottomAnchor="0.0" AnchorPane.topAnchor="56.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" >
<children>
</children>
</StackPane>
<AnchorPane fx:id="navList" style="-fx-background-color:white" AnchorPane.topAnchor="56.0" AnchorPane.bottomAnchor="0.0" prefWidth="180.0" translateX="-180" >
<children>
<Label text="left side menu"/>
</children>
</AnchorPane>
</children>
和控制器 FXMLDocumentController.java
public class FXMLDocumentController implements Initializable {
@FXML
private AnchorPane anchorPane;
@FXML
private Button menu;
@FXML
private AnchorPane navList;
private double shadowSize = 15;
@Override
public void initialize(URL url, ResourceBundle rb) {
Rectangle rectangle = new Rectangle(500,500);
anchorPane.setClip(rectangle);
anchorPane.getChildren().add(setupShadowPane());
prepareSlideMenuAnimation();
}
private Pane setupShadowPane() {
Pane shadowPane = new Pane();
shadowPane.setPrefHeight(500);
shadowPane.setPrefWidth(500);
shadowPane.setStyle(
"-fx-background-color: RED;" +
"-fx-effect: dropshadow(gaussian, black, " + 20 + ", 0, 0, 0);" +
"-fx-background-insets: " + shadowSize + ";"
);
Rectangle innerBounds = new Rectangle();
Rectangle outerBounds = new Rectangle();
shadowPane.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
System.out.println(newBounds.getWidth());
innerBounds.relocate(newBounds.getMinX() + shadowSize, newBounds.getMinY() + shadowSize);
innerBounds.setWidth(newBounds.getWidth() - shadowSize * 2);
innerBounds.setHeight(newBounds.getHeight() - shadowSize * 2);
outerBounds.setWidth(newBounds.getWidth());
outerBounds.setHeight(newBounds.getHeight());
Shape clip = Shape.subtract(outerBounds, innerBounds);
shadowPane.setClip(clip);
});
return shadowPane;
}
private void prepareSlideMenuAnimation() {
TranslateTransition openNav=new TranslateTransition(new Duration(350), navList);
openNav.setToX(0);
TranslateTransition closeNav=new TranslateTransition(new Duration(350), navList);
menu.setOnAction((ActionEvent evt)->{
if(navList.getTranslateX()!=0){
openNav.play();
}else{
closeNav.setToX(-(navList.getWidth()));
closeNav.play();
}
});
}
}
解决方案
最后,我完成了。我认为 John Astralidis 的回答是错误的。但是谢谢。关键是:
- 使用一个 StackPane 作为实际根窗格,然后将可视根窗格和阴影窗格添加到实际根窗格中作为 StackPane 的子窗格。可视根窗格是需要添加阴影效果窗格的。
- 用芯片设置可视根窗格,使其外部布局显示阴影窗格的阴影效果;
- 设置带有芯片的阴影窗格,该芯片包含其内部布局以显示可视根窗格的内容。
希望我的英语不好回答可以帮助某人。我在下面发布了我的整个演示代码:
入门类--FXApplication.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class FXApplication extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
stage.initStyle(StageStyle.TRANSPARENT);
Scene scene = new Scene(root);//
scene.setFill(Color.TRANSPARENT);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
布局FXML文件--FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<StackPane xmlns:fx="http://javafx.com/fxml/1" fx:id="pane" prefWidth="500" prefHeight="500" style="-fx-background-color: transparent;"
fx:controller="FXMLDocumentController">
<children>
<AnchorPane fx:id="anchorPane" prefWidth="500" prefHeight="500" style="-fx-background-color: WHITE;">
<children>
<ToolBar AnchorPane.topAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" minHeight="56.0" >
<Button text="menu" fx:id="menu" />
</ToolBar>
<StackPane fx:id="mainContent" style="-fx-background-color:rgba(0,0,0,0.30)" AnchorPane.bottomAnchor="0.0" AnchorPane.topAnchor="56.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" >
<children>
</children>
</StackPane>
<AnchorPane fx:id="navList" style="-fx-background-color:white" AnchorPane.topAnchor="56.0" AnchorPane.bottomAnchor="0.0" prefWidth="180.0" translateX="-180" >
<children>
<Label text="left side menu"/>
</children>
</AnchorPane>
</children>
</AnchorPane>
</children>
控制器类--FXMLDocumentController.java
import javafx.animation.TranslateTransition;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.util.Duration;
import java.net.URL;
import java.util.ResourceBundle;
public class FXMLDocumentController implements Initializable {
@FXML
private AnchorPane anchorPane;
@FXML
private StackPane pane;
@FXML
private Button menu;
@FXML
private AnchorPane navList;
private double shadowSize = 10;
@Override
public void initialize(URL url, ResourceBundle rb) {
Rectangle rectangle = new Rectangle(480,480);
rectangle.relocate(10,10);
anchorPane.setClip(rectangle);
pane.getChildren().add(setupShadowPane());
prepareSlideMenuAnimation();
}
private Pane setupShadowPane() {
Pane shadowPane = new Pane();
shadowPane.setPrefHeight(500);
shadowPane.setPrefWidth(500);
shadowPane.setStyle(
"-fx-background-color: RED;" +
"-fx-effect: dropshadow(gaussian, black, " + 20 + ", 0, 0, 0);" +
"-fx-background-insets: " + shadowSize + ";"
);
Rectangle innerBounds = new Rectangle();
Rectangle outerBounds = new Rectangle();
shadowPane.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
innerBounds.relocate(newBounds.getMinX() + shadowSize, newBounds.getMinY() + shadowSize);
innerBounds.setWidth(newBounds.getWidth() - shadowSize * 2);
innerBounds.setHeight(newBounds.getHeight() - shadowSize * 2);
outerBounds.setWidth(newBounds.getWidth());
outerBounds.setHeight(newBounds.getHeight());
Shape clip = Shape.subtract(outerBounds, innerBounds);
shadowPane.setClip(clip);
});
return shadowPane;
}
private void prepareSlideMenuAnimation() {
TranslateTransition openNav=new TranslateTransition(new Duration(350), navList);
openNav.setToX(0 + shadowSize);
TranslateTransition closeNav=new TranslateTransition(new Duration(350), navList);
menu.setOnAction((ActionEvent evt)->{
if(navList.getTranslateX()!=0+shadowSize){
openNav.play();
}else{
closeNav.setToX(-(navList.getWidth())+shadowSize);
closeNav.play();
}
});
}
}
以及下图:
推荐阅读
- javascript - jQuery Uncaught Syntax 错误,无法识别的表达式:+
- docker - 如何在最新的 Raspbian (20-06-2019) 上安装 docker?
- sql-server - 报表生成器:将表格结果打印到 Excel 中的不同工作表中
- javascript - 我的异步在等待调用时返回未定义
- javascript - 在 Youtube 视频上点击海报属性时视频不会播放
- javascript - 无法将图像添加到结构 js 组
- pandas - 无法使用 python 打开或查看数据
- java - 获取文档 Cloud Firestore 中集合的所有文档
- google-chrome - 将 Visual Studio MVC 应用程序调试到 Chrome 时出现“spawn UNKNOWN”错误
- reactjs - @material-ui 与 material-ui 之间的区别(无符号)