在JavaFX中切换窗格

我正在尝试使用FXML在JavaFX中创建Java程序。 但是我在布局管理方面遇到了麻烦。 我想在Panes之间切换,就像我习惯使用CardLayout一样,但我似乎无法得到它。

我用Google搜索,没有找到任何答案。

JavaFX中是否有任何CardLayout等效项? 如果是的话,你能举一个例子吗? 这对我的晚会很有帮助!

这是我的FXML代码

    

非动画过渡

如果您不需要在窗格之间进行动画过渡,则可以:

  1. 通过创建新场景并在舞台上设置该场景来替换整个场景
  2. 通过从父窗体中删除旧窗格并添加新窗格(通过操纵父窗口的子窗口列表 )来替换父布局中的特定窗格,或者
  3. 将所有窗格放在StackPane并将要显示的窗格移动到堆栈子列表的顶部。

动画过渡

如果您希望在窗格之间进行动画转换,请参阅Angela Caicedo关于在JavaFX中管理多个屏幕的两部分系列:

  • 第一部分
  • 第二部分

Angela的解决方案是使用StackPane和单独的自定义ScreenController类来管理堆栈中窗格之间的过渡或动画 。


构架

像JFXFlow和WebFX这样的框架还可以为您的应用程序提供浏览器样式界面,允许用户使用后退和前进按钮以及历史列表在屏幕之间来回切换。

2017年更新

我认为上面两个引用框架的开发现在已经不存在了。 正在开发的其他框架是:

  • TornadoFX
  • JRebirth
  • afterburner.fx

还有很多其他人(我不会在这里提供全面的清单)。


有关

  • 在同一场景中加载新的fxml

以下是我的工作方式:(在本例中,我创建了两个带有相应控制器的FXML文档。它们分别称为FXMLLogin.fxml和Home.fxml)。

那么,从FXMLLogin到Home,

在这个例子中,我 FXMLLoginController中创建了一个方法 ,它响应被按下的表单上的“登录”按钮:

 @FXML private void login(javafx.event.ActionEvent event) throws IOException { if(pwf1.getText().equals("alphabetathetagamma")) { Parent blah = FXMLLoader.load(getClass().getResource("Home.fxml")); Scene scene = new Scene(blah); Stage appStage = (Stage) ((Node) event.getSource()).getScene().getWindow(); appStage.setScene(scene); appStage.show(); } else { label1.setText("Password is incorrect. Please Try Again"); } } 

请注意,@ FXML非常重要。

如果我正确理解你的问题,那么这应该可以解决问题。

在窗格之间切换并不明显,在我找到的任何网络教程上都没有清楚地概述。 在我第一次弄明白之前,我不得不自己谷歌。 幸运的是,一旦掌握了它,它实际上非常简单。

我希望我没有误解你的问题? 如果这是你需要的,请告诉我:)

JRebirth应用程序框架使用其专用模式wB-CSMvc提供自定义“CardLayout”。

StackModel类将完成这项工作(由org.jrebirth.af:component工件提供),你可以在这里和这里找到2个用法。

可以使用enum | modelKey标识符调用每个“card”模型,并且每个堆栈都具有唯一的名称。

第一个样本用于JRebirth演示应用程序 ,它是一个非常简单的应用程序,允许显示其他JRebirth展示应用程序作为JRebirth模块动态加载(来自一个单独的独立jar)。

 public final class JRebirthDemo extends DefaultApplication { public static void main(final String... args) { Application.launch(JRebirthDemo.class, args); } @Override public Class firstModelClass() { return MainModel.class; } @Override protected String applicationTitle() { return "JRebirth Demo Application"; } @Override protected void customizeScene(final Scene scene) { super.customizeScene(scene); addCSS(scene, DemoStyles.DEFAULT); addCSS(scene, WorkbenchStyles.DEFAULT); } @Override protected void customizeStage(final Stage stage) { // Center the stage stage.centerOnScreen(); } @Override protected List> getResourceToPreload() { return Collections.emptyList(); } } 

此应用程序将加载其第一个模型(MainModel)并将其根节点放入场景根节点(StakPane,自动构建)。

MainModel将列出所有应用程序的子模块,以在其左侧菜单中添加按钮条目,以及将显示每个模块内容的StackModel。 StackModel使用特殊的注释使用其唯一的String键加载。

 public final class MainModel extends DefaultModel { private final List modules = new ArrayList<>(); @Link("DemoStack") private StackModel stackModel; @Override protected void initModel() { for (final ModuleModel mm : getModels(ModuleModel.class)) { this.modules.add(mm); } } @Override protected void showView() { view().node().setCenter(this.stackModel.node()); } @Override protected void hideView() { // Nothing to do yet } List getModules() { return this.modules; } } 

MainView将负责创建模块菜单:

 public final class MainView extends DefaultView { private final List 

当触发任何菜单按钮时,MainController将加载Module内容:

 public final class MainController extends DefaultController implements ActionAdapter { public MainController(final MainView view) throws CoreException { super(view); } public void onButtonFired(final ActionEvent event) { final Button b = (Button) event.getSource(); final UniqueKey data = (UniqueKey) b.getUserData(); model().sendWave(StackWaves.SHOW_PAGE_MODEL, WBuilder.waveData(StackWaves.PAGE_MODEL_KEY, data), WBuilder.waveData(StackWaves.STACK_NAME, "DemoStack")); } } 

第二个示例将StackModel作为innerComponent加载,每个卡将由枚举条目(存储到FXMLPage)标识,让我们看看FXMLShowCaseModel:

 final InnerComponent stack = CBuilder.innerComponent(StackModel.class, FXMLPage.class); this.stackModel = findInnerComponent(stack); 

将枚举条目与Model链接的枚举:

 public enum FXMLPage implements PageEnum { StandaloneFxml, IncludedFxml, ViewEmbeddedFxml, HybridFxml; @Override public UniqueKey getModelKey() { UniqueKey modelKey; switch (this) { default: case ViewEmbeddedFxml: modelKey = Key.create(EmbeddedModel.class); break; case StandaloneFxml: modelKey = Key.create(StandaloneModel.class); break; case HybridFxml: modelKey = Key.create(HybridModel.class, FXMLModel.KEYPART_FXML_PREFIX + "org.jrebirth.af.showcase.fxml.ui.hybrid.Hybrid"); break; case IncludedFxml: modelKey = Key.create(IncludedModel.class, new LoremIpsum()); break; } return modelKey; } } 

由于卡列表是已知的,因此工具栏项会静态创建到FXMLShowCaseView中,并且事件处理也会使用另一种技术在FXMLShowCaseController中静态定义:

 public final class FXMLShowCaseController extends DefaultController { private static final Logger LOGGER = LoggerFactory.getLogger(FXMLShowCaseController.class); public FXMLShowCaseController(final FXMLShowCaseView view) throws CoreException { super(view); } @Override protected void initEventAdapters() throws CoreException { // WaveData> stackName = Builders.waveData(StackWaves.STACK_PAGES, FXMLShowCaseModel.STACK_PAGES); // Manage Ui Command Button linkWave(view().getShowIncluded(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM, WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.IncludedFxml)); linkWave(view().getShowEmbedded(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM, WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.ViewEmbeddedFxml)); linkWave(view().getShowStandalone(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM, WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.StandaloneFxml)); linkWave(view().getShowHybrid(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM, WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.HybridFxml)); } } 

如果您有任何疑问,请告诉我