Javafx tableview edit method not call cellfactory - javafx

I try set edit cell on run program. Set table editable, cellfactory and other.
I can edit the cell, when clicked with the mouse. But the call edit() method of TableView does not create Textfield.
What have I missed?
public class Main extends Application {
TableView <TestClass> tableView;
TableColumn <TestClass, String> stringColumn;
TableColumn <TestClass, String> editColumn;
ObservableList<TestClass> items;
#Override
public void start(Stage primaryStage) throws Exception{
makeTestData();
tableView = new TableView();
tableView.setEditable(true);
stringColumn = new TableColumn<>("Col1");
editColumn = new TableColumn<>("Col2");
tableView.getColumns().addAll(stringColumn, editColumn);
stringColumn.setCellValueFactory(cell -> cell.getValue().stringProperty());
editColumn.setCellValueFactory(cell -> cell.getValue().editProperty());
editColumn.setCellFactory(TextFieldTableCell.<TestClass>forTableColumn());
tableView.setItems(items);
tableView.getSelectionModel().select(1);
tableView.getSelectionModel().focus(1);
tableView.edit(1, editColumn); // !!! not create textfield ???
BorderPane pane = new BorderPane();
pane.setCenter(tableView);
primaryStage.setScene(new Scene(pane));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public void makeTestData(){
items = FXCollections.observableArrayList(
new TestClass("str1", "edit1"),
new TestClass("str2", "edit2"),
new TestClass("str3", "edit3")
);
}
public class TestClass{
StringProperty string = new SimpleStringProperty();
StringProperty edit = new SimpleStringProperty();
public TestClass() {}
public TestClass(String string, String edit) {
this.string = new SimpleStringProperty(string);
this.edit = new SimpleStringProperty(edit);
}
public String getString() { return string.get();}
public StringProperty stringProperty() { return string; }
public void setString(String string) { this.string.set(string);}
public String getEdit() { return edit.get();}
public StringProperty editProperty() { return edit;}
public void setEdit(String edit) { this.edit.set(edit);}
}
}

yes im also getting this problem. the way i solved it is by putting the edit method call inside another fx thread.
Platform.runLater(() -> {
tableView.edit(row, editColumn);
});

Related

JavaFX tableView not showing data even though the data is being populated properly

I'm Actually new with JavaFX and been facing an issue to view the data on the table.
What I'm trying to do is to create a new stage on a Mouse Click Event of an Imageview where the Fields will be provided to the user to enter the data to the table on the parent node.
This is the function which is called on the mouse click event that creates a child node(stage) :
private void addQualification(MouseEvent event) {
System.out.println("Add Qualification Method");
final Stage dialog = new Stage();
dialog.setTitle("Add a Qualification");
dialog.initModality(Modality.WINDOW_MODAL);
dialog.initStyle(StageStyle.UTILITY);
// create a grid for the data entry.
GridPane grid = new GridPane();
AnchorPane anchorPane = new AnchorPane(grid);
ObservableList<String> QualChoiceList = FXCollections.observableArrayList("MBBS/MSC ", "MD/MS/DNB/PhD", "DM/M Ch.");
final ChoiceBox<String> QualChoice = new ChoiceBox<String>();
QualChoice.setValue("Select a Qualification");
QualChoice.setItems(QualChoiceList);
final TextField College = new TextField();
final TextField University = new TextField();
final TextField PassingYear = new TextField();
final TextField RegNo = new TextField();
final TextField StateName = new TextField();
grid.addRow(0, new Label("Qualification"), QualChoice);
grid.addRow(1, new Label("College"), College);
grid.addRow(2, new Label("University"), University);
grid.addRow(3, new Label("Year of Passing"), PassingYear);
grid.addRow(4, new Label("Registration No."), RegNo);
grid.addRow(5, new Label("Name of State"), StateName);
grid.setHgap(10);
grid.setVgap(10);
GridPane.setHgrow(QualChoice, Priority.ALWAYS);
GridPane.setHgrow(College, Priority.ALWAYS);
GridPane.setHgrow(University, Priority.ALWAYS);
GridPane.setHgrow(PassingYear, Priority.ALWAYS);
GridPane.setHgrow(RegNo, Priority.ALWAYS);
GridPane.setHgrow(StateName, Priority.ALWAYS);
// create action buttons for the dialog.
Button ok = new Button("Add");
Button cancel = new Button("Cancel");
ok.setDefaultButton(true);
cancel.setCancelButton(true);
anchorPane.getChildren().add(ok);
anchorPane.getChildren().add(cancel);
AnchorPane.setTopAnchor(grid, 20.0);
AnchorPane.setLeftAnchor(grid, 20.0);
AnchorPane.setRightAnchor(grid, 20.0);
AnchorPane.setBottomAnchor(grid, 80.0);
AnchorPane.setTopAnchor(ok, 240.0);
AnchorPane.setLeftAnchor(ok, 100.0);
AnchorPane.setRightAnchor(ok, 214.0);
AnchorPane.setBottomAnchor(ok, 30.0);
AnchorPane.setTopAnchor(cancel, 240.0);
AnchorPane.setLeftAnchor(cancel, 230.0);
AnchorPane.setRightAnchor(cancel, 95.0);
AnchorPane.setBottomAnchor(cancel, 30.0);
dialog.setScene(new Scene(anchorPane, 400, 310));
dialog.show();
// only enable the ok button when there has been some text entered.
ok.disableProperty().bind(College.textProperty().isEqualTo("").or(University.textProperty().isEqualTo("")).or(PassingYear.textProperty().isEqualTo("")).or(RegNo.textProperty().isEqualTo("")).or(StateName.textProperty().isEqualTo("")));
// add action handlers for the dialog buttons.
ok.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
int nextIndex = QualTable.getSelectionModel().getSelectedIndex() + 1;
QualTable.getItems().add(nextIndex, new Qualification(QualChoice.getValue(), College.getText(), University.getText(), PassingYear.getText(), RegNo.getText(), StateName.getText()));
QualTable.getSelectionModel().select(nextIndex);
dialog.close();
}
});
cancel.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
dialog.close();
}
});
This is the Qualification Class that I have used to inout the values to the QualTable using the add Method:
public static class Qualification {
private StringProperty Qual;
private StringProperty College;
private StringProperty University;
private StringProperty PassingYear;
private StringProperty RegNo;
private StringProperty StateName;
public Qualification(String Qual, String College, String University, String PassingYear, String RegNo, String StateName) {
setQual(Qual);
setCollege(College);
setUniversity(University);
setPassingYear(PassingYear);
setRegNo(RegNo);
setStateName(StateName);
}
public String getQual() {
return QualProperty().get();
}
public String getCollege() {
return CollegeProperty().get();
}
public String getUniversity() {
return UniversityProperty().get();
}
public String getPassingYear() {
return PassingYearProperty().get();
}
public String getRegNo() {
return RegNoProperty().get();
}
public String getStateName() {
return StateNameProperty().get();
}
public final void setQual(String value) {
QualProperty().set(value);
}
public final void setCollege(String Coll) {
CollegeProperty().set(Coll);
}
public final void setUniversity(String Univ) {
UniversityProperty().set(Univ);
}
public final void setPassingYear(String PsngYr) {
PassingYearProperty().set(PsngYr);
}
public final void setRegNo(String Reg) {
RegNoProperty().set(Reg);
}
public final void setStateName(String StNm) {
StateNameProperty().set(StNm);
}
public StringProperty QualProperty() {
if (Qual == null) {
Qual = new SimpleStringProperty(this, "Qual");
}
return Qual;
}
public StringProperty CollegeProperty() {
if (College == null) {
College = new SimpleStringProperty(this, "College");
}
return College;
}
public StringProperty UniversityProperty() {
if (University == null) {
University = new SimpleStringProperty(this, "University");
}
return University;
}
public StringProperty PassingYearProperty() {
if (PassingYear == null) {
PassingYear = new SimpleStringProperty(this, "PassingYear");
}
return PassingYear;
}
public StringProperty RegNoProperty() {
if (RegNo == null) {
RegNo = new SimpleStringProperty(this, "RegNo");
}
return RegNo;
}
public StringProperty StateNameProperty() {
if (StateName == null) {
StateName = new SimpleStringProperty(this, "StateName");
}
return StateName;
}
}
This is the FXML code of the Anchor Pane consisting the tableview QualTable
I Need help on this tableview and the function that I'm using to populate the table view...
The values are properly carried through the Qualification class but the tableview is not displaying the values on the row....
Please help me out through this and Thanks in Advance..!!!

