【问题标题】:Is it possible to do templating with FXML是否可以使用 FXML 进行模板化
【发布时间】:2016-06-13 12:15:19
【问题描述】:

我想知道是否有可能使用 FXML 来做模板,就像在 PHP 中使用 Twig 一样(当然还有很多其他模板引擎)

使用 Twig 你会有这样的视图:

布局:

<html>
<head>
    <title>{% block title %}My Website{% endblock %}</title>
</head>

<body>
{% block body %}{% endblock %}
</body>
</html>

一些页面:

{% extends "layout" }
{% block title %}{{ parent() }} - Some page{% endblock %}
{% block body %}
    <div>Some content</div>
{% endblock %}

这将在浏览器中呈现如下:

<html>
<head>
    <title>My Website - Some page</title>
</head>

<body>
    <div>Some content</div>
</body>
</html>

我的问题是:FXML 有没有这样的可能。因此,我们将使用标准 FXML 和一些在子 FXML 文件中重新定义的特殊标签来代替 HTML。

我现在有一个包含机制,但这不是我要搜索的。包含假设您必须重新定义“块”,即使是空文件。我想要的是继承机制。

是否可以使用 FXML?

【问题讨论】:

  • 没有像这样内置的,但请注意,您可以加载 FXML specifying only an InputStream。所以,虽然我从未尝试过,而且一开始可能需要做很多工作才能弄清楚如何去做,但应该可以使用任何通用 Java 模板库(例如Tiles)即时生成 FXML。
  • 感谢您的回答 James_D。不幸的是,JavaFX 中似乎没有预先构建任何东西来处理这种机制。不幸的是,它确实是一个不错的功能。
  • 另见这个问题,它可能提供了另一种方式来做这些事情:stackoverflow.com/questions/29042109/…
  • 我找到了一些方法来实现我想要的。有一个名为 pebble (mitchellbosecke.com/pebble/home) 的库在 Java 中复制了 Twig 的功能。它使用任何类型的文件(如果文件的标记没有覆盖我假设的 Pebble 标记)。然后该库为您提供呈现的内容,您可以将其写入可用于 FXML 的临时文件中。每当我尝试这个时,我会写一个更详细的帖子。

标签: java user-interface javafx-8 fxml


【解决方案1】:

这是我使用 Pebble 解决问题的方法。在我的实际项目中使用 Pebble 之前,以下示例为我提供了概念证明。我保持它非常简单,但它确实证明了我想要实现的目标是可能的。

布局.pebble.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>

<BorderPane id="page" prefWidth="1280.0" prefHeight="900.0" xmlns:fx="http://javafx.com/fxml">
    <top>
        <MenuBar BorderPane.alignment="CENTER">
            <menus>
                <Menu mnemonicParsing="false" text="File">
                    <items>
                        <MenuItem mnemonicParsing="false" onAction="#exitAction" text="Exit" />
                    </items>
                </Menu>

                <Menu mnemonicParsing="false" text="Help">
                    <items>
                        <MenuItem mnemonicParsing="false" text="About" />
                    </items>
                </Menu>
            </menus>
        </MenuBar>
    </top>

    <center>
        {% block body %}{% endblock %}
    </center>
</BorderPane>

索引.pebble.fxml:

{% extends "templates/Layout.pebble.fxml" %}

{% block body %}
<VBox xmlns:fx="http://javafx.com/fxml/1">
    <Text text="Test" />
</VBox>
{% endblock %}

App.java:

package be.dupirefr.pebblefx;

import java.io.File;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.template.PebbleTemplate;

import be.dupirefr.pebblefx.controllers.DumbController;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class App extends Application {
    public static void main(String args[]) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        PebbleEngine engine = new PebbleEngine.Builder().build();
        PebbleTemplate compiledTemplate = engine.getTemplate("templates/Index.pebble.fxml");

        Map<String, Object> context = new HashMap<>();

        File file = File.createTempFile("views/Index", "fxml");
        file.deleteOnExit();

        PrintWriter writer = new PrintWriter(file);
        compiledTemplate.evaluate(writer, context);
        writer.close();

        primaryStage.setTitle("Pebble test");

        FXMLLoader loader = new FXMLLoader();

        loader.setController(new DumbController());
        loader.setLocation(file.toURI().toURL());

        BorderPane pane = loader.load();
        Scene scene = new Scene(pane);

        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

进程生成了这个文件:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>

<BorderPane id="page" prefWidth="1280.0" prefHeight="900.0"
    xmlns:fx="http://javafx.com/fxml">
    <top>
        <MenuBar BorderPane.alignment="CENTER">
            <menus>
                <Menu mnemonicParsing="false" text="File">
                    <items>
                        <MenuItem mnemonicParsing="false" onAction="#exitAction"
                            text="Exit" />
                    </items>
                </Menu>

                <Menu mnemonicParsing="false" text="Help">
                    <items>
                        <MenuItem mnemonicParsing="false" text="About" />
                    </items>
                </Menu>
            </menus>
        </MenuBar>
    </top>

    <center>
        <VBox xmlns:fx="http://javafx.com/fxml/1">
            <Text text="Test" />
        </VBox>
    </center>
</BorderPane>

并且被 FXMLLoader 成功使用。

当然,您可以使用 Pebble 的其他功能,但我想看看它是否适用于任何类型的文件,以及 FXMLLoader 是否将临时文件作为输入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    相关资源
    最近更新 更多