Adicionando um componente personalizado ao SceneBuilder 2.0

Eu tenho a necessidade de ter um listener de seleção e selecionar o método em um painel para poder monitorar e apresentar um destaque quando um nó é clicado.

Eu fiz o seguinte:

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

E isso funciona muito bem – no entanto, não consigo mais trabalhar com o SceneBuilder, pois meu FXML faz referência a este PaneWithSelectionListener vez de ao Pane . Não sei como obter meu painel personalizado no SceneBuilder. Eu olhei para outras questões e elas são todas uma combinação de FXML e Controllers – onde isso é apenas um Pane .

Alguém sabe de uma maneira de fazer isso, ou talvez trocar o PaneWithSelectionListener por um PaneWithSelectionListener no momento da boot?

obrigado

    Se o problema é apenas disponibilizar sua class personalizada no SceneBuilder, você pode fazer isso com as seguintes etapas:

    1. Agrupe sua class personalizada (e quaisquer classs de suporte, como Annotation ) como um arquivo jar
    2. No SceneBuilder, ative o botão suspenso ao lado de “Biblioteca” na parte superior do painel esquerdo: insira a descrição da imagem aqui
    3. Escolha “Importar Arquivo JAR / FXML …”
    4. Selecione o arquivo Jar criado a partir do passo 1
    5. Certifique-se de que a class que você precisa acessar no SceneBuilder ( PaneWithSelectionListener ) esteja marcada
    6. Pressione “Importar Componente”
    7. PaneWithSelectionListener agora aparecerá no SceneBuilder em “Custom” no painel esquerdo: insira a descrição da imagem aqui

    Você notará que a lista suspensa no SceneBuilder tem uma opção “Pasta de biblioteca personalizada”, na qual você pode abrir a pasta em que os arquivos jar estão armazenados. Para uma opção rápida, você pode simplesmente copiar arquivos jar para esta pasta e (após um pequeno atraso), as classs contidas aparecerão na lista “Personalizada”.

    Eu criei um CustomCB uma checkbox de combinação que é do tipo um userObject. No meu caso, usei como userObject. Todo o projeto e o TESTER estão aqui. O primeiro é o CustomCB, os componentes e o arquivo JAR gerado a partir desse código são adicionados à Biblioteca. Isso pode ser carregado no SCENE BUILDER. Depois disso, está disponível para o design da cena.

    Então, é claro, você tem um testador CustomCB2, que também pode usar um FXML ao invés do que eu fiz.

    Eu realmente quero que os itens que começam com o texto que eu digito no ComboBox apareçam na lista. Mas eu não sei como fazer isso. Porque o PRIMEIRO NOME ou o ÚLTIMO NOME da class PESSOA pode começar com ‘Pe’. Se eu encontrar uma solução, vou postar aqui.

    Este é o 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 é o FXML para o componente personalizado.

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

    Este é o controlador para este FXML, mas não o menciona no arquivo FXML. Isso lança erro.

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

    Baixe o controlsfx-8.40.12.jar da WEB e inclua-o no campo BUILD PATH como biblioteca.

    Agora crie um arquivo jar para este projeto. “CustomCB.jar”.

    Esse arquivo JAR deve ser incluído como controle personalizado no Scene Builder. Eu uso a versão 10.0.

    Agora que é parte do construtor Scene, você pode usar este componente no design, a menos que você possa fazê-lo da maneira que eu fiz no meu CÓDIGO DE TESTE. Você precisa include “CustomCB.jar” como parte da biblioteca para criação.

    Este é o código para o testador.

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

    Precisa de muitas melhorias. Se alguém puder improvisar, por favor adicione aqui.