【问题标题】:Creating Custom Control in Jar for Gluon Scene Builder 11.00在 Jar 中为 Gluon Scene Builder 11.00 创建自定义控件
【发布时间】:2019-12-31 19:15:55
【问题描述】:

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

Maven 项目。

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>

CustomControl.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!");
    }
}

CustomControlExample.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();
    }

}

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>

【问题讨论】:

标签: javafx jar custom-controls scenebuilder gluon


【解决方案1】:

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

什么是自定义控件

没有关于此的文档,但您可以查看当前的 source code in 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 />

如果 FXMLLoader 可以加载该 FXML,则它是自定义控件。 否则将被丢弃。

自定义控件的类型

关于如何构建自定义控件有多种方法,但如果您要使用 FXML,这个旧的 tutorial 给出了一些关于如何使用 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);
        }
    }
...
}

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>

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

场景生成器 11

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

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

注意:merged PR 允许使用项目的 build/target 目录,而不需要 jar。

如果是发布的自定义控件,你应该得到这个:

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

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
  • 2016-11-18
  • 2015-04-18
  • 2019-08-08
  • 2016-01-30
  • 1970-01-01
相关资源
最近更新 更多