如何将JFoenix的JFXSnackbar对齐至左下角?位置设置失效问题
更新:我已改用
BorderPane并尝试调用pane.setBottom()方法,但未生效。
我正在使用JFoenix库,希望将Snackbar对齐到界面左下角,但目前Snackbar默认对齐在底部居中位置。
最小可复现示例
所有代码均位于application包下:
Controller.java
package application; import com.jfoenix.controls.JFXSnackbar; import com.jfoenix.controls.JFXSnackbar.SnackbarEvent; import com.jfoenix.controls.JFXSnackbarLayout; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.layout.AnchorPane; import javafx.util.Duration; public class Controller { @FXML private AnchorPane pane; @FXML Button snackbarButton; public void snackBarAction() { JFXSnackbar snackbar = new JFXSnackbar(); pane.setBottom(snackbar); snackbar.fireEvent(new SnackbarEvent( new JFXSnackbarLayout("Snackbar Message"), Duration.seconds(2), null)); } }
Main.java
import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; public class Main extends Application { @Override public void start(Stage primaryStage) { try { Parent parent = FXMLLoader.load(getClass().getResource("scene.fxml")); Scene scene = new Scene(parent); primaryStage.setScene(scene); primaryStage.show(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { launch(args); } }
scene.fxml
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.Button?> <?import javafx.scene.layout.BorderPane?> <BorderPane fx:id="pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller"> <center> <Button fx:id="snackbarButton" mnemonicParsing="false" onAction="#snackBarAction" text="Button" BorderPane.alignment="CENTER" /> </center> </BorderPane>
预期与实际行为
- 预期行为:
BorderPane的底部区域(若原本包含内容)会被移除,替换为Snackbar吐司提示。 - 实际行为:
BorderPane的底部区域确实被移除了(我曾尝试在底部添加按钮,点击snackbarButton后该按钮会如预期被移除),但Snackbar显示异常:无论我如何设置它的位置,Snackbar的提示消息始终出现在靠近顶部左侧的位置,而非预期的左下角。
解决方法
先修代码里的两处硬bug
- Controller里的
pane变量类型和FXML里的实际节点不匹配:FXML中声明的是BorderPane类型,Controller里写的是AnchorPane类型,虽然FXMLLoader不会强制校验类型,但布局逻辑的推导会出错。 JFXSnackbar的使用方式完全错误:它不是普通的可嵌入布局的控件,本身是一个浮层容器,不能通过pane.setBottom()这类布局方法手动塞进BorderPane的分区里——它的定位逻辑是依赖自身绑定的父容器尺寸实现的,手动嵌入的方式会导致内部坐标计算完全错乱。
- Controller里的
正确的实现逻辑
- 初始化
JFXSnackbar时直接传入要覆盖的父容器实例,让它自动作为浮层加到父容器的最上层。 - 修改内部对齐属性,把Snackbar的位置从默认的底部居中调整为左下角。
修改后的Controller核心代码:
public class Controller { // 修正类型匹配 @FXML private BorderPane pane; @FXML Button snackbarButton; // 把Snackbar设为类成员变量,不要每次点击都重复new private JFXSnackbar snackbar; @FXML public void initialize() { // 初始化时直接绑定父容器 snackbar = new JFXSnackbar(pane); // 获取Snackbar内部的覆盖层StackPane StackPane snackbarOverlay = (StackPane) snackbar.getChildrenUnmodifiable().get(0); // 设置对齐为左下角 snackbarOverlay.setAlignment(Pos.BOTTOM_LEFT); // 加边距避免Snackbar紧贴屏幕边缘 snackbarOverlay.setPadding(new Insets(0, 0, 16, 16)); } public void snackBarAction() { snackbar.fireEvent(new SnackbarEvent( new JFXSnackbarLayout("Snackbar Message"), Duration.seconds(2), null)); } }需补充的导入语句:
import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.layout.StackPane;- 初始化
额外注意
- 不要每次触发Snackbar时都创建新的实例,反复创建会导致浮层堆叠、位置错乱。
- 之前看到Snackbar跑到顶部的原因,就是因为手动嵌入的
JFXSnackbar没有绑定父容器的尺寸参考,内部坐标计算默认从节点原点(左上角)开始渲染,完全不受BorderPane底部分区的位置约束。
内容的提问来源于stack exchange,提问作者comma
相关产品推荐
相关产品推荐

