在 Jar 中为 Gluon Scene Builder 11.00 创建自定义控件

Gus*_*rio 6 javafx jar custom-controls scenebuilder gluon

我想在一个可执行的 jar 文件中创建一个自定义控件,然后在 Gluon Scene Builder 11.00 中使用。我需要知道如何做到这一点。我尝试了几种形式,但在 Scene Builder 中导入 jar 时我的控件没有出现。我正在使用 IntelliJ 社区版 2019.2 和 Gluon Scene Builder 11.00 和 Java 12.0.2。任何人都可以帮助我举一个小例子吗?

马文项目。

custom_control.fxml

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>

<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="51.0" prefWidth="138.0" type="VBox" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <TextField fx:id="textField" />
      <Button mnemonicParsing="false" onAction="#doSomething" prefHeight="25.0" prefWidth="142.0" text="Clck Me" />
   </children>
</fx:root>
Run Code Online (Sandbox Code Playgroud)

自定义控件.java

package customcontrolexample;

import java.io.IOException;

import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;

public class CustomControl extends VBox {
    @FXML private TextField textField;

    public CustomControl() {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(
                "custom_control.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    public String getText() {
        return textProperty().get();
    }

    public void setText(String value) {
        textProperty().set(value);
    }

    public StringProperty textProperty() {
        return textField.textProperty();
    }

    @FXML
    protected void doSomething() {
        System.out.println("The button was clicked!");
    }
}
Run Code Online (Sandbox Code Playgroud)

自定义控件示例.java

import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class CustomControlExample extends Application {

    private static Scene scene;

    @Override
    public void start(Stage stage) throws IOException {
        CustomControl customControl = new CustomControl();
        customControl.setText("Hello!");
        stage.setScene(new Scene(customControl));
        stage.setTitle("Custom Control");
        stage.setWidth(300);
        stage.setHeight(200);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

}
Run Code Online (Sandbox Code Playgroud)

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>customcontrol</groupId>
    <artifactId>CustomControlExample</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>12.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>12.0.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.3</version>
                <configuration>
                    <mainClass>CustomControlExample</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.1</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>CustomControlExample</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id> <!-- this is used for inheritance merges -->
                        <phase>package</phase> <!-- bind to the packaging phase -->
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>


</project>
Run Code Online (Sandbox Code Playgroud)

Jos*_*eda 5

当您想要创建可以使用 Scene Builder 导入的自定义控件时,需要考虑一些事项。

什么是自定义控件

没有关于此的文档,但您可以查看Scene Builder中的当前源代码,该代码探索 jar 中的所有类,并找到有效类作为自定义控件:

  • 类名不以java., javax., javafx., com.oracle.javafx.scenebuilder., com.javafx.,开头com.gluonhq
  • 具体类(非抽象类)
  • 可从Node. 这非常重要:该类应该是 JavaFX 节点的子类,例如容器(即扩展自VBox)或内置节点(即扩展自Button)。

对于找到的所有类,然后使用以下内容构建 FXML:

 <?import your.class.fullname?>
 <your.class.simplename />
Run Code Online (Sandbox Code Playgroud)

如果该 FXML 可以由 加载FXMLLoader,那么它就是一个自定义控件。否则它被丢弃。

自定义控件类型

关于如何构建自定义控件有多种方法,但是如果您打算使用 FXML,这个旧教程就如何使用fx:root和如何定义控制器提供了一些重要的说明,例如:

public class CustomControl extends VBox {

    public CustomControl() {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(
"custom_control.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
...
}
Run Code Online (Sandbox Code Playgroud)

Java 11 级别

最后,由于 Scene Builder 11 在 Java 11 上运行,因此必须编译 jar 并支持 Java 11。

使用 Maven:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
          <source>11</source>
          <target>11</target>
    </configuration>
</plugin>
Run Code Online (Sandbox Code Playgroud)

在转到 Scene Builder 之前,您可以在演示项目中尝试自定义控件。这将帮助您提前发现并解决可能出现的问题。

场景生成器 11

构建控件后,您可以打开 Scene Builder 11并按照文档将其导入。

基本上,使用该选项Add Library/FXML from file system并浏览您的文件系统来定位 jar。

注意:有一个合并的 PR将允许使用项目的 build/target 目录,而不是需要 jar。

对于发布的自定义控件,您应该得到以下信息:

自定义控件

如果视图未显示您的控件,则您必须首先解决一个问题。

注意:有一个待处理的PR,它将在进程失败时提供更多信息。

  • 有关其他信息,您还可以参考[如何将组件从 JAR 导入到 SceneBuilder](/sf/ask/2061128891/ -fxml-file-for-an-already-created-new-component-in-java-than-add) (2认同)