javafx: display hyperlink in table cell

I am new to JAVAFX and am trying to display the hyperlink in table cell. I could able to display as a hyperlink but not able to open the link.
Please find the logic for the same.
Main method goes here::
public class Main extends Application {
private BorderPane root;
private TableView<Item> table;
private Scene scene;
private TableColumn<Item, String> nameColumn;
private TableColumn<Item, Hyperlink> urlColumn;
private ObservableList<Item> websiteList;
#Override
public void start(Stage primaryStage) {
root = new BorderPane();
//scene = new Scene(root, 400, 400);
table = new TableView<Item>();
//root.setCenter(table);
nameColumn = new TableColumn<>("Name");
nameColumn.setCellValueFactory(new PropertyValueFactory<>("websiteName"));
urlColumn = new TableColumn<>("Address");
urlColumn.setCellValueFactory(new PropertyValueFactory<>("hyperlink"));
urlColumn.setCellFactory(new HyperlinkCell());
table.getColumns().add(nameColumn);
table.getColumns().add(urlColumn);
websiteList = FXCollections.observableArrayList();
websiteList.add(new Item("Google", "https://www.google.co.in/"));
websiteList.add(new Item("Facebook", "www.facebook.com"));
websiteList.add(new Item("Superglobals", "www.superglobals.net"));
Hyperlink hyperlink = new Hyperlink("Go to Eclipse home page");
hyperlink.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
getHostServices().showDocument("https://www.google.co.in/");
}
});
root.getChildren().addAll(hyperlink);
// root.setBottom(hyperlink);
table.setItems(websiteList);
root.setCenter(table);
scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Item.java::
public class Item {
private String websiteName;
private Hyperlink hyperlink;
public Item(String websiteName, String websiteUrl) {
this.websiteName = websiteName;
this.hyperlink = new Hyperlink(websiteUrl);
}
public String getWebsiteName() {
return websiteName;
}
public void setWebsiteName(String websiteName) {
this.websiteName = websiteName;
}
public Hyperlink getHyperlink() {
return hyperlink;
}
public void setHyperlink(String websiteUrl) {
this.hyperlink = new Hyperlink(websiteUrl);
}
}
HyperlinkCell.java::
public class HyperlinkCell implements Callback<TableColumn<Item, Hyperlink>, TableCell<Item, Hyperlink>> {
private static HostServices hostServices ;
public static HostServices getHostServices() {
return hostServices ;
}
#Override
public TableCell<Item, Hyperlink> call(TableColumn<Item, Hyperlink> arg) {
TableCell<Item, Hyperlink> cell = new TableCell<Item, Hyperlink>() {
#Override
protected void updateItem(Hyperlink item, boolean empty) {
super.updateItem(item, empty);
setGraphic(empty ? null : item);
}
};
return cell;
}
}
Output is displaying like this but am not able to open the hyperlink. Please help us on this.
Thanks.
Just update the onAction handler of the hyperlink in the updateItem() method:
TableCell<Item, Hyperlink> cell = new TableCell<Item, Hyperlink>() {
#Override
protected void updateItem(Hyperlink item, boolean empty) {
super.updateItem(item, empty);
setGraphic(empty ? null : item);
if (! empty) {
item.setOnAction(e -> {
// handle event here...
});
}
}
};
Note that it's really not a good idea to use UI elements (such as Hyperlink) in your data classes (such as Item). I recommend you refactor this so that Item only holds the data:
public class Item {
private String websiteName;
private String url;
public Item(String websiteName, String websiteUrl) {
this.websiteName = websiteName;
this.url = websiteUrl;
}
public String getWebsiteName() {
return websiteName;
}
public void setWebsiteName(String websiteName) {
this.websiteName = websiteName;
}
public String getUrl() {
return url;
}
public void setUrl(String websiteUrl) {
this.url = websiteUrl;
}
}
And then:
private TableColumn<Item, String> urlColumn;
// ...
urlColumn = new TableColumn<>("Address");
urlColumn.setCellValueFactory(new PropertyValueFactory<>("url"));
urlColumn.setCellFactory(new HyperlinkCell());
Somewhere in start() you need to do
HyperlinkCell.setHostServices(getHostServices());
and finally define the Hyperlink in the cell. That way there is only one Hyperlink instance per cell, instead of one for every item in the table.
public class HyperlinkCell implements Callback<TableColumn<Item, Hyperlink>, TableCell<Item, Hyperlink>> {
private static HostServices hostServices ;
public static HostServices getHostServices() {
return hostServices ;
}
public static void setHostServices(HostServices hostServices) {
HyperlinkCell.hostServices = hostServices ;
}
#Override
public TableCell<Item, String> call(TableColumn<Item, String> arg) {
TableCell<Item, Hyperlink> cell = new TableCell<Item, Hyperlink>() {
private final Hyperlink hyperlink = new Hyperlink();
{
hyperlink.setOnAction(event -> {
String url = getItem();
hostServices.showDocument(url);
});
}
#Override
protected void updateItem(String url, boolean empty) {
super.updateItem(url, empty);
if (empty) {
setGraphic(null);
} else {
hyperlink.setText(url);
setGraphic(hyperlink);
}
}
};
return cell;
}
}

