【问题标题】:Adding a custom component to SceneBuilder 2.0向 SceneBuilder 2.0 添加自定义组件
【发布时间】:2015-07-15 19:49:07
【问题描述】:

我需要有一个选择侦听器和一个窗格上的选择方法,以便能够在单击节点时监视并呈现突出显示。

我做了以下事情:

public class PaneWithSelectionListener extends Pane {

    private ObjectProperty<Annotation> selectedAnnotation = new SimpleObjectProperty<>();

    public PaneWithSelectionListener() { 
        super();
        selectedAnnotation.addListener((obs, oldAnno, newAnno) -> {
            if (oldAnno != null) {
                oldAnno.setStyle("");
            }
            if (newAnno != null) {
                newAnno.setStyle("-fx-border-color: blue;-fx-border-insets: 5;-fx-border-width: 1;-fx-border-style: dashed;");
            }
        });

        setOnMouseClicked(e->selectAnnotation(null));
    }

    public void selectAnnotation(Annotation ann){
        selectedAnnotation.set(ann);
    }
}

这很好用——但是我不能再使用 SceneBuilder,因为我的 FXML 引用了这个 PaneWithSelectionListener 而不是 Pane。我不确定如何将我的自定义窗格放入 SceneBuilder。我查看了其他问题,它们都是 FXML 和控制器的组合 - 这只是 Pane

有谁知道这样做的方法,或者在初始化时将Pane 换成PaneWithSelectionListener

谢谢

【问题讨论】:

  • 你只需要单选吗?
  • 是的 - 我只需要单选。我在图像顶部表示注释。如果用户点击一个 - 它应该选择。我认为他们不需要多项选择。只是一个将受到影响的指标。谢谢。

标签: javafx javafx-8 scenebuilder


【解决方案1】:

如果问题只是为了让您的自定义类在 SceneBuilder 中可用,您可以通过以下步骤来实现:

  1. 将您的自定义类(以及任何支持类,例如 Annotation)捆绑为 jar 文件
  2. 在 SceneBuilder 中,激活左窗格顶部“库”旁边的下拉按钮:
  3. 选择“导入 JAR/FXML 文件...”
  4. 选择步骤 1 中创建的 Jar 文件
  5. 确保在 SceneBuilder (PaneWithSelectionListener) 中您需要访问的类被选中
  6. 按“导入组件”
  7. PaneWithSelectionListener 现在将出现在左侧窗格中“自定义”下的 SceneBuilder 中:

您会注意到 SceneBuilder 中的下拉菜单有一个“自定义库文件夹”选项,您可以从中打开存储 jar 文件的文件夹。为了快速选择,您可以将 jar 文件复制到此文件夹,并且(经过短暂延迟),包含的类将出现在“自定义”列表中。

【讨论】:

  • 我昨天确实试过了,但是当我尝试加载它时,选择是空白的。
  • 好吧,这很奇怪。我将我的组件移动到另一个包中并导出了 jar 并且它工作了。
  • 如果你把它放在默认包中,我认为它会失败(FXML 通常不能很好地与默认包配合,尽管唯一的损失是非常快速的测试代码)。
  • 如果使用 SceneBuilder 2.0 或更低版本,从 eclipse 打开时,此解决方案仍无法使用自定义控件加载 fxml。为了完成这项工作,您需要将 jar 添加到 SceneBuilder 的 package.cfg 文件中。请参阅此已接受答案here 的底部。注意:Linux 使用 ':' 而不是 ';'将路径上的罐子分开
  • 对我也不起作用。组件类在 jar 文件中,但选择对话框为空白。不,我不会将它移到单独的包中,然后必须跟踪和维护两个项目。
【解决方案2】:

我创建了一个 CustomCB 一个用户对象类型的组合框。在我的例子中,我使用了&lt;APerson&gt; 作为用户对象。整个项目和测试仪都在这里。第一个是 CustomCB,将由此代码生成的组件和 JAR 文件添加到库中。这可以在 SCENE BUILDER 中加载。此后可用于场景设计。

那么当然,你有一个测试仪CustomCB2,它也可以使用FXML而不是我做的方式。

我实际上希望以我在 ComboBox 中键入的文本开头的项目出现在列表中。但我不知道该怎么做。因为 PERSON 类的 FIRST NAME 或 LAST NAME 可以以“Pe”开头。如果我找到解决方案,我会在这里发布。

这是自定义组件。

