When using a jfx TableView and setting setTableMenuButtonVisible to true, a small button with a "+" sign appears at the top right corner of the table. The problem is that it's a narrow rectangle but I want it to be more square, I've tried padding etc but nothing works.
Also, the "+" sign in the button seems to be a "-fx-shape". Is there anyway I can change it to a png image from my desktop instead?
With css file:
TableViewStyling.class (your class file)
showHideColumnImage.png (image file you want to use instead of 'plus' sign
stylesheet.css (css file for styling tableView's TableMenuButton)
stylesheet.css content
.table-view .show-hide-column-image {
-fx-background-image: url("showHideColumnImage.png");
-fx-padding: 2em; /* play with here to make it square */
-fx-shape: null;
}
usage example
package so;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
public class TableViewStyling 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"));
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
String css = this.getClass().getResource("stylesheet.css").toExternalForm();
scene.getStylesheets().add(css);
stage.setTitle("Table View Styling Sample");
stage.setWidth(450);
stage.setHeight(550);
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
TableColumn<Person, String> emailCol = new TableColumn<>("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
table.setTableMenuButtonVisible(true);
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
((Group) scene.getRoot()).getChildren().addAll(table);
stage.setScene(scene);
stage.show();
}
public class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty email;
private 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);
}
}
}
without css file:
lookup and find related node and apply css.
this way you can only lookup and find node after application show up (stage.show();)
package so;
import java.util.Set;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
public class TableViewStyling 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"));
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Table View Styling Sample 2");
stage.setWidth(450);
stage.setHeight(550);
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
TableColumn<Person, String> emailCol = new TableColumn<>("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
table.setTableMenuButtonVisible(true);
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
((Group) scene.getRoot()).getChildren().addAll(table);
stage.setScene(scene);
stage.show();
Set<Node> lookupAll = table.lookupAll(".show-hide-column-image");
lookupAll.forEach(n -> {
n.setStyle(""
+ "-fx-padding: 2em;"
+ "-fx-shape: null;"
+ "-fx-background-image: url(\""
+ TableViewStyling.class.getResource("showHideColumnImage.png").toExternalForm() + "\");");
});
}
public class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty email;
private 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);
}
}
}
Related
I took a stab at this yesterday but the TableView documentation has me a bit confused. After working on it for a couple of hours I gave up. Just wondering if any javafx experts out there can help me with this. I want to update a TableView in a background thread periodically when items in my database change.
Rather than post my entire application I have tried to break it down to a simple example. Replace all occurrences of ListView with TableView and ....
Then what?
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.Event;
import javafx.event.EventType;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* An example of triggering a JavaFX ListView when an item is modified.
*
* Displays a list of strings. It iterates through the strings adding
* exclamation marks with 2 second pauses in between. Each modification is
* accompanied by firing an event to indicate to the ListView that the value
* has been modified.
*
* #author Mark Fashing
*/
public class ListViewTest extends Application {
/**
* Informs the ListView that one of its items has been modified.
*
* #param listView The ListView to trigger.
* #param newValue The new value of the list item that changed.
* #param i The index of the list item that changed.
*/
public static <T> void triggerUpdate(ListView<T> listView, T newValue, int i) {
EventType<? extends ListView.EditEvent<T>> type = ListView.editCommitEvent();
Event event = new ListView.EditEvent<>(listView, type, newValue, i);
listView.fireEvent(event);
}
#Override
public void start(Stage primaryStage) {
// Create a list of mutable data. StringBuffer works nicely.
final List<StringBuffer> listData = Stream.of("Fee", "Fi", "Fo", "Fum")
.map(StringBuffer::new)
.collect(Collectors.toList());
final ListView<StringBuffer> listView = new ListView<>();
listView.getItems().addAll(listData);
final StackPane root = new StackPane();
root.getChildren().add(listView);
primaryStage.setScene(new Scene(root));
primaryStage.show();
// Modify an item in the list every 2 seconds.
new Thread(() -> {
IntStream.range(0, listData.size()).forEach(i -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(listData.get(i));
Platform.runLater(() -> {
// Where the magic happens.
listData.get(i).append("!");
triggerUpdate(listView, listData.get(i), i);
});
});
}).start();
}
public static void main(String[] args) {
launch(args);
}
}
Here is my first attempt:
Create a person class....
package org.pauquette.example;
import javafx.beans.property.SimpleStringProperty;
public class Person {
private final SimpleStringProperty email;
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
Person(String fName, String lName, String email) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getEmail() {
return email.get();
}
public String getFirstName() {
return firstName.get();
}
public String getLastName() {
return lastName.get();
}
public void setEmail(String fName) {
email.set(fName);
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public void setLastName(String fName) {
lastName.set(fName);
}
}
Create an extremely simple model class...
package org.pauquette.example;
import javafx.collections.*;
public class PeopleModel {
private ObservableList<Person> people=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")
);
public ObservableList<Person> getPeople() {
return people;
}
}
Now create a TableView of just firstName and build the columns then update the firstName every 2 seconds.......
package org.pauquette.example;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* An example of triggering a JavaFX TableView when an item is modified.
*
* Displays a list of strings. It iterates through the strings adding
* exclamation marks with 2 second pauses in between. Each modification is
* accompanied by firing an event to indicate to the TableView that the value
* has been modified.
*
* #author Mark Fashing-Modified for TableView by Bryan Pauquette
*/
public class TableViewTest extends Application {
/*
public static <T> void triggerUpdate(TableView<T> listView, T newValue, int i) {
EventType<? extends TableView.EditEvent<T>> type = TableView.editCommitEvent();
Event event = new TableView.EditEvent<>(listView, type, newValue, i);
listView.fireEvent(event);
}*/
#Override
public void start(Stage primaryStage) {
final TableView<Person> listView = new TableView<Person>();
final PeopleModel model=new PeopleModel();
final ObservableList<Person> listData=model.getPeople();
listView.getItems().addAll(listData);
final StackPane root = new StackPane();
buildColumns(listView,listData);
root.getChildren().add(listView);
primaryStage.setScene(new Scene(root));
primaryStage.show();
// Modify an item in the list every 2 seconds.
new Thread(() -> {
IntStream.range(0, listData.size()).forEach(i -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(listData.get(i));
Platform.runLater(() -> {
// Where the magic happens.
Person p=listData.get(i);
p.setFirstName(new StringBuilder(p.getFirstName()).append("!").toString());
//triggerUpdate(listView, listData.get(i), i);
});
});
}).start();
}
private void buildColumns(TableView<Person> listView,ObservableList<Person> listData) {
TableColumn<Person, String> dataCol = new TableColumn<Person, String>("First Name");
dataCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
listView.getColumns().add(dataCol);
listView.setItems(listData);
}
public static void main(String[] args) {
launch(args);
}
}
The method I am struggling with is triggerUpdate.....
I want the firstName column to get updated in the view with an appended exclamation point every 2 seconds just like in the original simple list view.
Here is working code.....
package org.pauquette.example;
import java.util.Observable;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
public class Person extends Observable {
private final SimpleStringProperty email;
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
Person(String fName, String lName, String email) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getEmail() {
return email.get();
}
public String getFirstName() {
return firstName.get();
}
public String getLastName() {
return lastName.get();
}
public void setEmail(String emailIn) {
email.setValue(emailIn);
setChanged();
notifyObservers(email);
}
public void setFirstName(String fNameIn) {
firstName.setValue(fNameIn);
setChanged();
notifyObservers(firstName);
}
public void setLastName(String lNameIn) {
lastName.setValue(lNameIn);
setChanged();
notifyObservers();
}
public ObservableValue<String> firstNameProperty() {
return firstName;
}
}
And......
package org.pauquette.example;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
* An example of triggering a JavaFX TableView when an item is modified.
*
* Displays a list of strings. It iterates through the strings adding
* exclamation marks with 2 second pauses in between. Each modification is
* accompanied by firing an event to indicate to the TableView that the value
* has been modified.
*
* #author Mark Fashing-Modified for TableView by Bryan Pauquette
*/
public class TableViewTest extends Application {
/*
public static <T> void triggerUpdate(TableView<T> listView, T newValue, int i) {
EventType<? extends TableView.EditEvent<T>> type = TableView.editCommitEvent();
Event event = new TableView.EditEvent<>(listView, type, newValue, i);
listView.fireEvent(event);
}*/
#Override
public void start(Stage primaryStage) {
final TableView<Person> listView = new TableView<Person>();
final PeopleModel model=new PeopleModel();
final ObservableList<Person> listData=model.getPeople();
/* int row=0;
for (Person p : listData) {
p.addObserver(new PersonObserver(listView,row));
row++;
}*/
listView.getItems().addAll(listData);
final StackPane root = new StackPane();
buildColumns(listView,listData);
root.getChildren().add(listView);
primaryStage.setScene(new Scene(root));
primaryStage.show();
// Modify an item in the list every 2 seconds.
new Thread(() -> {
IntStream.range(0, listData.size()).forEach(i -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(listData.get(i));
Platform.runLater(() -> {
// Where the magic happens.
Person p=listData.get(i);
p.setFirstName(new StringBuilder(p.getFirstName()).append("!").toString());
//triggerUpdate(listView, listData.get(i), i);
});
});
}).start();
}
private void buildColumns(TableView<Person> listView,ObservableList<Person> listData) {
TableColumn<Person, String> dataCol = new TableColumn<Person, String>("First Name");
//dataCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
dataCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
// p.getValue() returns the Person instance for a particular TableView row
return p.getValue().firstNameProperty();
}
});
listView.getColumns().add(dataCol);
listView.setItems(listData);
}
public static void main(String[] args) {
launch(args);
}
}
I am trying to make a tableview clickable, where it will return the text in the cell that is clicked. I am receiving two errors when trying to compile in Netbeans. All of the code was taken from "Example 12-11: Alternative Solution Of Cell Editing" official tableview tutorial & from this stackoverflow.com answer. Here are the errors:
type argument MouseEvent is not within bounds of type-variable T
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler() {
where T is a type-variable:
T extends Event declared in interface EventHandler
method addEventFilter in class Node cannot be applied to given types;
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler() {
required: EventType,EventHandler
found: int,>
reason: no instance(s) of type variable(s) T exist so that argument type int conforms to formal parameter type EventType
where T is a type-variable:
T extends Event declared in method addEventFilter(EventType,EventHandler)
import java.awt.event.MouseEvent;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TableViewSample extends Application {
private TableView<Person> table = new TableView<>();
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"));
final HBox hb = new HBox();
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(450);
stage.setHeight(550);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
table.setEditable(false);
Callback<TableColumn, TableCell> cellFactory =
new Callback<TableColumn, TableCell>() {
public TableCell call(TableColumn p) {
TableCell cell = new TableCell<Person, String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : getString());
setGraphic(null);
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
};
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getClickCount() > 1) {
System.out.println("double clicked!");
TableCell c = (TableCell) event.getSource();
System.out.println("Cell text: " + c.getText());
}
}
});
return cell;
}
};
TableColumn firstNameCol = new TableColumn("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("firstName"));
firstNameCol.setCellFactory(cellFactory);
firstNameCol.setOnEditCommit(
new EventHandler<CellEditEvent<Person, String>>() {
#Override
public void handle(CellEditEvent<Person, String> t) {
((Person) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setFirstName(t.getNewValue());
}
}
);
TableColumn lastNameCol = new TableColumn("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("lastName"));
lastNameCol.setCellFactory(cellFactory);
lastNameCol.setOnEditCommit(
new EventHandler<CellEditEvent<Person, String>>() {
#Override
public void handle(CellEditEvent<Person, String> t) {
((Person) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setLastName(t.getNewValue());
}
}
);
TableColumn emailCol = new TableColumn("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("email"));
emailCol.setCellFactory(cellFactory);
emailCol.setOnEditCommit(
new EventHandler<CellEditEvent<Person, String>>() {
#Override
public void handle(CellEditEvent<Person, String> t) {
((Person) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setEmail(t.getNewValue());
}
}
);
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
final TextField addFirstName = new TextField();
addFirstName.setPromptText("First Name");
addFirstName.setMaxWidth(firstNameCol.getPrefWidth());
final TextField addLastName = new TextField();
addLastName.setMaxWidth(lastNameCol.getPrefWidth());
addLastName.setPromptText("Last Name");
final TextField addEmail = new TextField();
addEmail.setMaxWidth(emailCol.getPrefWidth());
addEmail.setPromptText("Email");
final Button addButton = new Button("Add");
addButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
data.add(new Person(
addFirstName.getText(),
addLastName.getText(),
addEmail.getText()));
addFirstName.clear();
addLastName.clear();
addEmail.clear();
}
});
hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton);
hb.setSpacing(3);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table, hb);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty email;
private 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);
}
}
class EditingCell extends TableCell<Person, String> {
private TextField textField;
public EditingCell() {
}
#Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
textField.focusedProperty().addListener(new ChangeListener<Boolean>(){
#Override
public void changed(ObservableValue<? extends Boolean> arg0,
Boolean arg1, Boolean arg2) {
if (!arg2) {
commitEdit(textField.getText());
}
}
});
}
private String getString() {
return getItem() == null ? "" : getItem();
}
}
}
You have the wrong import for MouseEvent. You need javafx.scene.input.MouseEvent, not the AWT version.
It is likely that when your IDE prompted you to import MouseEvent, the first option was java.awt.event.MouseEvent, rather than javafx.scene.input.MouseEvent.
Be careful while importing with JavaFX, as many of it's classes have the same names as classes in standard Java libraries.
Similar to the question here: Javafx tableview with data from multiple classes
I am trying to create a table composed of more than one class. The backend is sqlite tables and I am trying to implement the Toxi solution found here: http://tagging.pui.ch/post/37027745720/tags-database-schemas That is why my simplified example below is the way it is - split up into unnecessary classes.
It is the Tag column I am trying to figure out. Is a wrapper class the cleanest way to go,a BookmarkTag class? Can you setup event handlers to fill out this other column when the row is updated? Ultimately the cell will contain a fancier display of the tags (clickable icons).
Thank you.
My main class:
package complextableview;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ComplexTableView extends Application {
#Override
public void start(Stage primaryStage) {
ObservableList<Bookmark> bookmarks = FXCollections.observableArrayList();
ObservableList<Tag> tags = FXCollections.observableArrayList();
ObservableList<TagMap> tagMapList = FXCollections.observableArrayList();
TableView<Bookmark> bookmarkTV = new TableView<>(bookmarks);
TableColumn<Bookmark, String> bookmarkNameCol = new TableColumn<>("URL");
// What to put here?
//TableColumn<?, String> bookmarkTagCol = new TableColumn<>("Tags");
bookmarkNameCol.setCellValueFactory(new PropertyValueFactory<>("Name"));
// What to put here?
//bookmarkTagCol.setCellValueFactory(new PropertyValueFactory<>("?"));
bookmarkTV.getColumns().add(bookmarkNameCol);
//bookmarkTV.getColumns().add(bookmarkTagCol);
// Populate data
bookmarks.add(new Bookmark(0, "stackoverflow.com"));
bookmarks.add(new Bookmark(1, "reddit.com"));
tags.add(new Tag(0, "work"));
tags.add(new Tag(1, "home"));
tags.add(new Tag(2, "fun"));
tagMapList.add(new TagMap(0, 0, 0)); // 1st mapping = google & "work"
tagMapList.add(new TagMap(1, 1, 1)); // 2nd mapping = reddit & "home"
tagMapList.add(new TagMap(2, 1, 2)); // 3rd mapping = reddit & "fun"
// Table Output
// URL Tags
// stackoverflow.com 'work'
// reddit.com 'home,fun'
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for ( TagMap tagMapping : tagMapList ){
if ( tagMapping.getBookmarkId() == 1)
sb1.append(tags.get(tagMapping.getTagId()).getString());
else
sb2.append(tags.get(tagMapping.getTagId()).getString());
}
System.out.println(sb1.toString());
System.out.println(sb2.toString());
StackPane root = new StackPane();
root.getChildren().add(bookmarkTV);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("ComplexTableView");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
And the other classes:
Bookmark
package complextableview;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Bookmark {
private final StringProperty name;
private final IntegerProperty id;
public Bookmark() {
id = new SimpleIntegerProperty(this, "id", 0);
name = new SimpleStringProperty(this, "name", "");
}
public Bookmark(Integer id, String name) {
this();
setId(id);
setName(name);
}
public final Integer getId() {return id.get();}
public final void setId(Integer value) {id.set(value);}
public IntegerProperty getIdProperty() {return id;}
public final String getName() {return name.get();}
public final void setName(String value) {name.set(value);}
public StringProperty getNameProperty() {return name;}
}
Tag
package complextableview;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Tag {
public final StringProperty string;
public final IntegerProperty id;
public Tag() {
id = new SimpleIntegerProperty(this, "id", 0);
string = new SimpleStringProperty(this, "string", "");
}
public Tag(Integer id, String string) {
this();
setId(id);
setString(string);
}
public final Integer getId() {return id.get();}
public final void setId(Integer value) {id.set(value);}
public IntegerProperty idProperty() {return id;}
public final String getString() {return string.get();}
public final void setString(String value) {string.set(value);}
public StringProperty stringProperty() {return string;}
}
TagMap
package complextableview;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
public class TagMap {
public final IntegerProperty id;
public final IntegerProperty bookmarkId;
public final IntegerProperty tagId;
public TagMap(){
id = new SimpleIntegerProperty(this, "id", 0);
bookmarkId = new SimpleIntegerProperty(this, "bookmarkId", 0);
tagId = new SimpleIntegerProperty(this, "tagId", 0);
}
public TagMap(Integer id, Integer bmId, Integer tagId) {
this();
setId(id);
setBookmarkId(bmId);
setTagId(tagId);
}
public final Integer getId() {return id.get();}
public final void setId(Integer value) {id.set(value);}
public IntegerProperty idProperty() {return id;}
public final Integer getTagId() {return tagId.get();}
public final void setTagId(Integer value) {tagId.set(value);}
public IntegerProperty tagIdProperty() {return tagId;}
public final Integer getBookmarkId() {return bookmarkId.get();}
public final void setBookmarkId(Integer value) {bookmarkId.set(value);}
public IntegerProperty bookmarkIdProperty() {return bookmarkId;}
}
I have a code from this example
In table the default color of all the text is BLACK.
How can I print the string ""Emma", "Jones", "emma.jones#example.com"" in red
Or, in general, how can I change the color of text of a specific TableCell?
public class TableViewSample 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")
);
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(450);
stage.setHeight(500);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
table.setEditable(true);
TableColumn firstNameCol = new TableColumn("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("firstName"));
TableColumn lastNameCol = new TableColumn("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("lastName"));
TableColumn emailCol = new TableColumn("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("email"));
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty email;
private 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);
}
}
}
I am having problem in populating data from a table in one screen to a Text Field in the other screen. I have two classes FirstClass containing a textbox and a button. On pressing a button a second window is opened containing a Table of values. As the user double clicks a row the value of the second column of the row should be inserted into the textbox of the FirstClass. Code of both the classes is attached. Thanking you in anticipation.
import javafx.application.Application;
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.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class FirstClass extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage primaryStage) {
primaryStage.setTitle("First Class");
GridPane gridpane = new GridPane();
gridpane.setPadding(new Insets(5));
gridpane.setHgap(5);
gridpane.setVgap(5);
final TextField userNameFld = new TextField();
gridpane.add(userNameFld, 1, 1);
Button btn = new Button();
btn.setText("Show Table");
gridpane.add(btn, 1, 3);
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
String a = TableClass.showDialog(primaryStage, true, "Table Window" );
userNameFld.setText(a);
}
});
StackPane root = new StackPane();
Scene scene =new Scene(root, 300, 250);
root.getChildren().addAll(gridpane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class TableClass extends Stage {
private static TableClass dialog;
private static String value = "";
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private Person(String fName, String lName) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
}
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);
}
}
private TableView<Person> table = new TableView<Person>();
private final ObservableList<Person> data =
FXCollections.observableArrayList(
new Person("JACK", "BROWN"),
new Person("JOHN", "VIANNEYS"),
new Person("MICHAEL", "NELSON"),
new Person("WILLIAM", " CAREY")
);
public TableClass(Stage owner, boolean modality, String title) {
super();
initOwner(owner);
Modality m = modality ? Modality.APPLICATION_MODAL : Modality.NONE;
initModality(m);
setOpacity(1);
setTitle(title);
StackPane root = new StackPane();
Scene scene = new Scene(root, 750, 750);
setScene(scene);
GridPane gridpane = new GridPane();
gridpane.setPadding(new Insets(5));
gridpane.setHgap(5);
gridpane.setVgap(5);
TableColumn firstNameCol = new TableColumn("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<Person,String>("firstName")
);
TableColumn lastNameCol = new TableColumn("Last Name");
lastNameCol.setMinWidth(200);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<Person,String>("lastName")
);
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol);
table.setOnMouseClicked(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
if (me.getClickCount() >= 2) {
String srr = table.getItems().get (table.getSelectionModel().getSelectedIndex()).getLastName();
value = srr;
dialog.hide();
}
}
});
gridpane.add(table, 1, 5,1,20 );
root.getChildren().add(gridpane);
}
public static String showDialog(Stage stg, Boolean a , String title){
dialog = new TableClass( stg,a, title);
dialog.show();
return value;
}
}
The quick and easy way (but it introduces coupling between the 2 classes) would be to pass userNameFld to your showDialog method and make it a member of TableClass. You can then change its value from the TableClass class.
A better way would be to bind the value of userNameFld to value.