JavaFX TableView custom header

i am customizing JavaFX TableView's header.
therefore i add a Graphic to the Label. By clicking the Label of the header i toggle my custom header(two lined). all this is working fine.
The header gets automatically resized so the custom headerfits in.
BUT, when i hide my custom headerthe headerstays large.
What am i missing so the headershrinks again?
i created a MCVE to demonstrate my problem:
public class TableViewHeaderMCVE extends Application {
private final TableView<Person> table = new TableView<>();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
final VBox root = new VBox();
Scene scene = new Scene(root);
stage.setWidth(218);
stage.setHeight(216);
TableColumn colName = new TableColumn("name");
colName.setMinWidth(100);
colName.setSortable(false);
TableColumn colProfession = new TableColumn("profession");
colProfession.setMinWidth(100);
colProfession.setSortable(false);
table.getColumns().addAll(colName, colProfession);
root.getChildren().addAll(table);
stage.setScene(scene);
stage.show();
// apply this after show!
TableViewHeader.installMod(table);
}
public static class TableViewHeader {
public static void installMod(TableView table) {
for (Node n : table.lookupAll(".column-header > .label")) {
if (n instanceof Label) {
new CustomHeaderLabel((Label) n);
}
}
}
}
public static class CustomHeaderLabel extends BorderPane {
protected Label customNode = null;
BooleanProperty expanded = new SimpleBooleanProperty(this, "expanded", false);
public CustomHeaderLabel(final Label parent) {
Label label = new Label(parent.getText());
// custom MenuButton
Button btn = new Button();
btn.setGraphic(new Label("\u2261"));
btn.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent ae) {
System.out.println("Hello World");
}
});
TextField filterTextField = new TextField();
filterTextField.promptTextProperty().set("type here to filter");
setCenter(label);
setRight(btn);
setBottom(filterTextField);
EventHandler<MouseEvent> toggleHeader = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
expanded.set(!expanded.get());
}
};
parent.setOnMouseClicked(toggleHeader);
expanded.addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> obs, Boolean oldValue, Boolean value) {
showCustomHeader(value);
}
});
label.textProperty().bind(parent.textProperty());
parent.setGraphic(this);
customNode = parent;
showCustomHeader(expanded.get());
}
protected void showCustomHeader(Boolean value) {
if (value) {
customNode.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
customNode.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
public static class Person {
private final SimpleStringProperty name;
private final SimpleStringProperty profession;
private Person(String name, String profession) {
this.name = new SimpleStringProperty(name);
this.profession = new SimpleStringProperty(profession);
}
public String getName() {
return name.get();
}
public String getProfession() {
return profession.get();
}
}
}
thanks to #James_D for his reply.
after his reply i tested the code on another computer
works on:
JDK 1.8.0_161 on Windows 10
JDK 9.0.4 and JDK 10 on Mac OS X
fails on:
JDK 1.8.0_66-b18 on Windows 7

Javafx : Domain objects to TreeView

I have three domain objects in my app as follows :
public class Workflow {
private String name;
private List<Sheet> sheets;
}
public class Sheet {
private String name;
private List<Task> tasks;
}
public class Task {
private String name;
}
All three are dependent as Workflow -> Sheet -> Task. My goal is to build TreeView so that it look like below :
-Workflow
|
- workflow name
-Sheets
|
- sheet name
- Tasks
|
- task name
So far, I have build a sample that builds more less what I expect, but it's not generic and 'automated' at all.
public class TreeViewSample extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Tree View Sample");
Workflow w = setup();
TreeItem<String> rootItem = new TreeItem<String> ("Workflow");
rootItem.setExpanded(true);
TreeItem<String> item = new TreeItem<String> (w.getName());
rootItem.getChildren().add(item);
(...)
TreeView<String> tree = new TreeView<String> (rootItem);
StackPane root = new StackPane();
root.getChildren().add(tree);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
private Workflow setup(){
Workflow wflow = new Workflow();
wflow.setName("wflow name");
wflow.setSheets(Arrays.asList(new Sheet("sheet name", Arrays.asList(new Task("task name")))));
return wflow;
}
Can someone advise on how I can recursively go to my domain objects and build the TreeView as in my example ?
You have to create a common Model to all of you models(Workflow, Sheet,Task), since all have a String property, it is quite simple to create one. Let's suppose we have the following model:
public class Model {
private String name;
public Model(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return getName();
}
}
class Workflow {
private String name;
private List<Sheet> sheets = new ArrayList<>();
public Workflow(String name) {
this.name = name;
}
public String getName() {
return name;
}
public List<Sheet> getSheets() {
return sheets;
}
}
class Sheet {
private String name;
private List<Task> tasks = new ArrayList<>();
public Sheet(String name) {
this.name = name;
}
public String getName() {
return name;
}
public List<Task> getTasks() {
return tasks;
}
}
class Task {
private String name;
public Task(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
I kept there together all of your models, to see them better.
I see you don't use any .fxml file at your app, mine is with .fxml I recommend that you separate at least to separate the Main class from the Controller class, like:
public class Main extends Application{
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
AnchorPane pane = loader.load();
primaryStage.setScene(new Scene(pane,800,600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Then the Controller class:
public class Controller implements Initializable {
#FXML
private TreeView<Model> treeView;
#Override
public void initialize(URL location, ResourceBundle resources) {
Workflow workflow = createWorkflow(); // This just sets up the models that you are using.
// You have to create a root in your case the "Workflow"
TreeItem<Model> root = new TreeItem<>(new Model(workflow.getName()));
// The foreach sheet you create a branch
workflow.getSheets().forEach(sheet -> {
TreeItem<Model> sheetBranch = new TreeItem<>(new Model(sheet.getName()));
// Then you have to add each branch to the root
root.getChildren().add(sheetBranch);
// Then foreach sheet you create a task item
sheet.getTasks().forEach(task -> {
TreeItem<Model> taskItem = new TreeItem<>(new Model(task.getName()));
// Then you have to add each task to its sheet parent
sheetBranch.getChildren().add(taskItem);
});
});
// Finally, you set the root for the TreeView. Of course this can be done right after instantiating the root.
treeView.setRoot(root);
}
// ------------------- Setup the model -----------------------
private Workflow createWorkflow() {
Workflow workflow = new Workflow("Workflow");
workflow.getSheets().addAll(createSheets());
return workflow;
}
private List<Sheet> createSheets() {
List<Sheet> sheets = new ArrayList<>();
IntStream.range(1, 10).forEach(value -> sheets.add(createSheet()));
return sheets;
}
private Sheet createSheet() {
Sheet sheet = new Sheet("Sheet" + new Random().nextInt(100)); // Random added to have different names
sheet.getTasks().addAll(createTasks());
return sheet;
}
private List<Task> createTasks() {
List<Task> tasks = new ArrayList<>();
IntStream.range(1, 5).forEach(value -> tasks.add(createTask()));
return tasks;
}
private Task createTask() {
return new Task("Task" + new Random().nextInt(100)); // Random added to have different names
}
}
Just in case if you need here is the .fxml file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TreeView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="stackoverflow.tree.Controller">
<TreeView fx:id="treeView"/>
</AnchorPane>
If you don't know the depth of the TreeView you can create all of the branches or leaves using recursion. In this case it is much simpler to use two foreachs instead of creating a recursive method which builds the tree structure.
Lacking a common supertype providing a list of child items you need to use 1 different method/1 nested loop per object containing a list of sub objects, i.e.
private TreeItem<String> createWorkFlow(Workflow workflow) {
TreeItem<String> item = new TreeItem<>(workflow.getName());
for (Sheet sheet : workflow.getSheets()) {
item.getChildren().add(createSheet(sheet));
}
return item;
}
private TreeItem<String> createSheet(Sheet sheet) {
TreeItem<String> item = new TreeItem<>(sheet.getName());
for (Task task : sheet.getTasks()) {
item.getChildren().add(new TreeItem<>(task.getName());
}
return item;
}
Or
private TreeItem<String> createWorkFlow(Workflow workflow) {
TreeItem<String> workflowItem = new TreeItem<>(workflow.getName());
for (Sheet sheet : workflow.getSheets()) {
TreeItem<String> sheetItem = new TreeItem<>(sheet.getName());
for (Task task : sheet.getTasks()) {
sheetItem.getChildren().add(new TreeItem<>(task.getName()));
}
workflowItem.getChildren().add(sheetItem);
}
return item;
}
unless you want to use reflection.
To avoid this you could implement a interface with your types:
public interface Item<T extends Item<?>> {
String getName();
default List<T> getChildren() {
return null; // default for terminal object
}
}
which would allow you to simplify the creating of the TreeItems to
public static <T extends Item<?>> TreeItem<String> createItem(Item<T> item) {
TreeItem<String> treeItem = new TreeItem<>(item.getName());
List<T> children = item.getChildren();
if (children != null) {
for (Item<?> ci : children) {
treeItem.getChildren().add(createItem(ci));
}
}
return treeItem;
}

Having trouble retrieving value from tableview

I'm having having trouble getting a correct output from tableview. I'm using a button to set one item from tableview to a label. However, it prints "StringProperty [Value pineapples]" where I would like it to be just "pineapples".
The tableview gives them correctly.
public class ProductListController implements Initializable {
#FXML public TableView<Model> tableview ;
#FXML private TableColumn<Model, Number> ProductID;
#FXML private TableColumn<Model, String> ProductName;
#FXML private TableColumn<Model, Number> ProductPrice;
#FXML private Label lblProduct;
#FXML private Label lblPrice;
#FXML
private void btnActionShow(ActionEvent event) {
assert tableview !=null : " ";
ProductID.setCellValueFactory(cellData -> cellData.getValue().ProductIDProperty());
ProductName.setCellValueFactory(cellData -> cellData.getValue().ProductNameProperty());
ProductPrice.setCellValueFactory(cellData -> cellData.getValue().ProductPriceProperty());
buildData();
}
private ObservableList<Model> data;
public void buildData(){
data = FXCollections.observableArrayList();
try{
Connection conn = DriverManager.getConnection
("jdbc:derby://localhost:1527/Stock", "*****", "*****");
Statement stmt = conn.createStatement();
String SQL = "SELECT * FROM PRODUCTS";
ResultSet rs = stmt.executeQuery(SQL);
while (rs.next()) {
Model mod = new Model();
mod.ProductID.set(rs.getInt("ID"));
mod.ProductName.set(rs.getString("NAME"));
mod.ProductPrice.set(rs.getInt("SELL_PRICE"));
data.add(mod);
}
tableview.setItems(data);
}
catch ( SQLException err) {
System.out.println(err.getMessage() );
}
}
//Button to fetch data from Tableview. Sets the data not the way I want.
#FXML
private void btnConfirmAction(ActionEvent event) {
Model model = tableview.getSelectionModel().getSelectedItem();
String prd;
prd = model.getProductName().toString();
lblProduct.setText(prd);
}
#FXML
private void btnNextAction(ActionEvent event) {
try{
FXMLLoader loader = new FXMLLoader(getClass().getResource("/appl/Discount.fxml"));
Parent parent = loader.load();
DiscountController discountcontr = loader.getController();
discountcontr.setProduct(tableview.getSelectionModel().getSelectedItem().getProductName().toString());
Stage stage = new Stage();
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.show();
}
catch(IOException e){
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
}
}
Model
public class Model {
public SimpleIntegerProperty ProductID = new SimpleIntegerProperty();
public SimpleStringProperty ProductName = new SimpleStringProperty ();
public SimpleIntegerProperty ProductPrice = new SimpleIntegerProperty();
private final SimpleBooleanProperty Checked = new SimpleBooleanProperty(false);
public SimpleBooleanProperty checkedProperty() {
return this.Checked;
}
public java.lang.Boolean getChecked() {
return this.checkedProperty().get();
}
public void setChecked(final java.lang.Boolean checked) {
this.checkedProperty().set(checked);
}
public SimpleIntegerProperty getProductID() {
return ProductID;
}
public SimpleStringProperty getProductName() {
return ProductName;
}
public SimpleIntegerProperty getProductPrice() {
return ProductPrice;
}
Since getProductName() returns a SimpleStringProperty, you need to retrieve the String from it using the get(). Just use :
String prd = model.getProductName().get();
Your model is implemented incorrectly. You should use the following pattern:
public class Model {
private SimpleStringProperty productName = new SimpleStringProperty();
public SimpleStringProperty productNameProperty() {
return productName ;
}
public final String getProductName() {
return productNameProperty().get();
}
public final void setProductName(String productName) {
productNameProperty().set(productName);
}
}
and similarly for the other properties.
If you use the e(fx)clipse plugin, you can generate the methods automatically from the property definition by right-clicking, choosing "Source" and then "Generate JavaFX Getters and Setters". I think NetBeans has similar functionality.

Resources