Agregar un componente personalizado a SceneBuilder 2.0

Tengo la necesidad de tener un oyente de selección y seleccionar el método en un panel para poder monitorear y presentar un resaltado cuando se hace clic en un nodo.

Hice lo siguiente:

public class PaneWithSelectionListener extends Pane { private ObjectProperty 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); } } 

Y esto funciona muy bien; sin embargo, ya no puedo trabajar con SceneBuilder porque mi FXML hace referencia a este PaneWithSelectionListener lugar de a Pane . No estoy seguro de cómo conseguir mi panel personalizado en SceneBuilder. He analizado otras preguntas y todas son una combinación de FXML y Controladores, donde esto es solo un Pane .

¿Alguien sabe de una manera de hacer esto, o quizás cambiar el Pane por un PaneWithSelectionListener en el momento de la inicialización?

Gracias

Si el problema es solo hacer que su clase personalizada esté disponible en SceneBuilder, puede hacerlo con los siguientes pasos:

  1. Agrupe su clase personalizada (y cualquier clase de apoyo, como Annotation ) como un archivo jar
  2. En SceneBuilder, active el botón desplegable al lado de “Biblioteca” en la parte superior del panel izquierdo: enter image description here
  3. Elija “Importar archivo JAR / FXML …”
  4. Seleccione el archivo Jar creado a partir del paso 1
  5. Asegúrese de que la clase a la que necesita acceder en SceneBuilder ( PaneWithSelectionListener ) esté marcada
  6. Presione “Importar componente”
  7. PaneWithSelectionListener ahora aparecerá en SceneBuilder en “Personalizar” en el panel izquierdo: enter image description here

Notará que el menú desplegable de SceneBuilder tiene una opción de “Carpeta de biblioteca personalizada”, desde la cual puede abrir la carpeta donde están almacenados los archivos jar. Para una opción rápida, puede simplemente copiar archivos jar a esta carpeta y (después de un breve retraso), las clases contenidas aparecerán en la lista “Personalizada”.

Creé un CustomCB un cuadro combinado que es de tipo un userObject. En mi caso, he usado como userObject. El proyecto completo y el TESTER están aquí. El primero es CustomCB, los componentes y el archivo JAR generado a partir de este código se agrega a la Biblioteca. Esto se puede cargar en SCENE BUILDER. A partir de entonces está disponible para el diseño de escena.

Entonces, por supuesto, tiene un probador CustomCB2, que también puede usar un FXML en lugar de la forma en que lo hice.

De hecho, quiero que los elementos que comiencen con el texto que escribo en el ComboBox aparezcan en la lista. Pero no sé cómo hacerlo. Porque FIRST NAME o LAST NAME de la clase PERSON pueden comenzar con ‘Pe’. Si encuentro una solución, la publicaré aquí.

Este es el componente personalizado.

 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; } } 

Este es el FXML para el componente personalizado.

 < ?xml version="1.0" encoding="UTF-8"?> < ?import javafx.scene.control.ComboBox?> < ?import javafx.scene.layout.VBox?>    

Este es el controlador para este FXML pero no lo menciona en el archivo FXML. Lanza error.

 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 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 values) { myCustomCombo.setItems(values); myCustomCombo.setEditable(true); TextFields.bindAutoCompletion(myCustomCombo.getEditor(), myCustomCombo.getItems()); } } 

Descargue controlsfx-8.40.12.jar de WEB e inclúyalo en BUILD PATH como biblioteca.

Ahora crea un archivo jar para este proyecto. “CustomCB.jar”.

Este archivo JAR debe incluirse como control personalizado en Scene Builder. Yo uso la versión 10.0.

Ahora que forma parte del generador de escenas, puede usar este componente en el diseño, a menos que pueda hacerlo de la manera que lo he hecho en mi CÓDIGO DE PRUEBA. Debe incluir “CustomCB.jar” como parte de la biblioteca para comstackción.

Este es el código para el probador.

 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 fathers = javafx.collections.FXCollections.observableArrayList(); static private javafx.collections.ObservableList 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)); } } 

Necesita muchas mejoras. Si alguien puede improvisar, por favor agrégalo aquí.