How to find the ListCell which is at the location of the drop position in javafx - javafx

I have a ListView which is a dragdrop target. When handling OnDragDropped event, I would like to find the list cell which is at the position of the mouse. In addition I want to highlight items when mouse is hovered above them even during a drag drop operation. How can this be achieved in JavaFx.

Use a cell factory on the list view to define custom cells: that way you can register the drag handlers with the individual cells, instead of with the list view. Then it is easy for the drag handlers to know which cells have fired the event.
Here is a SSCCE:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class ListViewWithDragAndDrop extends Application {
#Override
public void start(Stage primaryStage) {
ListView<String> listView = new ListView<>();
listView.getItems().addAll("One", "Two", "Three", "Four");
listView.setCellFactory(lv -> {
ListCell<String> cell = new ListCell<String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty) ;
setText(item);
}
};
cell.setOnDragOver(e -> {
Dragboard db = e.getDragboard();
if (db.hasString()) {
e.acceptTransferModes(TransferMode.COPY);
}
});
cell.setOnDragDropped(e -> {
Dragboard db = e.getDragboard();
if (db.hasString()) {
String data = db.getString();
if (cell.isEmpty()) {
System.out.println("Drop on empty cell: append data");
listView.getItems().add(data);
} else {
System.out.println("Drop on "+cell.getItem()+": replace data");
int index = cell.getIndex();
listView.getItems().set(index, data);
}
e.setDropCompleted(true);
}
});
// highlight cells when drag target. In real life, use an external CSS file
// and CSS pseudoclasses....
cell.setOnDragEntered(e -> cell.setStyle("-fx-background-color: gold;"));
cell.setOnDragExited(e -> cell.setStyle(""));
return cell ;
});
TextField textField = new TextField();
textField.setPromptText("Type text and drag to list view");
textField.setOnDragDetected(e -> {
Dragboard db = textField.startDragAndDrop(TransferMode.COPY);
String data = textField.getText();
Text text = new Text(data);
db.setDragView(text.snapshot(null, null));
ClipboardContent cc = new ClipboardContent();
cc.putString(data);
db.setContent(cc);
});
BorderPane root = new BorderPane(listView, textField, null, null, null);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Related

Drag and Drop an item from a treeview into a textArea

