Missing code to display data inside of the table - java

Goal:
Display data, below, inside of the table
"Jacob", "Smith", "jacob.smith#example.com"
"Isabella", "Johnson", "isabella.johnson#example.com"
"Ethan", "Williams", "ethan.williams#example.com"
"Emma", "Jones", "emma.jones#example.com"
"Michael", "Brown", "michael.brown#example.com"
Problem:
What code am I missing in order to display the data inside of the table?
Info:
I'm new in JavaFX.
I'm using netbeans
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="787.0" prefWidth="1086.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<TableView id="ttt" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<columns>
<TableColumn id="firstNameCol" prefWidth="124.0" text="First name" />
<TableColumn id="lastNameCol" prefWidth="139.0" text="Last name" />
<TableColumn id="emailCol" minWidth="7.0" prefWidth="197.0" text="Email" />
<TableColumn id="addressCol" prefWidth="105.0" text="Address" />
<TableColumn id="zipcodeCol" prefWidth="100.0" text="Zipcode" />
<TableColumn id="cityCol" prefWidth="204.0" text="City" />
</columns>
</TableView>
</center>
</BorderPane>
package dreamcrm;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class DreamCRM extends Application {
private TableView<Person> table = new TableView<Person>();
private final ObservableList<Person> data =
FXCollections.observableArrayList(
new Person("Jacob", "Smith", "jacob.smith#example.com"),
new Person("Isabella", "Johnson", "isabella.johnson#example.com"),
new Person("Ethan", "Williams", "ethan.williams#example.com"),
new Person("Emma", "Jones", "emma.jones#example.com"),
new Person("Michael", "Brown", "michael.brown#example.com")
);
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
package dreamcrm;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class FXMLDocumentController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
package dreamcrm;
import javafx.beans.property.SimpleStringProperty;
public class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty email;
public Person(String fName, String lName, String email) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
public String getEmail() {
return email.get();
}
public void setEmail(String fName) {
email.set(fName);
}
}

You will want to use fx:id instead of id for this. fx:id will still work with CSS selectors, so no worries there.
As #fabian pointed out, and that I missed, you also need to add the fx:controller in your fxml file so that it knows what is going to control it.
In your document controller, you will need to let it know it is getting some info from your fxml document using #FXML
So like this,
#FXML
private TableView ttt;
#FXML
private TableColumn<Person, String> firstNameCol, lastNameCol, emailCol,addressCol, zipCol, cityCol;
Here, you use your fx:id as the variable name.
Then, in your initialize function, you will need to set the cellValueFactory, like so.
#FXML
public void initialize(){
firstNamecol.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
//etc..
//Don't forget to add your list that you made to the tableview
ttt.setItems(list);
}
After you add the ObservableList you can now add and remove items and it should update accordingly.
On a related note, you need to have SimpleStringProperty as a returnable value, i.e.
public StringProperty firstNameProperty(){
return firstName;
}
This should get you started.

Related

How to add a button to a single row in a one column TableView?