package customCB;
    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    import javafx.beans.property.IntegerProperty;
    import javafx.beans.property.SimpleIntegerProperty;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;

    /**
     *
     * @author Hornigold Arthur
     */

    public class APerson {

    private final StringProperty firstName;
    private final StringProperty lastName;
    private final IntegerProperty familyID;
    private final IntegerProperty personID;

    public APerson() {
        this(null, null, 0,0);
    }

    /**
     * Constructor with some initial data.
     * 
     * @param familyID
     * @param familyName
     */

    public  APerson (String firstName, String lastName, int familyID, int personID) {
        this.firstName = new SimpleStringProperty(firstName);
        this.lastName = new SimpleStringProperty(lastName);
        this.familyID = new SimpleIntegerProperty(familyID);
        this.personID = new SimpleIntegerProperty(personID);
    }

    public int getFamilyID() {
        return familyID.get();
    }

    public void setFamilyID(int FamilyID) {
        this.familyID.set(FamilyID);
    }

    public IntegerProperty familyIDProperty() {
        return familyID;
    }

    public int getPersonID() {
        return personID.get();
    }

    public void setPersonID(int PersonID) {
        this.personID.set(PersonID);
    }

    public IntegerProperty personIDProperty() {
        return personID;
    }

    public String getFirstName() {
        return firstName.get();
    }

    public void setFirstName(String FirstName) {
        this.firstName.set(FirstName);
    }

    public StringProperty firstNameProperty() {
        return firstName;
    }

    public String getLastName() {
        return lastName.get();
    }

    public void setLastName(String LastName) {
        this.lastName.set(LastName);
    }

    public StringProperty lastNameProperty() {
        return lastName;
    }


    public String toString() {
        String name = getFirstName() + " " + getLastName()+ " [" + getFamilyID() +"]";
        return name;
    }
}

这是自定义组件的 FXML。

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

<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.layout.VBox?>

<fx:root stylesheets="@application.css" type="javafx.scene.layout.VBox" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <ComboBox fx:id="myCustomCombo" editable="true" onAction="#cbOnAction" prefWidth="300.0" style="-fx-background-color: white;" />
</fx:root>

这是此 FXML 的控制器,但未在 FXML 文件中提及。它会引发错误。

package customCB;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import org.controlsfx.control.textfield.TextFields;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;

public class CustomComboController extends VBox{

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML
    private ComboBox<APerson> myCustomCombo;

    @FXML
    void cbOnAction(ActionEvent event) {

    }

    @FXML
    void initialize() {
        assert myCustomCombo != null : "fx:id=\"myCustomCombo\" was not injected: check your FXML file 'CustomLvFXML.fxml'.";
    }

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

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

    public void setCBValues(javafx.collections.ObservableList<APerson> values) {
        myCustomCombo.setItems(values);
        myCustomCombo.setEditable(true);
        TextFields.bindAutoCompletion(myCustomCombo.getEditor(), myCustomCombo.getItems());
    }

}

从 WEB 下载 controlsfx-8.40.12.jar 并将其作为库包含在 BUILD PATH 中。

现在为这个项目创建一个 jar 文件。 “CustomCB.jar”。

这个 JAR 文件必须作为自定义控件包含在 Scene Builder 中。我使用的是 10.0 版。

现在它是 Scene builder 的一部分,您可以在设计中使用此组件,除非您可以按照我在 TEST CODE 中所做的方式进行操作。您需要将“CustomCB.jar”作为构建库的一部分。

这是测试仪的代码。

package customCB2;


    import javafx.application.Application;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.layout.VBox;


    public class Main extends Application {

        static private javafx.collections.ObservableList<APerson> fathers = javafx.collections.FXCollections.observableArrayList();
        static private javafx.collections.ObservableList<APerson> mothers = javafx.collections.FXCollections.observableArrayList();



    @Override
    public void start(Stage stage) throws Exception {

        CustomComboController customControl2 = new CustomComboController();
        CustomComboController customControl3 = new CustomComboController();

        loadFathers();
        loadMothers();

        customControl2.setCBValues(fathers);
        customControl3.setCBValues(mothers);

        VBox root = new VBox();
        root.getChildren().addAll(customControl2, customControl3);

        stage.setScene(new Scene(root));
        stage.setTitle("Custom Control Combo box");
        stage.setWidth(300);
        stage.show();
    }

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

    private void loadFathers() {
        fathers.clear();
        fathers.add(new APerson("Hornigold","Arthur",1,63));
        fathers.add(new APerson("Andrews","Sundareson",2,60));
        fathers.add(new APerson("Christopher","Easweradoss",3,57));
        fathers.add(new APerson("Arthur","Kennedy",4,55));
    }

    private void loadMothers() {
        mothers.clear();
        mothers.add(new APerson("Victoria","Arthur",1,95));
        mothers.add(new APerson("Eliza", "Daniel",1,60));
        mothers.add(new APerson("Nesammal", "Rivington",2,57));
        mothers.add(new APerson("Ratnammal","Andews",1,55));
    }


}

它需要很多改进。如果有人可以即兴发挥,请在此处添加。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 2019-10-11
    • 1970-01-01
    相关资源
    最近更新 更多