5

I want to have a text displayed above a JavaFX-TextField. Setting the prompText is almost what I want, but has some drawbacks for my use case. The following code seems to work, but it feels wrong to add a Label to the children of the TextField. Does the following code violate any JavaFX principles or is it safe to use?

public class MyTextField extends TextField {    
    public MyTextField() {
        Label label = new Label("test");
        this.getChildren().add(label);
    }  
}
user7291698
  • 1,972
  • 2
  • 15
  • 30
  • 1
    The "correct" way to do this would probably be by defining a custom skin, but that would be a lot of work... What are the drawbacks of `promptText`? It's possible there may be workarounds for that which would be better... – James_D Dec 13 '17 at 14:24
  • @James_D: `MyTextField` adds some functionality to the standard implementation, but an `init()` method needs to be called first so that this functionality works properly. The `init()` cannot be called from the constructor. The `Label` should give a hint to the developer(!) that he did not call the `init()` properly. I know there are plenty of other ways to remind the developer that he is doing something wrong, but this approach of a visible warning seemed to be the shortest. Can I interpret your comment that this code actually IS wrong? – user7291698 Dec 13 '17 at 14:39
  • 1
    It's probably not good practice to add a node as a child of a control, because you really have no idea whatsoever how child nodes of a control will be laid out; that's undefined in the UI and controls are simply not intended to be used that way. But modifying the UI as a signal to the *developer* that they have not used your classes correctly is far worse practice imho. You should throw an assertion error in this case, not modify the UI. (Just one example: what if you use some automated testing in the future; how is your label going to be detected in that case?) – James_D Dec 13 '17 at 14:44
  • @James_D: ok, many thanks, this answered my question! – user7291698 Dec 13 '17 at 15:01
  • 1
    @mrmcwolf he can not add label as graphic because `setGrahic(node`) is not available for `TextField` class. – Menai Ala Eddine - Aladdin Dec 13 '17 at 16:14
  • 1
    If you really really need a label inside a text field, use a stack pane and stack the label over the field. – Mordechai Dec 13 '17 at 19:45
  • You could use JFoenix's JFXTextField. You can float the label above the text field. [JFoenix](https://github.com/jfoenixadmin/JFoenix) is a very nice set of components if you like material design.. – RonSiven Dec 15 '17 at 17:20

2 Answers2

2

Based on :

Does the following code violate any JavaFX principles or is it safe to use?

In java this code is not safe to use because you call Overridable method in constructor and if you use Netbeans or any intellegent IDE,it will warn you with the message "Overridable method call in constructor" and the descritpion of the problem here is :

Calling methods that can be overridden can be dangerous in the contructor because in the moment when the overridden method is called the object is not fully initialized.

Second,you can add children nodes in Region,Group,Containers but it is not good practice to add child node to control ,and if you need add a label to TextField you can use CustomTextField of ControlFx ,and this example of code maybe is helpful for your need :

     Label myLabel=new Label("Hello");
    /*You use a container if you need add many nodes in CustomTextField*/
    //HBox box=new HBox();
    //box.getChildren().add(myLabel);
    CustomTextField customField=new CustomTextField();
    customField.setRight(mylabel);
    //customField.setLeft(mylabel);
    //customField.setRight(box);

Or by extending CustomTextField :

//This code is safe and the warning is removing here
public class MyTextField extends CustomTextField {

        public MyTextField() {
            Label label = new Label("test");
            this.setRight(label); 
        }
    }
0

Actually, what you can do and seems allowed by JavaFX (SceneBuilder shows it correctly) is add the TextField to the Pane on which you're working first and then on the next line of the fxml file add the label with a location inside the TextField. Like this:

        <TextField fx:id="txtUsername" alignment="BOTTOM_LEFT" layoutX="20.0" layoutY="20.0" prefHeight="40.0" prefWidth="250.0" promptText="User name / id" />
        <Label layoutX="24.0" layoutY="20.0" prefHeight="10.0" prefWidth="100.0" styleClass="label-small" text="User name" />

Then the label seems to be inside the TextField and with the alignment to bottom left of the TextField itself (and making it a bit higher; 40 instead of 32) the label shows up above the text in the TextField, but inside the boundaries of it

The -fx-font-size for label-small in my css file is 10

JeroenV
  • 53
  • 2
  • 10