I would like to drag and drop an item from a treeview into a textArea.
The goal is to write in the textArea the item dropped.
So if i choose to drop the item b, I would like to have b written in the textArea.
I have two problems.
1°) I have an error
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Only serializable objects or ByteBuffer can be used as data with data format []
2°) My setOn events don't run at all.
At any time, an event is detected.
package application;
import java.io.Serializable;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class testDragAndDropTreeView extends Application implements Serializable {
private final TreeView<String> tree = new TreeView<String>();
private final TextArea text = new TextArea();
private static final DataFormat DATAFORMAT = new DataFormat();
#Override
public void start(Stage Stage) {
HBox hbox = new HBox();
hbox.setPadding(new Insets(20));
TreeItem<String> a = new TreeItem<String>("a");
TreeItem<String> b = new TreeItem<String>("b");
TreeItem<String> c = new TreeItem<String>("c");
TreeItem<String> root = new TreeItem<String>("Root");
root.getChildren().addAll(a, b, c);
root.setExpanded(true);
tree.setRoot(root);
tree.setOnDragDetected(event -> {
Dragboard db = tree.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.put(DATAFORMAT, tree.getSelectionModel().getSelectedItem());
db.setContent(content);
});
text.setOnDragOver(event -> {
if (event.getGestureSource() != text && event.getDragboard().hasContent(DATAFORMAT)) {
event.acceptTransferModes(TransferMode.ANY);
}
event.consume();
});
text.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasContent(DATAFORMAT)) {
Person droppedPerson = (Person) db.getContent(DATAFORMAT);
text.appendText(droppedPerson.getName() + "\n");
success = true;
}
event.setDropCompleted(success);
event.consume();
});
tree.setCellFactory(param -> {
return new TreeCell<String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null) {
setStyle(null);
setGraphic(null);
setText(null);
return;
}
setText(item);
}
};
});
hbox.getChildren().addAll(tree, text);
Stage.setScene(new Scene(hbox));
Stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
A few of observations:
You were trying to put TreeItems in the clipboard content, but they aren't serializable and are not of the expected type, so they don't fit. You actually wanted to put the value of the tree items in the clipboard (I think).
You can just use a map to transfer data (clipboard content is also a map, so I guess you could still use that if you wanted).
You just want strings of data, so you should use DataFormat.PLAIN_TEXT and put a string in the transfer object.
You should cater for what to do if nothing is selected (selected item is null).
Your code was referencing a non-existent class Person, I just changed it to String.
The action of initiating a drag from a tree item selects the tree item before the drag occurs (this is the default operation of the tree with the mouse events you are consuming, not additional code).
The action of initiating a drag from a blank cell below the visible tree items, will drag and drop the selected item (if there is one or nothing at all), which is a bit strange but sounds like what you want to occur from comments.
An alternative would be to define drag handlers on the tree cells themselves rather than the entire tree, but that differs a bit from the design you seem to have.
Your code wasn't consistently following camel case naming conventions for Java, so I fixed some names. It is especially a bad idea to name a Stage variable Stage exactly the same case as the class name, as that is really confusing.
The root is shown and draggable. If you don't want the root shown, you can call tree.setShowRoot(false).
Example
Test this modification of your code and verify if it does what you want. If it is not exactly what you want, perhaps you can use it as a new starting point and tweak it how you want.
import java.io.Serializable;
import java.util.Map;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class DragAndDropTreeViewApp extends Application implements Serializable {
private static final DataFormat DATA_FORMAT = DataFormat.PLAIN_TEXT;
private final TreeView<String> tree = new TreeView<>();
private final TextArea text = new TextArea();
#Override
public void start(Stage stage) {
HBox hbox = new HBox();
hbox.setPadding(new Insets(20));
TreeItem<String> a = new TreeItem<>("a");
TreeItem<String> b = new TreeItem<>("b");
TreeItem<String> c = new TreeItem<>("c");
TreeItem<String> root = new TreeItem<>("Root");
//noinspection unchecked
root.getChildren().addAll(a, b, c);
root.setExpanded(true);
tree.setRoot(root);
tree.setOnDragDetected(event -> {
if (tree.getSelectionModel().getSelectedItem() != null) {
Dragboard db = tree.startDragAndDrop(TransferMode.ANY);
db.setContent(
Map.of(
DATA_FORMAT,
tree.getSelectionModel().getSelectedItem().getValue()
)
);
}
});
text.setOnDragOver(event -> {
if (event.getGestureSource() != text && event.getDragboard().hasContent(DATA_FORMAT)) {
event.acceptTransferModes(TransferMode.ANY);
}
event.consume();
});
text.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasContent(DATA_FORMAT)) {
String droppedPerson = (String) db.getContent(DATA_FORMAT);
text.appendText(droppedPerson + "\n");
success = true;
}
event.setDropCompleted(success);
event.consume();
});
tree.setCellFactory(param -> new TreeCell<>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setStyle(null);
setGraphic(null);
setText(null);
return;
}
setText(item);
}
});
hbox.getChildren().addAll(tree, text);
stage.setScene(new Scene(hbox));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}

JavaFx Tableview checkbox requires focus

