I am developing an javaFX application where the user has several textfields to fill and edit. I want that if you enter a new textfield by jumping from another by pressing TAB the content of the textfield is not selected and also the cursor is on the right. The textfields have an event listener that detects when they receive the focus and I have been testing various methods of the API to position the cursor and deselect content when entering the textfield, for the moment, all without success.
Where is my error?
id_ip2B_tf.focusedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (newValue) {
// 1 - don't work
id_ip2B_tf.deselect();
id_ip2B_tf.positionCaret(id_ip2B_tf.getLength());
// 2 - don't work
id_ip2B_tf.end();
}
}
Can you try wrapping the logic of setting the caret in Platform.runLater. Something like..
id_ip2B_tf.focusedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (newValue) {
Platform.runLater(()->{
id_ip2B_tf.deselect();
id_ip2B_tf.positionCaret(id_ip2B_tf.getLength());
});
}
}
});
Related
My problem is that I want my popups to either close or not be stay-on-top.
Currently, when I click on a window which is different from my app, the app disappears behind it, but the popups stay on top, in front of the window belonging to a different application.
I want the popups to either behave differently, or as a hack I would like to hide the popup.
I tried to do this with Listeners as I found these in other q&a on stackoverflow, but these Listeners never get called when I minimize or lose focus with the window.
I commented out the code which does not work in below code.
/*
* (non-Javadoc)
*
* #see javafx.application.Application#start(javafx.stage.Stage)
*/
#Override
public void start(Stage primaryStage)
{
log.debug("JavaFx start method");
//log.trace("is used", fileViewController.toString());
try
{
splash.start(primaryStage, () -> startMain());
primaryStage.toFront();
//HACK attempt
//primaryStage.setAlwaysOnTop(false);
//FIXME: this doesn't work (is not called)
/*
primaryStage.iconifiedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
System.err.println("minimized:" + t1.booleanValue());
popupBuilder.hide();
popupPicker.hide();
popupAbout.hide();
popupExecute.hide();
popupAdministration.hide();
popupLicensegenerator.hide();
popupProjects.hide();
}
});
*/
/*
* This doesn't work, either
primaryStage.focusedProperty().addListener(new ChangeListener<Boolean>(){
#Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) {
System.err.println("focus:" + newValue);
if (!newValue){
popupBuilder.hide();
popupPicker.hide();
popupAbout.hide();
popupExecute.hide();
popupAdministration.hide();
popupLicensegenerator.hide();
popupProjects.hide();
}else{
//nothing
}
}
});
*/
}
catch (Exception e)
{
log.error("Error during start initialization of main application!");
e.printStackTrace();
System.exit(1);
}
}
Is there possibility to keep focus on textField in JavaFX?
I do validation on textField using listener.
textField.textProperty().addListener(
new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (!validate(newValue)) {
textField.setStyle("-fx-text-fill: green;");
textField.requestFocus();
} else {
textField.setStyle("-fx-text-fill: black;");
}
}
}
);
It is function which returns boolean depending on textField value validity. If value is not valid then I change text color to RED. Then I want to keep focus on invalid textField and force user to correct value.
Can it be done?
Thanks in advance.
Also use a listener for the focused property which takes back the focus, when it's moved somewhere else:
ChangeListener<Boolean> focusLossListener = (observable, wasFocused, isFocused) -> {
if (!isFocused) {
tf.requestFocus();
}
};
textField.textProperty().addListener(
new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
textField.focusedProperty().removeListener(focusLossListener);
if (!validate(newValue)) {
textField.focusedProperty().addListener(focusLossListener);
textField.setStyle("-fx-text-fill: green;");
textField.requestFocus();
} else {
textField.setStyle("-fx-text-fill: black;");
}
}
}
);
I'm using this code to validate TextField for network port.
fieldNport.textProperty().addListener(new ChangeListener<String>()
{
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
{
IpAddressNameValidator.hide();
if (!newValue.matches("-?\\d+(\\.\\d+)?"))
{
MenuItem cc = new MenuItem(newValue + " is not correct network port");
cc.getStyleClass().add("validator-item");
IpAddressNameValidator.getItems().clear();
IpAddressNameValidator.getItems().add(cc);
IpAddressNameValidator.show(fieldNport, Side.RIGHT, 10, 0);
}
}
});
I noticed that the validator is not updated when I delete the old value with backspace. The only solution that I found is this IpAddressNameValidator.hide(); and then show the validator message again.
I there other way to refresh the validator message when I add or remove values? This solution works but the message is blinking when I add new values.
Every time the text changes and the regex expression matches then you are unnecessarily recreating the MenuItem etc. Rather do it like this:
fieldNport.textProperty().addListener(new ChangeListener<String>()
{
private MenuItem cc = new MenuItem();
{
cc.getStyleClass().add("validator-item");
ipAddressNameValidator.getItems().clear();
ipAddressNameValidator.getItems().add(cc);
}
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
{
if (!newValue.matches("-?\\d+(\\.\\d+)?"))
{
if ( ! ipAddressNameValidator.isShowing() )
{
ipAddressNameValidator.show(fieldNport, Side.RIGHT, 10, 0);
}
cc.setText( newValue + " is not correct network port" );
}
}
});
Is there anyway I can add items to a TreeView control just when a node gets expanded?
I'd like to add child items to a tree item when the users expands the parent item.
Use expandedProperty, like in the example below:
treeItem.expandedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
BooleanProperty bb = (BooleanProperty) observable;
TreeItem t = (TreeItem) bb.getBean();
_treeItemEventHandler.onTreeItemExpanded(t);
// add items to t
}
});
My JavaFx FXML application has an issue.
When I select a checkbox on a form, I want to execute a method based on the checkbox that was clicked. Is there any way that I can pass the name of the checkbox through to the method so I can perform some conditional work on it?
I have two checkboxes and only one can be selected. When I click on one, the other should be de-selected and vice versa. Obviously the code below will not work so I am looking to pass the name of the object that was clicked.
Any help would be appreciated,
many thanks.
#FXML private void updateRcs(){
if (chkRcsuri.isSelected()){
chkRcsuri2.setSelected(false);
}
if (chkRcsuri2.isSelected()){
chkRcsuri.setSelected(false);
}
}
You can use change tracking or use Event handling mechanism of JavaFX.
With checkboxes like this,
final CheckBox chk1 = new CheckBox("chk 1");
final CheckBox chk2 = new CheckBox("chk 2");
Change tracking
chk1.selectedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
chk2.setSelected(!newValue);
}
});
chk2.selectedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
chk1.setSelected(!newValue);
}
});
Using event handling
EventHandler eh = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if (event.getSource() instanceof CheckBox) {
CheckBox chk = (CheckBox) event.getSource();
System.out.println("Action performed on checkbox " + chk.getText());
if ("chk 1".equals(chk.getText())) {
chk2.setSelected(!chk1.isSelected());
} else if ("chk 2".equals(chk.getText())) {
chk1.setSelected(!chk2.isSelected());
}
}
}
};
chk1.setOnAction(eh);
chk2.setOnAction(eh);
Wouldn't radio buttons give you a mutually exclusive selection? Just make sure you set the groupname to be the same - selecting one would then automatically de-select the other and you can just put additional logic in the Action event.
Better than trying to re-write same functionality around checkboxes.
So I was trying to do a similar thing, except I had multiple checkboxes and then one that would be nonsensical to have selectable in conjuction with the others. I made two seperate listeners and set one general purpose one to the main boxes, and a specialized one to the exception.
#FXML private CheckBox redCB = new CheckBox();
#FXML private CheckBox blueCB = new CheckBox();
#FXML private CheckBox greenCB = new CheckBox();
#FXML private CheckBox whiteCB = new CheckBox();
#FXML private CheckBox blackCB = new CheckBox();
#FXML private CheckBox colorlessCB = new CheckBox();
//assigning listeners
redCB.selectedProperty().addListener(colorCheckChange);
blueCB.selectedProperty().addListener(colorCheckChange);
greenCB.selectedProperty().addListener(colorCheckChange);
whiteCB.selectedProperty().addListener(colorCheckChange);
blackCB.selectedProperty().addListener(colorCheckChange);
colorlessCB.selectedProperty().addListener(colorlessCheckChange);
//note: this is the only different one^^^
//making listeners
ChangeListener colorCheckChange = new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> ov,
Boolean old_val, Boolean new_val) {
if (new_val)
colorlessCB.setSelected(false);
}};
ChangeListener colorlessCheckChange = new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> ov,
Boolean old_val, Boolean new_val) {
if (new_val)
{
redCB.setSelected(false);
blueCB.setSelected(false);
greenCB.setSelected(false);
blackCB.setSelected(false);
whiteCB.setSelected(false);
}
}
};
The first one basically just makes sure that colorlessCB isn't selected while trying to select the other colors, and vice verca. This way you also avoid the problem of de-selecting one, and the other one automatically reselecting itself.
This is my solution. But be sure about the a variable to be appropriate for you
//First in FXML file
<CheckBox fx:id="chkbxAuto" mnemonicParsing="false" onAction="#autoConfig" text="Auto" />
// in controler
public class FXMLController implements Initializable {
private static int a = 0;
//references to lables
....
#FXML
private Label lblStateValue;
#FXML
private Group grpSetting; // a group of elements which I want to be disabled and enabled
...
#FXML
private void autoConfig(ActionEvent event) {
System.out.println("Configing automatically");
a++;
if(a%2==1){
lblStateValue.setText("Auto configuration enabled"); // it change a lable to show the state
grpSetting.setDisable(true); // it disable a group of elements
}
else{
lblStateValue.setText("Auto configuration disabled");
grpSetting.setDisable(false);
}
a%=10;
}
...
I know this question is pretty old, but I found when looking for the same problem. I found a solution which
a) seems clearer (at least to me comparing to the listener definition) for reading source code and
b) Defining a changeListener on a checkBox gave me some problems.
Anyway my solution was to define an onAction function for the checkbox.
yourCheckboxName.setOnAction(this::aFunctionName);
...
void aFunctionName() {
if(yourCheckboxName.isSelected()) {
doThis()
} else {
doThat()
}
}
Attention This needs Java8 or higher.
None of the above options take advantage of the most commpact lambda expresions that can be used to add this very repetitive listeners.
Let suppose you have two checkboxes:
chk1.selectedProperty().addListener((observable, oldValue, newValue) -> chk2.setSelected(!newValue));
chk2.selectedProperty().addListener((observable, oldValue, newValue) -> chk1.setSelected(!newValue));