在JavaFX中切换窗格
我正在尝试使用FXML在JavaFX中创建Java程序。 但是我在布局管理方面遇到了麻烦。 我想在Panes之间切换,就像我习惯使用CardLayout一样,但我似乎无法得到它。
我用Google搜索,没有找到任何答案。
JavaFX中是否有任何CardLayout等效项? 如果是的话,你能举一个例子吗? 这对我的晚会很有帮助!
这是我的FXML代码
非动画过渡
如果您不需要在窗格之间进行动画过渡,则可以:
- 通过创建新场景并在舞台上设置该场景来替换整个场景
- 通过从父窗体中删除旧窗格并添加新窗格(通过操纵父窗口的子窗口列表 )来替换父布局中的特定窗格,或者
- 将所有窗格放在
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 extends Model> 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 extends ResourceItem, ?, ?>> 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 extends Model> data = (UniqueKey extends Model>) 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 extends Model> getModelKey() { UniqueKey extends Model> 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)); } }
如果您有任何疑问,请告诉我