I implemented boolean representation in my tableView as checkbox. It works fine in general but very irritating fact is that it requires row to be focused (editing) to apply change of checkbox value. It means I first have to double click on the field and then click checkbox.
How to make checkbox change perform onEditCommit right away?
public class BooleanCell<T> extends TableCell<T, Boolean> {
private CheckBox checkBox;
public BooleanCell() {
checkBox = new CheckBox();
checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (isEditing())
commitEdit(newValue == null ? false : newValue);
}
});
setAlignment(Pos.CENTER);
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
this.setEditable(true);
}
#Override
public void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
checkBox.setSelected(item);
setGraphic(checkBox);
}
}
}
I'm not sure about the rest of your implementation, but I assume you do not have your TableView set to editable:
tableView.setEditable(true);
On a side note, you could easily use a CheckBoxTableCell instead of implementing your own (BooleanCell).
Here is a very simple application you can run to see how this works. Each CheckBox may be clicked without first focusing the row and its value updates your underlying model as well (which you can see by clicking the "Print List" button).
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CheckBoxTableViewSample extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
// Simple interface
VBox root = new VBox(5);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
// List of sample items
ObservableList<MyItem> myItems = FXCollections.observableArrayList();
myItems.addAll(
new MyItem(false, "Item 1"),
new MyItem(false, "Item 2"),
new MyItem(true, "Item 3"),
new MyItem(false, "Item 4"),
new MyItem(false, "Item 5")
);
// Create TableView
TableView<MyItem> tableView = new TableView<MyItem>();
// We need the TableView to be editable in order to allow each CheckBox to be selectable
tableView.setEditable(true);
// Create our table Columns
TableColumn<MyItem, Boolean> colSelected = new TableColumn<>("Selected");
TableColumn<MyItem, String> colName = new TableColumn<>("Name");
// Bind the columns with our model's properties
colSelected.setCellValueFactory(f -> f.getValue().selectedProperty());
colName.setCellValueFactory(f -> f.getValue().nameProperty());
// Set the CellFactory to use a CheckBoxTableCell
colSelected.setCellFactory(param -> {
return new CheckBoxTableCell<MyItem, Boolean>();
});
// Add our columns to the TableView
tableView.getColumns().addAll(colSelected, colName);
// Set our items to the TableView
tableView.setItems(myItems);
// Create a button to print out our list of items
Button btnPrint = new Button("Print List");
btnPrint.setOnAction(event -> {
System.out.println("-------------");
for (MyItem item : myItems) {
System.out.println(item.getName() + " = " + item.isSelected());
}
});
root.getChildren().addAll(tableView, btnPrint);
// Show the Stage
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
/**
* Just a simple sample class to display in our TableView
*/
final class MyItem {
// This property will be bound to the CheckBoxTableCell
private final BooleanProperty selected = new SimpleBooleanProperty();
// The name of our Item
private final StringProperty name = new SimpleStringProperty();
public MyItem(boolean selected, String name) {
this.selected.setValue(selected);
this.name.set(name);
}
public boolean isSelected() {
return selected.get();
}
public BooleanProperty selectedProperty() {
return selected;
}
public void setSelected(boolean selected) {
this.selected.set(selected);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
}

JavaFX Dynamic Form Field UI

Does anyone know how to imitate the functionality from the UI components shown below? I want to replicate adding form fields when text is entered into the TextField box. I don't need the dropdown button, just the dynamic adding of the forms.
You could modify the children of a GridPane adding a new TextField & Button every time one of the buttons is activated. Listen to the text properties to enable/disable the Button and save the results.
private static void insertRow(GridPane grid, List<String> values, int index) {
// increment index of children with rowIndex >= index
for (Node n : grid.getChildren()) {
int row = GridPane.getRowIndex(n);
if (row >= index) {
GridPane.setRowIndex(n, row + 1);
}
}
TextField text = new TextField();
Button add = new Button("+");
add.setDisable(true);
add.setOnAction(evt -> {
insertRow(grid, values, GridPane.getRowIndex(add) + 1);
});
values.add(index, "");
text.textProperty().addListener((a, oldValue, newValue) -> {
add.setDisable(newValue.isEmpty());
values.set(GridPane.getRowIndex(add), newValue);
});
grid.addRow(index, text, add);
}
#Override
public void start(Stage primaryStage) throws Exception {
GridPane grid = new GridPane();
List<String> list = new ArrayList<>();
insertRow(grid, list, 0);
Button print = new Button("print");
print.setOnAction(evt -> {
System.out.println(list);
});
grid.add(print, 0, 1);
Scene scene = new Scene(grid, 300, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
This may not be exactly what you're looking for and may not be the best way to do this, but should be easy to adapt it to your needs.
Basically, you will need a list of HBox objects to be added to a VBox in your application. You could create the list yourself and bind it to the children of your VBox, or just add/remove the HBoxes to/from the VBox using the getChildren().add() and getChildren().remove() methods.
Here is a complete little application to demonstrate the concept. I created an internal class to handle the HBox with the fields you need. This could be adapted to be more felixable:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
private static VBox mainPane;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
mainPane = new VBox(5);
mainPane.setPadding(new Insets(10));
mainPane.setAlignment(Pos.TOP_CENTER);
mainPane.getChildren().add(new UIForms());
primaryStage.setScene(new Scene(mainPane));
primaryStage.show();
}
static void addField() {
mainPane.getChildren().add(new UIForms());
}
static void removeField(UIForms field) {
if (mainPane.getChildren().size() > 1) {
mainPane.getChildren().remove(field);
}
}
}
class UIForms extends HBox {
private TextField textField1;
private TextField textField2;
private Button btnAddField;
private Button btnRemoveField;
public UIForms() {
// Setup the HBox layout
setAlignment(Pos.CENTER_LEFT);
setSpacing(5);
// Create the UI controls
textField1 = new TextField();
textField2 = new TextField();
btnAddField = new Button("+");
btnRemoveField = new Button("-");
// Setup button actions
btnAddField.setOnAction(e -> Main.addField());
btnRemoveField.setOnAction(e -> Main.removeField(this));
// Add the UI controls
getChildren().addAll(
textField1, textField2, btnAddField, btnRemoveField
);
}
}

Change TableCell style on focus without setCellSelectionEnabled

Is there a way to style a TableCell in a TableView without tableView.getSelectionModel().setCellSelectionEnabled(true); in JavaFX?
I tried this solution https://community.oracle.com/thread/3528543?start=0&tstart=0 but it randomly fails to highlight the row
ex:
tableView.getSelectionModel().setCellSelectionEnabled(true);
final ObservableSet<Integer> selectedRowIndexes = FXCollections.observableSet();
final PseudoClass selectedRowPseudoClass = PseudoClass.getPseudoClass("selected-row");
tableView.getSelectionModel().getSelectedCells().addListener((Change<? extends TablePosition> change) -> {
selectedRowIndexes.clear();
tableView.getSelectionModel().getSelectedCells().stream().map(TablePosition::getRow).forEach(row -> {
selectedRowIndexes.add(row);
});
});
tableView.setRowFactory(tableView -> {
final TableRow<List<StringProperty>> row = new TableRow<>();
BooleanBinding selectedRow = Bindings.createBooleanBinding(() ->
selectedRowIndexes.contains(row.getIndex()), row.indexProperty(), selectedRowIndexes);
selectedRow.addListener((observable, oldValue, newValue) -> {
row.pseudoClassStateChanged(selectedRowPseudoClass, newValue);
}
);
return row;
});
Okay. So as long as your cell actually gets the focus, providing a custom TableCell to the cell factory of the column you want to style differently will allow you to listen to any property of the TableCell, since you are defining that TableCell yourself. Below is an example on how to listen to the focusedProperty of the TableCell and change the style when that happens.
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MCVE3 extends Application {
#Override
public void start(Stage stage) {
TableView<ObservableList<String>> table = new TableView<ObservableList<String>>();
// I have no idea how to get focus on a cell unless you enable cell selection. It does not seem to be possible at all.
table.getSelectionModel().setCellSelectionEnabled(true);
// Initializes a column and adds it to the table.
TableColumn<ObservableList<String>, String> col = new TableColumn<ObservableList<String>, String>("Column");
col.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().get(0)));
// Initializes a column and adds it to the table.
TableColumn<ObservableList<String>, String> col2 = new TableColumn<ObservableList<String>, String>("Column 2");
col2.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().get(1)));
// We add a custom cell factory to second column. This enables us to customize the behaviour of the cell.
col2.setCellFactory(e -> new FocusStyleCell());
table.getColumns().addAll(col, col2);
// Add data to the table.
table.getItems().add(FXCollections.observableArrayList("One", "OneTwo"));
table.getItems().add(FXCollections.observableArrayList("Two", "TwoTwo"));
table.getItems().add(FXCollections.observableArrayList("Three", "ThreeTwo"));
table.getItems().add(FXCollections.observableArrayList("Four", "FourTwo"));
BorderPane view = new BorderPane();
view.setCenter(table);
stage.setScene(new Scene(view));
stage.show();
}
/**
* A custom TableCell that will change style on focus.
*/
class FocusStyleCell extends TableCell<ObservableList<String>, String> {
// You always need to override updateItem. It's very important that you don't forget to call super.updateItem when you do this.
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(item);
}
}
public FocusStyleCell() {
// We add a listener to the focusedProperty. newValue will be true when the cell gets focused.
focusedProperty().addListener((obs, oldValue, newValue) -> {
if (newValue) {
setStyle("-fx-background-color: black;");
// // Or add some custom style class:
// if (getStyleClass().contains("focused-cell")) {
// getStyleClass().add("focused-cell");
// }
} else {
// If you instead wish to use style classes you need to
// remove that style class once focus is lost.
// getStyleClass().remove("focused-cell");
setStyle("-fx-background-color: -fx-background");
}
});
}
}
public static void main(String[] args) {
launch();
}
}
I could not solve it using focus listener but it is possible using a MouseEvent.MOUSE_CLICKED
column.setCellFactory(column1 -> {
TableCell<List<StringProperty>, String> cell = new TextFieldTableCell<>();
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, e ->
cell.setStyle("-fx-border-color:black black black black;-fx-background-color:#005BD1;-fx-text-fill:white")
);
cell.addEventFilter(MouseEvent.MOUSE_EXITED, e ->
cell.setStyle("")
);
return cell;
});
Full example https://github.com/gadelkareem/aws-client/blob/master/src/main/java/com/gadelkareem/awsclient/application/Controller.java#L443

