I try to create my own component for JavaFX. In this component, there are 2 methods in which true or false is transmitted and, depending on this, the contents of the component change, but when you import the Jar file into Scene Builder, the Custom block has only one property and it is not editable.
How can I allow editing this property and add my own to it?
Github
Controller
public class ShowPassword extends Control { private final String DEF_STYLE_CLASS = "show-password"; public ShowPassword() { init(); } private void init() { getStyleClass().setAll(DEF_STYLE_CLASS); } @Override protected Skin<?> createDefaultSkin() { return new ShowPasswordSkin(this); } private BooleanProperty showing; private BooleanProperty showVisisble; public final void setShowing(boolean value){ ShowingProperty().set(value); } public final void setShowVisisble(boolean value){ ShowVisisbleProperty().set(value); } public final BooleanProperty ShowVisisbleProperty(){ if (showVisisble==null){ showVisisble = new BooleanPropertyBase() { @Override protected void invalidated() { final Boolean v = get(); pseudoClassStateChanged(PSEUDO_CLASS_SHOW_VISIBLE,v); } @Override public Object getBean() { return ShowPassword.this; } @Override public String getName() { return "show-visible"; } }; } return showVisisble; } public final BooleanProperty ShowingProperty(){ if (showing==null){ showing = new BooleanPropertyBase() { @Override protected void invalidated() { final Boolean v = get(); pseudoClassStateChanged(PSEUDO_CLASS_SHOWING,v); } @Override public Object getBean() { return ShowPassword.this; } @Override public String getName() { return "showing"; } }; } return showing; } public final boolean isShowing(){ return showing == null?false:showing.get(); } public final boolean isShowVisible(){ return showVisisble == null?false:showVisisble.get(); } @Override public String getUserAgentStylesheet() { return ShowPassword.class.getResource("showpassword.css").toExternalForm(); } private static final PseudoClass PSEUDO_CLASS_SHOWING = PseudoClass.getPseudoClass("showing"); private static final PseudoClass PSEUDO_CLASS_SHOW_VISIBLE = PseudoClass.getPseudoClass("show-visible"); } Skin
public class ShowPasswordSkin extends SkinBase<ShowPassword> { private Image lockImg = new Image(getClass().getResourceAsStream("/icon/lock.png")); private Image unlockImg = new Image(getClass().getResourceAsStream("/icon/unlock.png")); private GridPane container; private StackPane stackField; private ImageView leftImg; private ImageView rightImg; private TextField textField; private PasswordField passwordField; public ShowPasswordSkin(ShowPassword control) { super(control); container = new GridPane(); stackField = new StackPane(); leftImg = new ImageView(); rightImg = new ImageView(); textField = new TextField(); rightImg.setPickOnBounds(true); passwordField = new PasswordField(); container.setGridLinesVisible(true); RowConstraints row1 = new RowConstraints(); RowConstraints row2 = new RowConstraints(); RowConstraints row3 = new RowConstraints(); ColumnConstraints col1 = new ColumnConstraints(38,38,38); ColumnConstraints col2 = new ColumnConstraints(); ColumnConstraints col3 = new ColumnConstraints(38,38,38); container.getRowConstraints().addAll(row1,row2,row3); if (control.isShowVisible()){ col2.setMinWidth(100); col2.setMaxWidth(9999); col2.setHgrow(Priority.ALWAYS); container.getColumnConstraints().addAll(col1,col2); container.add(leftImg,0,0); container.add(stackField,1,0); }else { col2.setMinWidth(100); col2.setMaxWidth(9999); col2.setHgrow(Priority.ALWAYS); container.getColumnConstraints().addAll(col1,col2,col3); container.add(leftImg,0,0); container.add(stackField,1,0); container.add(rightImg,2,0); } leftImg.setImage(leftImage(control.isShowVisible())); stackField.getChildren().addAll(textField,passwordField); getChildren().add(container); rightImg.setOnMouseReleased(e -> mousePresed(control)); rightImg.setImage(showStateChanget(false)); control.ShowingProperty().addListener(((observable, oldValue, newValue) -> { System.out.println(newValue); if (newValue.booleanValue() != oldValue.booleanValue()){ rightImg.setImage(showStateChanget(newValue)); } })); } private Image leftImage(boolean value) { InputStream imageStram; if (value){ imageStram = getClass().getResourceAsStream("/icon/login.png"); }else { imageStram = getClass().getResourceAsStream("/icon/key.png"); } return new Image(imageStram); } private Image showStateChanget(boolean value) { fieldActive(textField,value); fieldActive(passwordField,!value); return value?unlockImg:lockImg; } private void fieldActive(TextField field,boolean value){ field.setDisable(!value); field.setVisible(value); field.setOpacity(value?1:0); } private void mousePresed(ShowPassword showPassword){ showPassword.setShowing(!showPassword.isShowing()); } @Override protected void layoutChildren(double contentX, double contentY, double contentWidth, double contentHeight) { ShowPassword showPassword = getSkinnable(); showPassword.setLayoutY(contentY); showPassword.setLayoutX(contentX); container.setLayoutX(contentX); container.setLayoutY(contentY); container.resize(showPassword.getWidth(),showPassword.getHeight()); } @Override protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { return (leftImg.getFitWidth()+(getSkinnable().isShowVisible()?rightImg.getFitWidth():0))-(leftInset+rightInset); } @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { return (leftImg.getFitHeight()+(getSkinnable().isShowVisible()?rightImg.getFitHeight():0))-(topInset+bottomInset); } @Override protected double computeMaxWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { return 9999; } @Override protected double computeMaxHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { return 9999; } } 