I want to reproduce that combobox in JavaFX
With swing there is a way by using a renderer where HTML code can be passed.
I haven't found a way yet to do it in JAVAFX. I saw the cellFactory but it seems to handle only one line of text.
I tried to use an observableList of WebView. I was able to display the information as desired, but then the onAction was never called. I tried by setting an event and a listener, but nothing worked. I tried the next examples separately.
cbOrderLine.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<WebView>() {
#Override
public void changed(ObservableValue<? extends WebView> arg0, WebView arg1, WebView arg2) {
int uasbdviadn = 0;
if (arg2 != null) {
System.out.println("Selected employee: " + arg2.getId() + " " + uasbdviadn);
}
}
});
cbOrderLine.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent ev) {
int index = cbOrderLine.getSelectionModel().getSelectedIndex();
initComboBox(index);
}
});
this is the code to create my dummy values
private List<WebView> createListFakeOrderLineItem() {
List<WebView> list = new ArrayList<>();
list.add(createFakeOrderLineItem(1));
list.add(createFakeOrderLineItem(2));
list.add(createFakeOrderLineItem(3));
list.add(createFakeOrderLineItem(4));
return list;
}
private WebView createFakeOrderLineItem(int id) {
WebView wv = new WebView();
wv.setPrefSize(684, 90);
ProductionOrderHeader header = new ProductionOrderHeader();
header.setPoNumber("PONumber1234");
ProductionOrderLine line = new ProductionOrderLine();
line.setId(3333);
ManufactureProduct product = new ManufactureProduct();
product.setId(1111);
product.setPartNumber("Product.PartNumber1111");
ManufacturePart part = new ManufacturePart();
part.setId(9999);
part.setPartNumber("Part.Partnumber9999");
part.setHardwareId(666666);
part.setHardwareName("Hardware Name");
OrderLineItem item = new OrderLineItem(id, header, line, part, product);
// return item;
wv.getEngine().loadContent(item.toString());
return wv;
}
This is my OrderLineItem
public class OrderLineItem {
Integer index;
ProductionOrderHeader header;
ProductionOrderLine line;
ManufacturePart part;
ManufactureProduct product;
public OrderLineItem(Integer index, ProductionOrderHeader header, ProductionOrderLine line, ManufacturePart part,
ManufactureProduct product) {
this.index = index;
this.header = header;
this.line = line;
this.part = part;
this.product = product;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public ProductionOrderHeader getHeader() {
return header;
}
public void setHeader(ProductionOrderHeader order) {
this.header = order;
}
public ProductionOrderLine getLine() {
return line;
}
public void setLine(ProductionOrderLine orderLine) {
this.line = orderLine;
}
public ManufacturePart getPart() {
return part;
}
public void setPart(ManufacturePart part) {
this.part = part;
}
public ManufactureProduct getProduct() {
return product;
}
public void setProduct(ManufactureProduct product) {
this.product = product;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("<html>");
sb.append("<table>");
sb.append("<tr>");
sb.append("<td valign=\"middle\" style=\"font-size: 32px; padding-right:5px;\">");
sb.append((index + 1));
sb.append("</td>");
sb.append("<td style=\"border: 1px solid #919191; width:616px; font-size:12px; padding:10px;\">");
sb.append("<b>");
sb.append(header.getPoNumber());
sb.append(" [");
sb.append(line.getId());
sb.append("] </b> -");
sb.append("<b>P/N: </b> #");
sb.append(product.getId());
sb.append("<b> ");
sb.append(product.getPartNumber());
sb.append("</b><br/>");
sb.append("Part: # ");
sb.append(part.getId());
sb.append("<b> ");
sb.append(part.getPartNumber());
sb.append("</b> H/W: # ");
sb.append(part.getHardwareId());
sb.append("<b> ");
sb.append(part.getHardwareName());
sb.append("</b>");
sb.append("</td>");
sb.append("</tr>");
sb.append("</table>");
sb.append("</html>");
return sb.toString();
}
}
I'm using JAVAFX 8.
Thanks
I saw the cellFactory but it seems to handle only one line of text.
Firstly your understanding of cellFactory is wrong. And also setting a WebView as your comboBox item is really a horrible idea :). Instead you can build a simple layout and set it as graphic in your cell factory.
And by the way, never set Nodes as items to your controls (ComboBox, ListView..etc), you can just pass your model and build the appropriate layout in cellFactories.
Below is a quick demo to give you an idea of how to build your desired comboBox. Hope this can help you to have a better understanding.
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
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.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MultiLineComboBoxDemo extends Application {
#Override
public void start(Stage stage) throws Exception {
VBox root = new VBox();
root.setSpacing(15);
root.setPadding(new Insets(25));
root.setAlignment(Pos.TOP_LEFT);
Scene sc = new Scene(root, 600, 600);
stage.setScene(sc);
stage.show();
final ObservableList<Person> items = FXCollections.observableArrayList();
for (int i = 1; i < 4; i++) {
items.add(new Person(i,"Name " + i, i + 30, "email" + i + "#test.com"));
}
final ComboBox<Person> comboBox = new ComboBox<>();
comboBox.setItems(items);
comboBox.setCellFactory(param -> new ListCell<Person>() {
#Override
protected void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setGraphic(buildLayout(item));
} else {
setGraphic(null);
}
}
});
comboBox.setButtonCell(new ListCell<Person>(){
#Override
protected void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setGraphic(buildLayout(item));
} else {
setGraphic(null);
}
}
});
comboBox.getSelectionModel().selectedItemProperty().addListener((obs,oldVal,selectedPerson)->{
System.out.println("Name : "+selectedPerson.getName());
// Do what you want..
});
root.getChildren().add(comboBox);
}
private HBox buildLayout(Person person) {
VBox layout = new VBox();
HBox.setHgrow(layout,Priority.ALWAYS);
layout.setStyle("-fx-border-width:1px;-fx-border-color:#444444;");
layout.setSpacing(5);
layout.setPadding(new Insets(2));
HBox topRow = new HBox();
topRow.setSpacing(5);
topRow.getChildren().addAll(getLabel("Name :","bold"),getLabel(person.getName(),"normal"), getLabel("Age :","bold"),getLabel(person.getAge()+"","normal"));
HBox bottomRow = new HBox();
bottomRow.setSpacing(5);
bottomRow.getChildren().addAll(getLabel("Email :","bold"),getLabel(person.getEmail(),"normal"));
layout.getChildren().addAll(topRow, bottomRow);
HBox pane = new HBox();
pane.setAlignment(Pos.CENTER_LEFT);
pane.setSpacing(5);
pane.setPadding(new Insets(2));
Label num = new Label(person.getId()+"");
num.setStyle("-fx-font-size:20px;-fx-font-weight:bold;-fx-text-fill:black;");
pane.getChildren().addAll(num,layout);
return pane;
}
private Label getLabel(String txt, String style){
Label lblName = new Label(txt);
lblName.setStyle("-fx-font-weight:"+style+";-fx-text-fill:black;");
return lblName;
}
public static void main(String[] args) {
Application.launch(args);
}
class Person {
IntegerProperty id = new SimpleIntegerProperty();
StringProperty name = new SimpleStringProperty();
IntegerProperty age = new SimpleIntegerProperty();
StringProperty email = new SimpleStringProperty();
public Person(int id,String name, int age, String email) {
setId(id);
setName(name);
setAge(age);
setEmail(email);
}
public int getId() {
return id.get();
}
public IntegerProperty idProperty() {
return id;
}
public void setId(int id) {
this.id.set(id);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public int getAge() {
return age.get();
}
public IntegerProperty ageProperty() {
return age;
}
public void setAge(int age) {
this.age.set(age);
}
public String getEmail() {
return email.get();
}
public StringProperty emailProperty() {
return email;
}
public void setEmail(String email) {
this.email.set(email);
}
}
}
Related
I've a JFXTreeTableView and i want to center the text of the data for each column.
there is one of my creating columns code :
JFXTreeTableColumn<TableData, String> DrinkColumn = new JFXTreeTableColumn<>("Drink");
DrinkColumn.setPrefWidth(100);
DrinkColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<TableData, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<TableData, String> param) {
return param.getValue().getValue().Drink;
}
}
);
I don't use JFoenix, but using a standard TreeTableView, the following external CSS will center the text in tree table cells:
.tree-table-cell {
-fx-alignment: center ;
}
Here's a SSCCE (the code above goes in style.css):
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
public class TreeTableViewTest extends Application {
#Override
public void start(Stage primaryStage) {
TreeTableView<Item> table = new TreeTableView<>();
TreeTableColumn<Item, String> col = new TreeTableColumn<>("Item");
col.setCellValueFactory(cellData -> cellData.getValue().getValue().nameProperty());
col.setPrefWidth(250);
table.getColumns().add(col);
TreeTableColumn<Item, Number> valueCol = new TreeTableColumn<>("Value");
valueCol.setCellValueFactory(cellData -> cellData.getValue().getValue().valueProperty());
valueCol.setPrefWidth(150);
table.getColumns().add(valueCol);
table.setRoot(createRandomTree(50));
Scene scene = new Scene(table);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
private TreeItem<Item> createRandomTree(int nItems) {
Random rng = new Random();
TreeItem<Item> root = new TreeItem<>(new Item("Item 1", rng.nextInt(1000)));
root.setExpanded(true);
List<TreeItem<Item>> items = new ArrayList<>();
items.add(root);
for (int i = 2 ; i <= nItems ; i++) {
TreeItem<Item> item = new TreeItem<>(new Item("Item "+i, rng.nextInt(1000)));
item.setExpanded(true);
items.get(rng.nextInt(items.size())).getChildren().add(item);
items.add(item);
}
return root ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}
If you want to center only specific columns, then use a cell factory on the column and set a CSS class or PseudoClass on the cell:
valueCol.setCellFactory(column -> {
TreeTableCell<Item, Number> cell = new TreeTableCell<Item, Number>() {
#Override
protected void updateItem(Number value, boolean empty) {
super.updateItem(value, empty);
if (empty) {
setText(null);
} else {
setText(value.toString());
}
}
};
cell.pseudoClassStateChanged(PseudoClass.getPseudoClass("centered"), true);
return cell ;
});
and modify the CSS accordingly:
.tree-table-cell:centered {
-fx-alignment: center ;
}
The latter version gives
I have Created a custom control call it ComboBoxTablePopup extending Comboboxbase class. I have used a tableview as a popup content. Everything works fine,
update value, show popup, hide popup. After switching the focus from ComboBoxTablePopup to another control like a TextField or Spinner, it updates it self with null value.
So, I don't know what makes this happens. So here is my implementation on self executable class.
import com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior;
import com.sun.javafx.scene.control.behavior.KeyBinding;
import com.sun.javafx.scene.control.skin.ComboBoxListViewSkin;
import com.sun.javafx.scene.control.skin.ComboBoxPopupControl;
import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.WeakInvalidationListener;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.WeakListChangeListener;
import javafx.event.ActionEvent;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class TestComboboxTablePopup extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
ComboBoxTablePopupControl<dataModel> comboBoxTablePopup = new ComboBoxTablePopupControl<>();
TableColumn<dataModel, Integer> tcId = new TableColumn<>("Id");
TableColumn<dataModel, String> tcName = new TableColumn<>("Name");
tcId.setCellValueFactory(new PropertyValueFactory<dataModel, Integer>("id"));
tcName.setCellValueFactory(new PropertyValueFactory<dataModel, String>("name"));
comboBoxTablePopup.setColumns(FXCollections.observableArrayList(tcId, tcName));
comboBoxTablePopup.setItems(FXCollections.observableArrayList(
new dataModel(1, "Data Model object 1"),
new dataModel(2, "Data Model object 2"),
new dataModel(3, "Data Model object 3")
));
VBox vBox = new VBox(comboBoxTablePopup);
Scene scene = new Scene(vBox);
primaryStage.setScene(scene);
primaryStage.setWidth(400);
primaryStage.setHeight(300);
primaryStage.show();
}
public class dataModel {
private int id;
private String name;
public dataModel(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
private static <S> StringConverter<S> defaultStringConverter() {
return new StringConverter<S>() {
#Override
public String toString(S t) {
return t == null ? "abood fait" : t.toString();
}
#Override
public S fromString(String string) {
return null;
}
};
}
private class ComboBoxTablePopupControl<S> extends ComboBoxBase {
/***************************************************************************
* *
* Static properties and methods *
* *
**************************************************************************/
private static final String DEFAULT_STYLE_CLASS = "combobox-table-popup";
private ObjectProperty<ObservableList<S>> items = new SimpleObjectProperty<ObservableList<S>>(this, "items");
public final void setItems(ObservableList<S> value) {
itemsProperty().set(value);
}
public final ObservableList<S> getItems() {
return items.get();
}
public ObjectProperty<ObservableList<S>> itemsProperty() {
return items;
}
public ObjectProperty<StringConverter<S>> converterProperty() {
return converter;
}
private ObjectProperty<StringConverter<S>> converter =
new SimpleObjectProperty<StringConverter<S>>(this, "converter", defaultStringConverter());
public final void setConverter(StringConverter<S> value) {
converterProperty().set(value);
}
public final StringConverter<S> getConverter() {
return converterProperty().get();
}
// Editor
private ReadOnlyObjectWrapper<TextField> editor;
public final TextField getEditor() {
return editorProperty().get();
}
public final ReadOnlyObjectProperty<TextField> editorProperty() {
if (editor == null) {
editor = new ReadOnlyObjectWrapper<TextField>(this, "editor");
editor.set(new ComboBoxListViewSkin.FakeFocusTextField());
}
return editor.getReadOnlyProperty();
}
private
ObservableList<TableColumn<S, ?>> columns = FXCollections.observableArrayList();
public ObservableList<TableColumn<S, ?>> getColumns() {
return columns;
}
public void setColumns(ObservableList<TableColumn<S, ?>> columns) {
this.columns = columns;
}
/***************************************************************************
* *
* Constructors *
* *
**************************************************************************/
/**
* Creates a default ComboboxTablePopup instance with an empty
* {#link #itemsProperty() items} list and default
* {#link #selectionModelProperty() selection model}.
*/
public ComboBoxTablePopupControl() {
this(FXCollections.<S>emptyObservableList());
}
/**
* Creates a default ComboboxTablePopup instance with the provided items list and
* a default { selection model}.
*/
public ComboBoxTablePopupControl(ObservableList<S> items) {
setItems(items);
getStyleClass().add(DEFAULT_STYLE_CLASS);
setEditable(true);
valueProperty().addListener((observable, oldValue, newValue) -> {
System.out.println(newValue);
});
}
public ComboBoxTablePopupControl(ObservableList<S> items, ObservableList<TableColumn<S, ?>> columns) {
this(items);
this.columns = columns;
}
#Override
protected Skin<?> createDefaultSkin() {
return new ComboBoxTablePopupControlSkin<>(this);
}
}
public class ComboBoxTablePopupControlSkin<S> extends ComboBoxPopupControl {
private ComboBoxTablePopupControl comboBoxTablePopup;
private ObservableList<S> comboboxTablePopupItems;
private TableView<S> tableViewPopupContent;
private ObservableList<S> tableViewPopupItems;
private Predicate<S> predicate;
private final InvalidationListener itemsObserver;
private final ListChangeListener<S> tableViewItemsListener = new ListChangeListener<S>() {
#Override
public void onChanged(ListChangeListener.Change<? extends S> c) {
getSkinnable().requestLayout();
}
};
private final WeakListChangeListener<S> weakListViewItemsListener =
new WeakListChangeListener<S>(tableViewItemsListener);
public ComboBoxTablePopupControlSkin(ComboBoxTablePopupControl comboBoxTablePopup) {
super(comboBoxTablePopup, new ComboBoxBaseBehavior(comboBoxTablePopup, null));
this.comboBoxTablePopup = comboBoxTablePopup;
updateComboBoxTablePopupItems();
itemsObserver = observable -> {
updateComboBoxTablePopupItems();
updateTableViewItems();
};
this.comboBoxTablePopup.itemsProperty().addListener(new WeakInvalidationListener(itemsObserver));
tableViewPopupContent = createTableView();
tableViewPopupContent.setManaged(false);
getChildren().add(tableViewPopupContent);
updateTableViewItems();
registerChangeListener(comboBoxTablePopup.converterProperty(), "CONVERTER");
registerChangeListener(comboBoxTablePopup.itemsProperty(), "ITEMS");
registerChangeListener(comboBoxTablePopup.valueProperty(), "VALUE");
registerChangeListener(comboBoxTablePopup.editorProperty(), "EDITABLE");
}
private void updateTableViewItems() {
this.tableViewPopupItems = comboBoxTablePopup.getItems();
this.tableViewPopupContent.setItems(this.tableViewPopupItems);
if (tableViewPopupItems != null) {
tableViewPopupItems.removeListener(weakListViewItemsListener);
}
this.tableViewPopupItems = comboboxTablePopupItems;
tableViewPopupContent.setItems(tableViewPopupItems);
if (tableViewPopupItems != null) {
tableViewPopupItems.addListener(weakListViewItemsListener);
}
getSkinnable().requestLayout();
}
public void updateComboBoxTablePopupItems() {
comboboxTablePopupItems = comboBoxTablePopup.getItems();
comboboxTablePopupItems = comboboxTablePopupItems == null ? FXCollections.<S>emptyObservableList() : comboboxTablePopupItems;
}
private TableView<S> createTableView() {
final TableView<S> tableView = new TableView<>();
tableView.setId("table-view");
tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
tableView.setFocusTraversable(false);
for (TableColumn tblColumn : tableColumns()) {
tableView.getColumns().add(tblColumn);
}
tableView.getSelectionModel().selectedItemProperty().addListener(o -> {
S selectedItem = tableView.getSelectionModel().getSelectedItem();
comboBoxTablePopup.setValue(selectedItem);
});
tableView.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.ENTER ||
e.getCode() == KeyCode.SPACE) {
S selectedItem = tableView.getSelectionModel().getSelectedItem();
comboBoxTablePopup.setValue(selectedItem);
comboBoxTablePopup.hide();
}
});
return tableView;
}
private ObservableList<TableColumn> tableColumns() {
return ((ComboBoxTablePopupControl) getSkinnable()).getColumns();
}
#Override
protected Node getPopupContent() {
return this.tableViewPopupContent;
}
#Override
protected TextField getEditor() {
return ((ComboBoxTablePopupControl) getSkinnable()).getEditor();
}
#Override
protected StringConverter<S> getConverter() {
return ((ComboBoxTablePopupControl) getSkinnable()).getConverter();
}
#Override
public Node getDisplayNode() {
Node displayNode;
displayNode = getEditableInputNode();
updateDisplayNode();
return displayNode;
}
#Override
protected void handleControlPropertyChanged(String p) {
if ("VALUE".equals(p)) {
updateDisplayNode();
System.out.println(comboBoxTablePopup.getValue());
comboBoxTablePopup.fireEvent(new ActionEvent());
} else if ("CONVERTER".equals(p)) {
updateDisplayNode();
System.out.println("Conveter peroptery");
} else if ("ITEMS".equals(p)) {
updateComboBoxTablePopupItems();
updateTableViewItems();
} else if ("EDITOR".equals(p)) {
getEditableInputNode();
} else
super.handleControlPropertyChanged(p);
}
}
}
If someone still has trouble with this issue, here is a workaround for a choicebox. I assume you already have a table with columns and an EventHandler. This example is not tested with any editable (isEditable(true)) object.
First set a custom Factory and an EventHandler for setOnEditStart
yourColumn.setCellFactory(value -> new CustomEditFactory(yourObsList));
In your CustomEditFactory class you have to extend TreeTableCell<KnotenObs, String> and #Override four methods
startEdit()
#Override
public void startEdit() {
super.startEdit();
choiceBox.getSelectionModel().select(getItem());
oldValue = choiceBox.getSelectionModel().getSelectedItem();
setGraphic(choiceBox);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
commitEdit()
#Override
public void commitEdit(String newValue) {
if(newValue == null) {
super.commitEdit(oldValue);
} else {
super.commitEdit(newValue);
}
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
cancelEdit()
#Override
public void cancelEdit() {
super.cancelEdit();
if(getItem() == null) {
setText(oldValue);
} else {
setText(getItem());
}
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
updateItem()
#Override
public void updateItem(String item, boolean empty) {
if(item == null) {
super.updateItem(oldValue, empty);
setText(oldValue);
} else {
super.updateItem(item, empty);
setText(item);
}
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
I'm stuck with trying to format Long values in a TableView with JavaFX.
I have following class to store the rows that I want to display on the table:
import java.text.DecimalFormat;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleStringProperty;
public class DataByCurrencyPairRow {
private DecimalFormat integerFormat = new DecimalFormat("#,###");
private SimpleStringProperty currencyPair = new SimpleStringProperty("");
private SimpleDoubleProperty shareOfTotalVolume = new SimpleDoubleProperty(0);
private SimpleLongProperty totalVolume = new SimpleLongProperty(0);
private SimpleLongProperty currencyBought = new SimpleLongProperty(0);
private SimpleLongProperty currencySold = new SimpleLongProperty(0);
private SimpleLongProperty monthlyAverage = new SimpleLongProperty(0);
public DataByCurrencyPairRow() {
currencyPair.set("");
shareOfTotalVolume.set(0);
totalVolume.set(0);
currencyBought.set(0);
currencySold.set(0);
monthlyAverage.set(0);
}
public String getCurrencyPair() {
return currencyPair.getValue();
}
public void setCurrencyPair(String currencyPair) {
this.currencyPair.setValue(currencyPair);
}
public Long getMonthlyAverage() {
return monthlyAverage.getValue();
}
public void setMonthlyAverage(Long monthlyAverage) {
this.monthlyAverage.setValue(monthlyAverage);
}
public Long getCurrencySold() {
return currencySold.getValue();
}
public void setCurrencySold(Long currencySold) {
this.currencySold.setValue(currencySold);
}
public Long getCurrencyBought() {
return currencyBought.getValue();
}
public void setCurrencyBought(Long currencyBought) {
this.currencyBought.setValue(currencyBought);
}
public Long getTotalVolume() {
return totalVolume.getValue();
}
public void setTotalVolume(Long totalVolume) {
this.totalVolume.setValue(totalVolume);
}
public Double getShareOfTotalVolume() {
return shareOfTotalVolume.getValue();
}
public void setShareOfTotalVolume(Double shareOfTotalVolume) {
this.shareOfTotalVolume.setValue(shareOfTotalVolume);
}
}
Then I have the controller with initialize method where I have been trying to override the updateItem method to get the table to show comma as a thousand separator:
public class MainController {
private static final String DEFAULT_TIME_HORIZON = new String("0");
private final NumberFormat integerFormat = new DecimalFormat("#,###");
#FXML
TableView<DataByCurrencyPairRow> tableTransactionsByCurrencyPair;
#FXML
TableColumn<DataByCurrencyPairRow, Long> columnTotal;
#FXML
void initialize() {
columnTotal.setCellFactory(
new Callback<TableColumn<DataByCurrencyPairRow, SimpleLongProperty>, TableCell<DataByCurrencyPairRow, SimpleLongProperty>>() {
#Override
public TableCell<DataByCurrencyPairRow, SimpleLongProperty> call(TableColumn<DataByCurrencyPairRow, SimpleLongProperty> param
) {
return new TableCell<DataByCurrencyPairRow, SimpleLongProperty>() {
#Override
protected void updateItem(SimpleLongProperty item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText("0");
setStyle("");
} else {
setText(integerFormat.format(item.longValue()));
}
}
};
}
}
);
And this is the method that populates the TableView:
public void updateByCurrencyPairTable() {
System.out.println("#MainController: Updating data in table view Markets volumes by currency pair");
ObservableList<DataByCurrencyPairRow> data = tableTransactionsByCurrencyPair.getItems();
data.clear();
// Add row items to the table view Markets volume by currency
for (DataByCurrencyPairRow row : customer.getDataByCurrencyPairR12m().getDataByCurrencyPair()) {
data.add(row);
}
}
Please help me by showing how to do this!! I also tried to override the updateItem method as Long instead of SimpleLongProperty and my IDE accepted the code but still the number is not formatted in the table.
Thank you guys in advance!!!
LongProperty implements ObservableValue<Number>, not ObservableValue<Long> (or ObservableValue<SimpleLongProperty>). So your table columns need to be of type TableColumn<DataByCurrencyPair, Number> and your cell factory needs to match those types accordingly.
Here's a simple example of a formatted column with Longs:
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Random;
import javafx.application.Application;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class TableWithFormattedLong extends Application {
private final NumberFormat integerFormat = new DecimalFormat("#,###");
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
TableColumn<Item, String> itemColumn = new TableColumn<>("Item");
itemColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
TableColumn<Item, Number> valueColumn = new TableColumn<>("Value");
valueColumn.setCellValueFactory(cellData -> cellData.getValue().valueProperty());
valueColumn.setCellFactory(tc -> new TableCell<Item, Number>() {
#Override
protected void updateItem(Number value, boolean empty) {
super.updateItem(value, empty);
if (value == null || empty) {
setText("");
} else {
setText(integerFormat.format(value));
}
}
});
table.getColumns().add(itemColumn);
table.getColumns().add(valueColumn);
Random rng = new Random();
for (int i = 1 ; i <= 20 ; i++) {
table.getItems().add(new Item("Item "+i, rng.nextLong()));
}
primaryStage.setScene(new Scene(table, 600, 600));
primaryStage.show();
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final LongProperty value = new SimpleLongProperty();
public Item(String name, long value) {
setName(name);
setValue(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final LongProperty valueProperty() {
return this.value;
}
public final long getValue() {
return this.valueProperty().get();
}
public final void setValue(final long value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}
There is no need to set the Cellfactory, just set the CellValueFactory.
TableColumn<DataByCurrencyPairRow, String> columnTotal;
columnTotal.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<DataByCurrencyPairRow,String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(CellDataFeatures<DataByCurrencyPairRow, String> param) {
DataByCurrencyPairRow value = param.getValue();
return new ReadOnlyStringWrapper(NumberFormat.getNumberInstance(Locale.US).format(123123)); //replace the number with the calculated total
}
});
I have a Javafx TableView where I can add new Rows by double Click on an empty Row at the End of my "filled" / Textfield filled Rows.
My Problem is,if i add some Rows ,Java don't give me more of the empty Rows I could double click to add some Rows.
Edit:removed some unnessary log
To see what i mean, here is the Code:
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextArea;
import javafx.util.Callback;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
interface inside_table
{
public void Select_Row_by_Col(int index);
}
public class Supermain extends Application {
ObservableList<myTextRow> data;
#Override
public void start(Stage primaryStage) {
ArrayList myindizes=new ArrayList();
final TableView<myTextRow> table = new TableView<>();
table.setEditable(true);
table.setStyle("-fx-text-wrap: true;");
//Table columns
TableColumn<myTextRow, String> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(new PropertyValueFactory<>("ID"));
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(new PropertyValueFactory<>("text"));
clmtext.setCellFactory(new TextFieldCellFactory("text"));
TableColumn<myTextRow, String> clmtext2 = new TableColumn<>("Text2");
clmtext2.setMinWidth(160);
clmtext2.setCellValueFactory(new PropertyValueFactory<>("text2"));
clmtext2.setCellFactory(new TextFieldCellFactory("text2"));
//Add data
data = FXCollections.observableArrayList(
new myTextRow(5, "Lorem","bla"),
new myTextRow(2, "Ipsum","bla")
);
table.getColumns().addAll(clmID, clmtext,clmtext2);
table.setItems(data);
table.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
if (mouseEvent.getClickCount() == 2 && mouseEvent.getY()>24) {
data.add(new myTextRow(td_get_biggest_ID() + 1,"",""));
table.selectionModelProperty().get().select(data.size()-1);
}
}
}
});
HBox hBox = new HBox();
hBox.setSpacing(5.0);
hBox.setPadding(new Insets(5, 5, 5, 5));
Button btn = new Button();
btn.setText("Get Data");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
for (myTextRow data1 : data) {
System.out.println("data:" + data1.getText2());
}
}
});
hBox.getChildren().add(btn);
BorderPane pane = new BorderPane();
pane.setTop(hBox);
pane.setCenter(table);
primaryStage.setScene(new Scene(pane, 640, 480));
primaryStage.show();
class I_table implements inside_table{
#Override
public void Select_Row_by_Col(int index) {
table.getSelectionModel().select(index);
}
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public static class TextFieldCellFactory
implements Callback<TableColumn<myTextRow, String>, TableCell<myTextRow, String>> {
private String ColumnName;
public TextFieldCellFactory(String ColumnName){
this.ColumnName=ColumnName;
}
#Override
public TableCell<myTextRow, String> call(TableColumn<myTextRow, String> param) {
TextFieldCell textFieldCell = new TextFieldCell(this.ColumnName);
return textFieldCell;
}
public static class TextFieldCell extends TableCell<myTextRow, String> {
private TextArea textField;
private StringProperty boundToCurrently = null;
private String last_text;
private String ColumnName;
public TextFieldCell(String cname) {
textField = new TextArea();
textField.setWrapText(true);
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
last_text="";
this.ColumnName=cname;
this.setGraphic(textField);
textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if(this.ColumnName=="text2"){
if(isNowFocused){last_text=textField.getText();System.out.println("NOW focus "+last_text);}
if (! isNowFocused && ! isValid(textField.getText())) {
textField.setText(last_text);
//textField.setText("00:00:00:00");
textField.selectAll();
System.out.println("blur");
}
}
});
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
// myindizes.add(getIndex());
// Retrieve the actual String Property that should be bound to the TextField
// If the TextField is currently bound to a different StringProperty
// Unbind the old property and rebind to the new one
ObservableValue<String> ov = getTableColumn().getCellObservableValue(getIndex());
SimpleStringProperty sp = (SimpleStringProperty) ov;
if (this.boundToCurrently == null) {
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(sp);
} else if (this.boundToCurrently != sp) {
this.textField.textProperty().unbindBidirectional(this.boundToCurrently);
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(this.boundToCurrently);
}
double height = real_lines_height(textField.getText(), this.getWidth(), 30, 22);
textField.setPrefHeight(height);
textField.setMaxHeight(height);
textField.setMaxHeight(Double.MAX_VALUE);
// if height bigger than the biggest height in the row
//-> change all heights of the row(textfields ()typeof textarea) to this height
// else leave the height as it is
//System.out.println("item=" + item + " ObservableValue<String>=" + ov.getValue());
//this.textField.setText(item); // No longer need this!!!
} else {
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}//update
private boolean isValid(String s){
String splitArray[] = s.split(":");
if (splitArray.length != 4) {
System.out.println("false");
return false;
}
for (int i = 0; i < splitArray.length; i++) {
if (splitArray[i].length() != 2) {
System.out.println("false");
return false;
}
if (!splitArray[i].substring(0, 1).matches("[0-9]")) {
System.out.println("no number1");
return false;
}
if (!splitArray[i].substring(1, 2).matches("[0-9]")) {
System.out.println("no number2");
return false;
}
if (i < 3) {
int itest = Integer.parseInt(splitArray[i]);
if (itest > 59) {
System.out.println(itest + " ist zu groß!");
return false;
}
} else {
int itest2 = Integer.parseInt(splitArray[i]);
if (itest2 > Math.floor(25)) {
System.out.println(itest2 + " ist zu groß!");
return false;
}
//framerate!!!!!
}
System.out.println("splits: " + splitArray[i]);
//if( el.charAt(0).)
}
return true;
}
}
}
public class myTextRow {
private final SimpleIntegerProperty ID;
private final SimpleStringProperty text;
private final SimpleStringProperty text2;
public myTextRow(int ID, String text,String text2) {
this.ID = new SimpleIntegerProperty(ID);
this.text = new SimpleStringProperty(text);
this.text2 = new SimpleStringProperty(text2);
}
//setter
public void setID(int id) {
this.ID.set(id);
}
public void setText(String text) {
this.text.set(text);
}
public void setText2(String text) {
this.text2.set(text);
}
//getter
public int getID() {
return ID.get();
}
public String getText() {
return text.get();
}
public String getText2() {
return text2.get();
}
//properties
public StringProperty textProperty() {
return text;
}
public StringProperty text2Property() {
return text2;
}
public IntegerProperty IDProperty() {
return ID;
}
}
private static double real_lines_height(String s, double width, double heightCorrector, double widthCorrector) {
HBox h = new HBox();
Label l = new Label("Text");
h.getChildren().add(l);
Scene sc = new Scene(h);
l.applyCss();
double line_height = l.prefHeight(-1);
int new_lines = s.replaceAll("[^\r\n|\r|\n]", "").length();
// System.out.println("new lines= "+new_lines);
String[] lines = s.split("\r\n|\r|\n");
// System.out.println("line count func= "+ lines.length);
int count = 0;
//double rest=0;
for (int i = 0; i < lines.length; i++) {
double text_width = get_text_width(lines[i]);
double plus_lines = Math.ceil(text_width / (width - widthCorrector));
if (plus_lines > 1) {
count += plus_lines;
//rest+= (text_width / (width-widthCorrector)) - plus_lines;
} else {
count += 1;
}
}
//count+=(int) Math.ceil(rest);
count += new_lines - lines.length;
return count * line_height + heightCorrector;
}
private static double get_text_width(String s) {
HBox h = new HBox();
Label l = new Label(s);
l.setWrapText(false);
h.getChildren().add(l);
Scene sc = new Scene(h);
l.applyCss();
// System.out.println("FXMLDocumentController.get_text_width(): "+l.prefWidth(-1));
return l.prefWidth(-1);
}
public int td_get_biggest_ID() {
int biggest = 0;
for (int i = 0; i < data.size(); i++) {
if (((myTextRow) data.get(i)).getID() > biggest) {
biggest = ((myTextRow) data.get(i)).getID();
}
}
return biggest;
}
}
Just click anywhere else on the TableView but make sure it's at least 24 pixels from the top; This will work since you've added the event handler is added to the TableView...
If you only want to use the last row, then use a custom rowFactory and handle the events there.
Add a placeholder item to the TableView items that marks the row that is used for adding new elements (for some reason the selection model doesn't like null):
final myTextRow addPlaceHolder = new myTextRow(Integer.MIN_VALUE, null, null);
...
//Add data
data = FXCollections.observableArrayList(
new myTextRow(5, "Lorem", "bla"),
new myTextRow(2, "Ipsum", "bla"),
addPlaceHolder
);
make sure your TextFieldCells treat null values as empty rows:
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty && item != null) {
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
...
make sure the first column does not display anything for the placeholder
//Table columns
TableColumn<myTextRow, Number> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(cdf -> {
myTextRow item = cdf.getValue();
return item == addPlaceHolder ? Bindings.createObjectBinding(() -> null) : item.IDProperty();
});
and use the following rowFactory to handle adding the items (you don't need the updateItem part unless you need to add a style class to the TableRow; you need not extend TableRow in this case)
table.setRowFactory(tv -> new TableRow<myTextRow>() {
{
setOnMouseClicked(mouseEvent -> {
if (mouseEvent.getButton() == MouseButton.PRIMARY
&& mouseEvent.getClickCount() == 2
&& !isEmpty()
&& getItem() == addPlaceHolder) {
data.add(data.size() - 1, new myTextRow(td_get_biggest_ID() + 1, "", ""));
table.selectionModelProperty().get().select(data.size() - 1);
mouseEvent.consume();
}
});
}
#Override
protected void updateItem(myTextRow item, boolean empty) {
super.updateItem(item, empty);
// add style class for row containing addPlaceHolder
List<String> classes = getStyleClass();
final String clazz = "add-row";
if (item == addPlaceHolder) {
if (!classes.contains(clazz)) {
classes.add(clazz);
}
} else {
classes.remove(clazz);
}
}
});
I'm trying to insert data into a Javafx TableView, actually I did it, but it fills the row with the following String:
IntegerProperty [value: 72] and etc...
How can I show only the value fill in my rows??
My TableView code:
#FXML TableView tableView = new TableView<MetaDadosInfo>();
#FXML javafx.scene.control.TableColumn instituicaoCol;
#FXML javafx.scene.control.TableColumn anoCol;
#FXML javafx.scene.control.TableColumn tamanhoCol;
#FXML javafx.scene.control.TableColumn tipoCol;
#FXML javafx.scene.control.TableColumn nomeCol;
final ObservableList<MetaDadosInfo> data = FXCollections.observableArrayList(
new MetaDadosInfo(codigoInstituicao, ano, size, type, name));
instituicaoCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("codigoInstituicao"));
anoCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("ano"));
tamanhoCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("size"));
tipoCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("type"));
nomeCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("name"));
tableView.setItems(data);
MetaDadosInfo class:
public class MetaDadosInfo {
private SimpleIntegerProperty codigoInstituicao;
private SimpleIntegerProperty ano;
private SimpleLongProperty size;
private SimpleStringProperty type;
private SimpleStringProperty name;
public MetaDadosInfo(int codigoInstituicao, int ano, long size, String type, String name) {
this.codigoInstituicao = new SimpleIntegerProperty (codigoInstituicao);
this.ano = new SimpleIntegerProperty (ano);
this.size = new SimpleLongProperty (size);
this.type = new SimpleStringProperty (type);
this.name = new SimpleStringProperty (name);
}
public SimpleIntegerProperty getCodigoInstituicao() {
return codigoInstituicao;
}
public void setCodigoInstituicao(SimpleIntegerProperty codigoInstituicao) {
this.codigoInstituicao = codigoInstituicao;
}
public SimpleIntegerProperty getAno() {
return ano;
}
public void setAno(SimpleIntegerProperty ano) {
this.ano = ano;
}
public SimpleLongProperty getSize() {
return size;
}
public void setSize(SimpleLongProperty size) {
this.size = size;
}
public SimpleStringProperty getType() {
return type;
}
public void setType(SimpleStringProperty type) {
this.type = type;
}
public SimpleStringProperty getName() {
return name;
}
public void setName(SimpleStringProperty name) {
this.name = name;
}
}
The error was in getters and setters from my MetaDadosInfo class, the right way is:
public class MetaDadosInfo {
private SimpleIntegerProperty codigoInstituicao;
private SimpleIntegerProperty ano;
private SimpleLongProperty size;
private SimpleStringProperty type;
private SimpleStringProperty name;
public MetaDadosInfo(int codigoInstituicao, int ano, long size, String type, String name) {
this.codigoInstituicao = new SimpleIntegerProperty (codigoInstituicao);
this.ano = new SimpleIntegerProperty (ano);
this.size = new SimpleLongProperty (size);
this.type = new SimpleStringProperty (type);
this.name = new SimpleStringProperty (name);
}
public int getCodigoInstituicao() {
return codigoInstituicao.get();
}
public void setCodigoInstituicao(int codigoInstituicao) {
this.codigoInstituicao.set(codigoInstituicao);
}
public int getAno() {
return ano.get();
}
public void setAno(int ano) {
this.ano.set(ano);
}
public Long getSize() {
return size.get();
}
public void setSize(long size) {
this.size.set(size);
}
public String getType() {
return type.get();
}
public void setType(String type) {
this.type.set(type);
}
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
}
After wasting my day i finally able to find the solution in very easy way
package test;
import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
public class Test extends Application {
public static final String Column1MapKey = "A";
public static final String Column2MapKey = "B";
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Table View Sample");
stage.setWidth(300);
stage.setHeight(500);
final Label label = new Label("Student IDs");
label.setFont(new Font("Arial", 20));
TableColumn<Map, String> firstDataColumn = new TableColumn<>("Class A");
TableColumn<Map, String> secondDataColumn = new TableColumn<>("Class B");
firstDataColumn.setCellValueFactory(new MapValueFactory(Column1MapKey));
firstDataColumn.setMinWidth(130);
secondDataColumn.setCellValueFactory(new MapValueFactory(Column2MapKey));
secondDataColumn.setMinWidth(130);
TableView table_view = new TableView<>();
table_view.setItems(generateDataInMap());
table_view.setEditable(true);
table_view.getSelectionModel().setCellSelectionEnabled(true);
table_view.getColumns().setAll(firstDataColumn, secondDataColumn);
// Callback<TableColumn<Map, String>, TableCell<Map, String>> cellFactoryForMap = new Callback<TableColumn<Map, String>, TableCell<Map, String>>() {
// #Override
// public TableCell call(TableColumn p) {
// return new TextFieldTableCell(new StringConverter() {
// #Override
// public String toString(Object t) {
// return t.toString();
// }
//
// #Override
// public Object fromString(String string) {
// return string;
// }
// });
// }
// };
// firstDataColumn.setCellFactory(cellFactoryForMap);
// secondDataColumn.setCellFactory(cellFactoryForMap);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table_view);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
private ObservableList<Map> generateDataInMap() {
int max = 10;
ObservableList<Map> allData = FXCollections.observableArrayList();
for (int i = 1; i < max; i++) {
Map<String, String> dataRow = new HashMap<>();
String value1 = "A" + i;
String value2 = "B" + i;
dataRow.put(Column1MapKey, value1);
dataRow.put(Column2MapKey, value2);
allData.add(dataRow);
}
return allData;
}
}
just try to change and use it in your way it can also be used directly in resultset
Happy Coding, Happy Innovation
This doesn't work with PropertyValueFactory because you have not declared your JavaFX beans with the expected naming conventions for the properties you have defined in your data model.
Refer to this post for how to use PropertyValueFactory correctly: How to use the PropertyValueFactory correctly?