How to get focus on TextField within TabPane, when Enter Key is pressed (using Javafx)?

How to requestFocus on TextField of different Tabs of TabPane, whenever the Enter Key is pressed on that particular Tab.
Each Tab within TabPane contains TextField, whenever a particular Tab is selected using Enter Key, than the TextField within that Tab must get Focused (requestFocus)
package tabdemo;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TabDemo extends Application {
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.setPrefHeight(500);
VBox.setVgrow(tabPane, Priority.ALWAYS);
tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
tabPane.setStyle("-fx-background-color: #fff; -fx-border-color: #e7eaec #e7eaec #e7eaec #e7eaec; -fx-border-width: 6;");
Tab tab1 = new Tab();
tab1.setText(" Try Demo");
tab1.setId("TryDemo");
TextField username1 = new TextField();
tab1.setContent(username1);
Tab tab2 = new Tab();
tab2.setText(" Select Company");
tab2.setId("SelectCompany");
TextField username2 = new TextField();
tab2.setContent(username2);
Tab tab3 = new Tab();
tab3.setText(" Create Company");
tab3.setId("CreateCompany");
TextField username3 = new TextField();
tab3.setContent(username3);
//Add childen to tabpane
tabPane.getTabs().addAll(tab1, tab2, tab3);
StackPane root = new StackPane();
root.getChildren().add(tabPane);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
// Tabpane Change Listener
tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
#Override
public void changed(ObservableValue<? extends Tab> arg0, Tab oldtab, Tab newtab) {
if (newtab == tab1) {
}
if (newtab == tab2) {
}
if (newtab == tab3) {
//tab3.getContent().requestFocus();
//username3.requestFocus();
}
}
});
// End Tabpane Change Listener
// Root Listner
root.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.TAB || event.getCode() == KeyCode.ENTER) {
tabPane.requestFocus();
event.consume();
}
}
});
// END Root Listner
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Any help would be appreciated.
Change your implementation of the ChangeListener to this:
// Tabpane Change Listener
tabPane.getSelectionModel().selectedItemProperty().addListener((arg0, oldtab, newtab) -> {
TextField field = (TextField) newtab.getContent();
Platform.runLater(() -> field.requestFocus());
});
This ensures that the request for the focus is pushed as the last 'task' for the application thread.
See also RequestFocus in TextField doesn't work -JavaFX 2.1 and JavaFX: Focusing textfield programmatically

Resources