I have a TableView with a single Column and I want to have a Button in the last row of that TableView/Column. The Button should be disabled until a row is selected and then it should be enabled. I've done numerous searches on this but everything I've found seems to be adding a button to every row within a multi-column table. Is there a quick way to do this?
Here are some sample images:
TableButtonView.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="406.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tablebutton.TableButtonController">
<children>
<VBox layoutX="60.0" layoutY="22.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="100.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label alignment="CENTER" maxWidth="1.7976931348623157E308" prefHeight="51.0" prefWidth="200.0" text="Agency Customization">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Label>
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="40.0">
<children>
<Label alignment="CENTER_RIGHT" maxHeight="1.7976931348623157E308" prefHeight="30.0" prefWidth="70.0" text="Agency: " />
<TextField fx:id="agencyTextField" maxHeight="1.7976931348623157E308" prefHeight="30.0" prefWidth="45.0" />
<Button fx:id="addButton" maxHeight="1.7976931348623157E308" onAction="#onAdd" prefHeight="30.0" prefWidth="67.0" text="_Add">
<HBox.margin>
<Insets left="10.0" />
</HBox.margin>
</Button>
</children>
<padding>
<Insets bottom="10.0" />
</padding>
</HBox>
<TableView fx:id="agencyTableView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="276.0">
<columns>
<TableColumn fx:id="agencyColumn" prefWidth="188.0" text="Agency" />
</columns>
<VBox.margin>
<Insets left="5.0" right="5.0" />
</VBox.margin>
</TableView>
<ButtonBar maxWidth="1.7976931348623157E308">
<buttons>
<Button fx:id="okAgencyButton" mnemonicParsing="false" onAction="#onOK" text="OK" />
<Button fx:id="cancelAgencyButton" mnemonicParsing="false" onAction="#onCancel" text="Cancel" />
</buttons>
<padding>
<Insets bottom="5.0" right="20.0" top="5.0" />
</padding>
</ButtonBar>
</children>
</VBox>
</children>
</AnchorPane>
TableButtonController.java:
package tablebutton;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class TableButtonController implements Initializable {
private WebView helpWebView;
#FXML
private TextField agencyTextField;
#FXML
private Button addButton;
#FXML
private TableView<String> agencyTableView;
#FXML
private TableColumn<String, String> agencyColumn;
#FXML
private Button okAgencyButton;
#FXML
private Button cancelAgencyButton;
#Override
public void initialize(URL url, ResourceBundle rb) {
agencyColumn.setCellValueFactory(cellData ->
new ReadOnlyStringWrapper(cellData.getValue())
);
agencyColumn.setStyle( "-fx-alignment: CENTER;");
ObservableList<String> agencies = FXCollections.observableArrayList(
"AA","DL","LH");
agencyTableView.getItems().addAll(agencies);
}
#FXML
private void onAdd(ActionEvent event) {
}
#FXML
private void onOK(ActionEvent event) {
// Just exit for now
Stage stage = (Stage) okAgencyButton.getScene().getWindow();
stage.close();
}
#FXML
private void onCancel(ActionEvent event) {
// Just exit for now
Stage stage = (Stage) cancelAgencyButton.getScene().getWindow();
stage.close();
}
}
TableButton.java:
package tablebutton;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class TableButton extends Application {
#Override
public void start(Stage primaryStage) {
try
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("TableButtonView.fxml"));
Scene scene = new Scene((Parent) loader.load());
primaryStage.setScene(scene);
primaryStage.setTitle("TableView Button Test");
primaryStage.show();
}
catch (IOException ignored)
{
}
}
public static void main(String[] args) {
launch(args);
}
}
Trying to put the button actually inside the TableView is problematic and not recommended. There is a technical difficulty in getting the button to render in the last row of the TableView (this is not trivial), and there are also potential usability issues (what if there are a lot of rows in the table and the table needs to be scrolled, does the remove button just scroll out of view? if so, then how would a user find it if they wanted to remove something).
Instead, don't put the button in the TableView:
Use a VBox which contains the the TableView and the Button.
Set appropriate constraints so that the Button butts right up under the TableView and is sized to the width of the TableView.
Bind the disable property of the Button to an empty selected items set.
Sample code:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Remover extends Application {
#Override
public void start(Stage stage) throws Exception {
ObservableList<NamedColor> colors = FXCollections.observableArrayList(
new NamedColor("red", Color.RED),
new NamedColor("green", Color.GREEN),
new NamedColor("blue", Color.BLUE),
new NamedColor("indigo", Color.INDIGO)
);
TableView<NamedColor> table = new TableView<>(colors);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
TableColumn<NamedColor, String> colorNames = new TableColumn<>("Colors");
colorNames.setCellValueFactory(new PropertyValueFactory<>("name"));
table.getColumns().add(colorNames);
Button remove = new Button("Remove");
remove.disableProperty().bind(
Bindings.isEmpty(
table.getSelectionModel().getSelectedItems()
)
);
remove.setMaxWidth(Double.MAX_VALUE);
remove.setOnAction(event ->
table.getItems()
.removeAll(
table.getSelectionModel().getSelectedItems()
)
);
VBox layout = new VBox(table, remove);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch(Remover.class);
}
public static class NamedColor {
private String name;
private Color color;
public NamedColor(String name, Color color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public Color getColor() {
return color;
}
}
}

JavaFX: TableView Cell pixelates ImageView - How do I undo transform?

Edit: This question has been completely reworked in light of new information.
This is using javafx8 and SceneBuilder2.
I have found that making a TableView the child of an accordion's AnchorPane, and then (in SceneBuilder) right clicking on the TableView, and clicking "fit-to-parent" causes images displayed in table cells to distort and lose quality; things look bold. I passed this image
to the table constructor to be displayed. The one on the left is before "fit-to-content" was applied; the one on the right was after.
Does anyone have some idea of a way I can get around this? Because I need a table in an accordion to dynamically resize horizontally with the window without my image losing quality.
Minimal Example Below
The controller first
package application;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import java.net.URL;
public class SampleController implements Initializable
{
#FXML private TableView<SomeTableItems> someTable;
#FXML private TableColumn<SomeTableItems, String> imagesRow;
#FXML private TableColumn<SomeTableItems, String> description;
#FXML private TableColumn<SomeTableItems, String> modified;
#FXML private TableColumn<SomeTableItems, String> created;
#Override
public void initialize(URL arg0, ResourceBundle arg1)
{
imagesRow.setCellValueFactory(new PropertyValueFactory<SomeTableItems, String>("imagesRow"));
description.setCellValueFactory(new PropertyValueFactory<SomeTableItems, String>("description"));
modified.setCellValueFactory(new PropertyValueFactory<SomeTableItems, String>("modified"));
created.setCellValueFactory(new PropertyValueFactory<SomeTableItems, String>("created"));
someTable.setItems(getSomeTableItems());
}
private ObservableList<SomeTableItems> getSomeTableItems()
{
ObservableList<SomeTableItems> itemsToReturn = FXCollections.observableArrayList();
itemsToReturn.add(new SomeTableItems("/imageAssets/tableImage1.png","secondContent", "thirdContent", "fourthContent"));
return itemsToReturn;
}
}
Assume you have a package called imageAssets containing an image titled "tableImage1.png" for the above code. The constructor for SomeTableItems is below.
package application;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class SomeTableItems
{
private Node imagesRow;
private SimpleStringProperty description;
private SimpleStringProperty modified;
private SimpleStringProperty created;
public Node getImagesRow()
{
return imagesRow;
}
public String getDescription()
{
return description.get();
}
public String getModified() {
return modified.get();
}
public String getCreated()
{
return created.get();
}
public void setImagesRow(String pathToImage)
{
this.imagesRow = new ImageView(new Image(getClass().getResourceAsStream(pathToImage)));
}
public void setDescription(SimpleStringProperty description)
{
this.description = description;
}
public void setModified(SimpleStringProperty modified)
{
this.modified = modified;
}
public void setCreated(SimpleStringProperty created)
{
this.created = created;
}
public SomeTableItems()
{
this.imagesRow = new ImageView(new Image(getClass().getResourceAsStream("/imageAssets/tableImage1.png")));
this.description = new SimpleStringProperty("-");
this.modified = new SimpleStringProperty("-");
this.created = new SimpleStringProperty("-");
}
public SomeTableItems(String pathToImage, String description, String modified, String created)
{
this.imagesRow = new ImageView(new Image(getClass().getResourceAsStream(pathToImage)));
this.description = new SimpleStringProperty(description);
this.modified = new SimpleStringProperty(modified);
this.created = new SimpleStringProperty(created);
}
}
Below is the fxml made in SceneBuilder2
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane prefHeight="206.0" prefWidth="384.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SampleController">
<center>
<Accordion BorderPane.alignment="CENTER">
<panes>
<TitledPane animated="false" text="untitled 3">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TableView fx:id="someTable" prefHeight="180.0" prefWidth="382.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" BorderPane.alignment="CENTER">
<columns>
<TableColumn fx:id="imagesRow" prefWidth="75.0" text="C1" />
<TableColumn fx:id="description" prefWidth="75.0" text="C2" />
<TableColumn fx:id="modified" prefWidth="75.0" text="C3" />
<TableColumn fx:id="created" prefWidth="75.0" text="C4" />
</columns>
</TableView>
</children>
</AnchorPane>
</content>
</TitledPane>
</panes>
</Accordion>
</center>
</BorderPane>
The above code reproduces the error shown in the screenshot at the beginning. If you look at the line in the fxml where the TableView is declared, you can undo the fit-to-parent effect by replacing the line with the below code. It is the difference between the bolding "glitch" happening or not.
<TableView fx:id="someTable" prefHeight="200.0" prefWidth="402.0" BorderPane.alignment="CENTER">
And the Main is generic. I will happily include a main upon request though.
Thanks to anyone interested and willing to assist me. I really appreciate your time.
There is almost never a good reason to use AnchorPane. While it is possible for AnchorPane to have legitimate uses, in practice it is far more common that AnchorPane is used the same way null layouts were used in AWT/Swing: to exactly specify the location and size of a node.
Forcing the size of your table is what’s causing the image to get (slightly) resized.
The easiest solution is to use a layout which will respect the preferred size of its child node, such as a BorderPane or StackPane:
<BorderPane>
<center>
<TableView fx:id="someTable" …
…
</TableView>
</center>
</BorderPane>

Bind TableView items with ObservableList in FXML - Java FX

I'm unable to bind TableView items with ObservableList in FXML.
Everything works fine when I set materialTable.setItems(materialDataObservableList); in button click event.
But I don't want button to know about TableView so I wanted to bind materialTable.items to materialDataObservableList property.
What am I doing wrong?
Or maybe I don't understand how binding works...
Thanks for help!
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="464.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.xxx.sm.frontend.fx.MainSceneController">
/*
*/
<children>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<Button fx:id="getMaterialsButton" mnemonicParsing="false" onAction="#getMaterialsButton" text="Get materials" />
<TableView fx:id="materialTable" editable="true" prefHeight="413.0" prefWidth="600.0" items="${materialDataObservableList}" >
//Columns here
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</VBox>
</children>
public class MainSceneController {
private ObservableList<MaterialData> materialDataObservableList;
public TableView materialTable;
public Button getMaterialsButton;
public void getMaterialsButton() {
getMaterialsFromRESTController();
}
private void getMaterialsFromRESTController() {
MaterialClient controller = new MaterialClient();
try {
materialDataObservableList = FXCollections.observableArrayList(controller.getMaterias());
} catch (IOException e) {
System.out.println("Failed to connect to RESTController");
}
//materialTable.setItems(materialDataObservableList);
}
public ObservableList<MaterialData> getMaterialDataObservableList() {
return materialDataObservableList;
}
}
If you are calling getMaterialsFromRESTController() from MainSceneController's constructor (so it is initialized as soon as the controller is available to the FXMLLoader), then
<TableView fx:id="materialTable" editable="true" prefHeight="413.0" prefWidth="600.0"
items="${controller.materialDataObservableList}" >
will work. (Note you access a property of the controller with ${controller.property}.)
If not, you can modify the controller as follows to make it work:
public class MainSceneController {
private final ObservableList<MaterialData> materialDataObservableList
= FXCollections.observableArrayList();
public TableView materialTable;
public Button getMaterialsButton;
public void getMaterialsButton() {
getMaterialsFromRESTController();
}
private void getMaterialsFromRESTController() {
MaterialClient controller = new MaterialClient();
try {
materialDataObservableList.setAll(controller.getMaterias());
} catch (IOException e) {
System.out.println("Failed to connect to RESTController");
}
}
public ObservableList<MaterialData> getMaterialDataObservableList() {
return materialDataObservableList;
}
}
and then the above FXML should work.
Here is a SSCCE:
BindTableItemsExample.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>
<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="TableController">
<center>
<TableView items="${controller.items}">
<columns>
<TableColumn text="Item">
<cellValueFactory><PropertyValueFactory property="name" /></cellValueFactory>
</TableColumn>
</columns>
</TableView>
</center>
<bottom>
<Button text="Load" onAction="#loadItems" BorderPane.alignment="center" >
<BorderPane.margin>
<Insets top="5" left="5" right="5" bottom="5"/>
</BorderPane.margin>
</Button>
</bottom>
</BorderPane>
TableController.java:
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
public class TableController {
private final ObservableList<Item> items = FXCollections.observableArrayList();
#FXML
private void loadItems() {
items.setAll(createItems());
}
private List<Item> createItems() {
return IntStream.rangeClosed(1, 100)
.mapToObj(i -> "Item "+i)
.map(Item::new)
.collect(Collectors.toList());
}
public ObservableList<Item> getItems() {
return items ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
public Item(String name) {
setName(name);
}
public final StringProperty nameProperty() {
return this.name;
}
public final java.lang.String getName() {
return this.nameProperty().get();
}
public final void setName(final java.lang.String name) {
this.nameProperty().set(name);
}
}
}
BindTableItemsTest.java (application class):
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class BindTableItemsTest extends Application {
#Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("BindTableItemsExample.fxml"));
primaryStage.setScene(new Scene(loader.load(), 600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Adapting Oracle's Address book tutorial to include cell editing

I'm a novice and would very like a to know how to make a column cell editable when using FXML.
Specifically, I have been following the two working examples provided by Oracle. The first one (http://docs.oracle.com/javafx/2/ui_controls/table-view.htm) allows editing.
The second example ( http://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm ) suggests at the bottom of the tutorial that it can be edited but doesn't show how this is achieved.
I have read the answers to the related questions but they are beyond my current level ofknowledge.
Can anyone show me how it can be done in as simpler way as possible please?
To save you looking up the tutorial these are the files which I've copied directly from Oracle:
Thanks in advance.
First is FXMLTableView.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package fxmltableview;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class FXMLTableView extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("FXML TableView Example");
Pane myPane = (Pane)FXMLLoader.load(getClass().getResource
("fxml_tableview.fxml"));
Scene myScene = new Scene(myPane);
primaryStage.setScene(myScene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The second one is the controller:
package fxmltableview;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
public class FXMLTableViewController {
#FXML private TableView<Person> tableView;
#FXML private TextField firstNameField;
#FXML private TextField lastNameField;
#FXML private TextField emailField;
#FXML
protected void addPerson(ActionEvent event) {
ObservableList<Person> data = tableView.getItems();
data.add(new Person(firstNameField.getText(),
lastNameField.getText(),
emailField.getText()
));
firstNameField.setText("");
lastNameField.setText("");
emailField.setText("");
}
}
The third file is FormattedTableCellFactory.java
package fxmltableview;
import java.text.Format;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.text.TextAlignment;
import javafx.util.Callback;
public class FormattedTableCellFactory<S, T>
implements Callback<TableColumn<S, T>, TableCell<S, T>> {
private TextAlignment alignment;
private Format format;
public TextAlignment getAlignment() {
return alignment;
}
public void setAlignment(TextAlignment alignment) {
this.alignment = alignment;
}
public Format getFormat() {
return format;
}
public void setFormat(Format format) {
this.format = format;
}
#Override
#SuppressWarnings("unchecked")
public TableCell<S, T> call(TableColumn<S, T> p) {
TableCell<S, T> cell = new TableCell<S, T>() {
#Override
public void updateItem(Object item, boolean empty) {
if (item == getItem()) {
return;
}
super.updateItem((T) item, empty);
if (item == null) {
super.setText(null);
super.setGraphic(null);
} else if (format != null) {
super.setText(format.format(item));
} else if (item instanceof Node) {
super.setText(null);
super.setGraphic((Node) item);
} else {
super.setText(item.toString());
super.setGraphic(null);
}
}
};
cell.setTextAlignment(alignment);
switch (alignment) {
case CENTER:
cell.setAlignment(Pos.CENTER);
break;
case RIGHT:
cell.setAlignment(Pos.CENTER_RIGHT);
break;
default:
cell.setAlignment(Pos.CENTER_LEFT);
break;
}
return cell;
}
}
The fourth file is the Person class:
package fxmltableview;
import javafx.beans.property.SimpleStringProperty;
public class Person {
private final SimpleStringProperty firstName = new SimpleStringProperty("");
private final SimpleStringProperty lastName = new SimpleStringProperty("");
private final SimpleStringProperty email = new SimpleStringProperty("");
public Person() {
this("", "", "");
}
public Person(String firstName, String lastName, String email) {
setFirstName(firstName);
setLastName(lastName);
setEmail(email);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
public String getEmail() {
return email.get();
}
public void setEmail(String fName) {
email.set(fName);
}
}
and the last file is the .fxml file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.cell.*?>
<?import javafx.collections.*?>
<?import fxmltableview.*?>
<GridPane alignment="CENTER" hgap="10.0" vgap="10.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="fxmltableview.FXMLTableViewController">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<children>
<Label style="-fx-font: NORMAL 20 Tahoma;" text="Address Book" GridPane.columnIndex="0" GridPane.rowIndex="0">
</Label>
<TableView fx:id="tableView" editable="true" GridPane.columnIndex="0" GridPane.rowIndex="1">
<columns>
<TableColumn fx:id="firstNameColumn" prefWidth="100" text="First Name">
<cellValueFactory>
<PropertyValueFactory property="firstName" />
</cellValueFactory>
<cellFactory>
<FormattedTableCellFactory alignment="left">
</FormattedTableCellFactory>
</cellFactory>
</TableColumn>
<TableColumn prefWidth="100" text="Last Name">
<cellValueFactory>
<PropertyValueFactory property="lastName" />
</cellValueFactory>
<cellFactory>
<FormattedTableCellFactory alignment="left">
</FormattedTableCellFactory>
</cellFactory>
</TableColumn>
<TableColumn prefWidth="200" text="Email Address">
<cellValueFactory>
<PropertyValueFactory property="email" />
</cellValueFactory>
<cellFactory>
<FormattedTableCellFactory alignment="left">
</FormattedTableCellFactory>
</cellFactory>
</TableColumn>
</columns>
<items>
<FXCollections fx:factory="observableArrayList">
<Person email="jacob.smith#example.com" firstName="Jacob" lastName="Smith" />
<Person email="isabella.johnson#example.com" firstName="Isabella" lastName="Johnson" />
<Person email="ethan.williams#example.com" firstName="Ethan" lastName="Williams" />
<Person email="emma.jones#example.com" firstName="Emma" lastName="Jones" />
<Person email="michael.brown#example.com" firstName="Michael" lastName="Brown" />
</FXCollections>
</items>
<sortOrder>
<fx:reference source="firstNameColumn" />
</sortOrder>
</TableView>
<HBox alignment="bottom_right" spacing="10" GridPane.columnIndex="0" GridPane.rowIndex="2">
<children>
<TextField fx:id="firstNameField" prefWidth="90" promptText="First Name" />
<TextField fx:id="lastNameField" prefWidth="90" promptText="Last Name" />
<TextField fx:id="emailField" prefWidth="150" promptText="email" />
<Button onAction="#addPerson" text="Add" />
</children>
</HBox>
</children>
<columnConstraints>
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints />
<RowConstraints />
<RowConstraints />
</rowConstraints>
</GridPane>

tableview not showing data from database

I am unable to populate my tableview. I believe the problem is in the controller, in the way my data is being sent to the FXML file, because a system out print (see below) shows exactly what I have in my database.
Please let me know where I did a mistake. I went over all tutorials that exist on that, but nothing fits my problem.
Thanks
Main App:
package tableview;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MainApp extends Application {
public static void main(String[] args) {
// TODO Auto-generated method stub
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("view/FXMLTable.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Controller:
import tableview.model.Person;
public class FXMLTableController{
#FXML
public TableView<Person> tableview ;
#FXML
private TableColumn<Person, Number> clientIdColumn;
#FXML
private TableColumn<Person, String> firstNameColumn;
#FXML
private TableColumn<Person, String> lastNameColumn;
#FXML
private void initialize() {
assert tableview != null : "fx:id=\"tableview\" was not injected: check your FXML file 'UserMaster.fxml'.";
clientIdColumn.setCellValueFactory(cellData -> cellData.getValue().
clientIDProperty());
firstNameColumn.setCellValueFactory(cellData -> cellData.getValue()
.firstNameProperty());
lastNameColumn.setCellValueFactory(cellData -> cellData.getValue()
.lastNameProperty());
buildData();
}
private ObservableList<Person> data;
public void buildData(){
data = FXCollections.observableArrayList();
Connection con = null;
try {
Class.forName("org.sqlite.JDBC");
con = DriverManager.getConnection("jdbc:sqlite:tableviewdb.db");
String SQL = "Select * from INFO";
ResultSet rs = con.createStatement().executeQuery(SQL);
while(rs.next()){
Person per = new Person();
per.ClientID.set(rs.getInt("CLIENTID"));
per.FirstName.set(rs.getString("FIRSTNAME"));
per.LastName.set(rs.getString("LASTNAME"));
data.add(per);
}
tableview = new TableView<Person>();
tableview.setItems(data);
System.out.println(tableview.getItems().get(1).ClientID);
}
catch(Exception e){
e.printStackTrace();
System.out.println("Error on Building Data");
}
}
}
Model Class:
package tableview.model;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Person {
public SimpleIntegerProperty ClientID = new SimpleIntegerProperty();
public SimpleStringProperty FirstName = new SimpleStringProperty();
public SimpleStringProperty LastName = new SimpleStringProperty();
public SimpleIntegerProperty getClientID() {
return ClientID;
}
public SimpleStringProperty getFirstname() {
return FirstName;
}
public SimpleStringProperty getLastName() {
return LastName;
}
public IntegerProperty clientIDProperty(){
return ClientID;
}
public StringProperty firstNameProperty(){
return FirstName;
}
public StringProperty lastNameProperty(){
return LastName;
}
}
FXML file:
(disregard the save button for now...)
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<children>
<SplitPane prefHeight="400.0" prefWidth="600.0">
<items>
<SplitPane dividerPositions="0.5" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<TextField layoutX="93.0" layoutY="34.0" />
<TextField layoutX="93.0" layoutY="85.0" />
<Label layoutX="35.0" layoutY="39.0" text="name" />
<Label layoutX="35.0" layoutY="90.0" text="email" />
<Button layoutX="204.0" layoutY="140.0" mnemonicParsing="false" text="save" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<TableView layoutY="-2.0" prefHeight="200.0" prefWidth="598.0">
<columns>
<TableColumn prefWidth="302.0" text="name" />
<TableColumn prefWidth="295.0" text="email" />
</columns>
</TableView>
</children>
</AnchorPane>
</items>
</SplitPane>
</items>
</SplitPane>
</children>
</AnchorPane>
You're creating a new TableView and setting its items, instead of setting the items on the table that the FXML file defined. Remove the
tableView = new TableView<Person>();
from the controller.
To get the #FXML-annotated fields in the controller to be populated with the appropriate elements from the FXML file, you need to add fx:id attributes to those elements:
<TableView fx:id="tableview" ... >
<columns>
<TableColumn fx:id="firstNameColumn" ... />
...

Categories