How to keep track of moving object (rectangle) in javafx? - java

I found this code snippet in a video and I'm trying to integrate it in a ridesharing app. Basically, the rectangle will represent the driver moving on the map and I want to keep track of his location to see when he reaches his destination.
import javafx.animation.AnimationTimer;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Rectangle;
import java.net.URL;
import java.util.ResourceBundle;
public class MapController implements Initializable {
private BooleanProperty wPressed = new SimpleBooleanProperty();
private BooleanProperty aPressed = new SimpleBooleanProperty();
private BooleanProperty sPressed = new SimpleBooleanProperty();
private BooleanProperty dPressed = new SimpleBooleanProperty();
private BooleanBinding keyPressed = wPressed.or(aPressed).or(sPressed).or(dPressed);
private double movementVariable = 2;
private int destinationX = 300, destinationY = 300;
#FXML
private Rectangle shape1;
#FXML
private AnchorPane scene;
#FXML
private Button buttonStartRide;
#FXML
void start(ActionEvent event) {
shape1.setVisible(true);
buttonStartRide.setOpacity(0);
shape1.setLayoutY(200);
shape1.setLayoutX(280);
}
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long timestamp) {
if(wPressed.get()) {
shape1.setLayoutY(shape1.getLayoutY() - movementVariable);
}
if(sPressed.get()){
shape1.setLayoutY(shape1.getLayoutY() + movementVariable);
}
if(aPressed.get()){
shape1.setLayoutX(shape1.getLayoutX() - movementVariable);
}
if(dPressed.get()){
shape1.setLayoutX(shape1.getLayoutX() + movementVariable);
}
}
};
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
movementSetup();
shape1.setVisible(false);
keyPressed.addListener(((observableValue, aBoolean, t1) -> {
if(!aBoolean){
timer.start();
} else {
timer.stop();
}
}));
}
public void movementSetup(){
scene.setOnKeyPressed(e -> {
if(e.getCode() == KeyCode.W) {
wPressed.set(true);
}
if(e.getCode() == KeyCode.A) {
aPressed.set(true);
}
if(e.getCode() == KeyCode.S) {
sPressed.set(true);
}
if(e.getCode() == KeyCode.D) {
dPressed.set(true);
}
});
scene.setOnKeyReleased(e ->{
if(e.getCode() == KeyCode.W) {
wPressed.set(false);
}
if(e.getCode() == KeyCode.A) {
aPressed.set(false);
}
if(e.getCode() == KeyCode.S) {
sPressed.set(false);
}
if(e.getCode() == KeyCode.D) {
dPressed.set(false);
}
});
}
public boolean checkReachedDestination()
{
if((shape1.getLayoutX() == destinationX) && (shape1.getLayoutY() == destinationY))
{
return true;
}
return false;
}
}
I thought that I could maybe do this with a Listener for shape1, however it seems like there is no Listener defined for the type Rectangle. Any thoughts?

Related

How to put a ProcessIndicator in each row of a TableView and indicate task status

I'm trying to do the following in JavaFX:
Have a TableView with multiple rows.
Each row contains columns with text and one Progress/Status column.
When a specific Button is pressed, for each row of the TableView some task should be performed, one row after the other. (e.g. check some data, ...)
While this task is performed, a indeterminate ProgressIndicator shall be shown in the Status column, until the task for this row is finished, then the indicator shows as done.
When all tasks for each row are done, the button can be pressed again to reset the status and execute the tasks again.
I had found some help in this related Stackoverflow post and also here and tried to tweak this as needed but got stuck on some issues:
Currently, each ProgressIndicator for each row is displayed immediately (as indeterminate) when I run the program. How can I only activate them / make them visible for each row one after another once the button is pressed?
Pressing the button again once the fake tasks are done does not restart it. How would I have to modify / rebuild the program to make resets possible?
Does the overall approach make sense?
My current runnable code:
import java.util.Random;
import java.util.concurrent.*;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ProgressIndicatorTableCellTest extends Application {
public void start(Stage primaryStage) {
TableView<TestTask> table = new TableView<>();
Random rng = new Random();
for (int i = 0; i < 3; i++) {
table.getItems().add(new TestTask(rng.nextInt(3000) + 2000, "Test"));
}
TableColumn<TestTask, String> nameCol = new TableColumn("Name");
nameCol.setCellValueFactory(new PropertyValueFactory<TestTask, String>("name"));
nameCol.setPrefWidth(75);
TableColumn<TestTask, Double> progressCol = new TableColumn("Progress");
progressCol.setCellValueFactory(new PropertyValueFactory<TestTask, Double>("progress"));
progressCol.setCellFactory(ProgressIndicatorTableCell.<TestTask>forTableColumn());
table.getColumns().addAll(nameCol, progressCol);
BorderPane root = new BorderPane();
root.setCenter(table);
Button btn = new Button("Start");
btn.setOnAction(actionEvent -> {
ExecutorService executor = Executors.newSingleThreadExecutor();
for (TestTask task : table.getItems()) {
executor.submit(task);
}
});
root.setBottom(btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public static class TestTask extends Task<Void> {
private final int waitTime; // milliseconds
final ReadOnlyStringWrapper name = new ReadOnlyStringWrapper();
public static final int NUM_ITERATIONS = 100;
public TestTask(int waitTime, String name) {
this.waitTime = waitTime;
this.name.set(name);
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
#Override
protected Void call() throws Exception {
this.updateProgress(ProgressIndicator.INDETERMINATE_PROGRESS, 1);
Thread.sleep(waitTime);
this.updateProgress(1, 1);
return null;
}
}
}
class ProgressIndicatorTableCell<S> extends TableCell<S, Double> {
public static <S> Callback<TableColumn<S, Double>, TableCell<S, Double>> forTableColumn() {
return new Callback<TableColumn<S, Double>, TableCell<S, Double>>() {
#Override
public TableCell<S, Double> call(TableColumn<S, Double> param) {
return new ProgressIndicatorTableCell<>();
}
};
}
private final ProgressIndicator progressIndicator;
private ObservableValue observable;
public ProgressIndicatorTableCell() {
this.progressIndicator = new ProgressIndicator();
setGraphic(progressIndicator);
}
#Override
public void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
progressIndicator.progressProperty().unbind();
observable = getTableColumn().getCellObservableValue(getIndex());
if (observable != null) {
progressIndicator.progressProperty().bind(observable);
} else {
progressIndicator.setProgress(item);
}
setGraphic(progressIndicator);
}
}
}
And the current output:
Here is a version that implements your first question. With this requirement, the cell is only a function of the task's state. If it's RUNNING, display an indeterminate progress indicator; if it's SUCCEEDED display a progress indicator with value 1; otherwise, display nothing.
Note the original question is very old and uses a lot of outdated code styles. I've updated accordingly.
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ProgressIndicatorTableCellTest extends Application {
public void start(Stage primaryStage) {
TableView<TestTask> table = new TableView<>();
Random rng = new Random();
for (int i = 0; i < 3; i++) {
table.getItems().add(new TestTask(rng.nextInt(3000) + 2000, "Test"));
}
TableColumn<TestTask, String> nameCol = new TableColumn<>("Name");
nameCol.setCellValueFactory(data -> data.getValue().nameProperty());
nameCol.setPrefWidth(75);
TableColumn<TestTask, Worker.State> progressCol = new TableColumn<>("Progress");
progressCol.setCellValueFactory(data -> data.getValue().stateProperty());
progressCol.setCellFactory(col -> new ProgressIndicatorTableCell<>());
table.getColumns().addAll(nameCol, progressCol);
BorderPane root = new BorderPane();
root.setCenter(table);
Button btn = new Button("Start");
btn.setOnAction(actionEvent -> {
ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
});
for (TestTask task : table.getItems()) {
executor.submit(task);
}
});
root.setBottom(btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public static class TestTask extends Task<Void> {
private final int waitTime; // milliseconds
final ReadOnlyStringWrapper name = new ReadOnlyStringWrapper();
public static final int NUM_ITERATIONS = 100;
public TestTask(int waitTime, String name) {
this.waitTime = waitTime;
this.name.set(name);
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
#Override
protected Void call() throws Exception {
this.updateProgress(ProgressIndicator.INDETERMINATE_PROGRESS, 1);
Thread.sleep(waitTime);
this.updateProgress(1, 1);
return null;
}
}
}
class ProgressIndicatorTableCell<S> extends TableCell<S, Worker.State> {
private final ProgressIndicator progressIndicator = new ProgressIndicator();
#Override
protected void updateItem(Worker.State state, boolean empty) {
super.updateItem(state, empty);
if (state == Worker.State.SUCCEEDED) {
progressIndicator.setProgress(1);
setGraphic(progressIndicator);
} else if (state == Worker.State.RUNNING) {
progressIndicator.setProgress(-1);
setGraphic(progressIndicator);
} else {
setGraphic(null);
}
}
}
To allow for "restarting", you should use a Service instead of just a Task. This version will allow for a restart if the button is pressed multiple times, returning everything to the initial state before proceeding.
This version also factors the processing work out of the model class, which is desirable for properly assigning responsibilities to classes:
Item.java:
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleObjectProperty;
public class Item {
public enum State {WAITING, PROCESSING, READY}
final ReadOnlyStringWrapper name = new ReadOnlyStringWrapper();
private final ObjectProperty<State> state = new SimpleObjectProperty<>(State.WAITING);
public Item(String name) {
this.name.set(name);
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
public State getState() {
return state.get();
}
public ObjectProperty<State> stateProperty() {
return state;
}
public void setState(State state) {
this.state.set(state);
}
}
ProcessManager.java:
import javafx.application.Platform;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import java.util.List;
import java.util.Random;
public class ProcessManager {
private final List<Item> items;
private Random rng = new Random();
private Service<Void> service = new Service<>() {
#Override
protected Task<Void> createTask() {
return new Task<>() {
#Override
protected Void call() throws Exception {
for (Item task: items) {
try {
Platform.runLater(() -> task.setState(Item.State.PROCESSING));
Thread.sleep(2000 + rng.nextInt(3000));
Platform.runLater(() -> task.setState(Item.State.READY));
} catch (InterruptedException exc) {
Thread.currentThread().interrupt();
}
if (isCancelled()) {
Platform.runLater(() -> task.setState(Item.State.WAITING));
break;
}
}
return null;
}
};
}
};
public ProcessManager(List<Item> items) {
this.items = items ;
service.setOnCancelled(e -> items.forEach(task -> task.setState(Item.State.WAITING)));
}
public void process() {
service.restart();
}
}
and the application:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ProgressIndicatorTableCellTest extends Application {
public void start(Stage primaryStage) {
ObservableList<Item> tasks = FXCollections.observableArrayList();
ProcessManager processManager = new ProcessManager(tasks);
TableView<Item> table = new TableView<>();
for (int i = 0; i < 3; i++) {
Item task = new Item("Item " + (i + 1));
tasks.add(task);
}
table.setItems(tasks);
TableColumn<Item, String> nameCol = new TableColumn<>("Name");
nameCol.setCellValueFactory(data -> data.getValue().nameProperty());
nameCol.setPrefWidth(75);
TableColumn<Item, Item.State> progressCol = new TableColumn<>("Progress");
progressCol.setCellValueFactory(data -> data.getValue().stateProperty());
progressCol.setCellFactory(col -> new TableCell<>() {
private final ProgressIndicator indicator = new ProgressIndicator();
#Override
protected void updateItem(Item.State state, boolean empty) {
super.updateItem(state, empty);
if (state == Item.State.PROCESSING) {
indicator.setProgress(-1);
setGraphic(indicator);
} else if (state == Item.State.READY) {
indicator.setProgress(1);
setGraphic(indicator);
} else {
setGraphic(null);
}
}
});
table.getColumns().addAll(nameCol, progressCol);
BorderPane root = new BorderPane();
root.setCenter(table);
Button btn = new Button("Start");
btn.setOnAction(actionEvent -> processManager.process());
root.setBottom(btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

how to add completed task functionality in Java FXML in to do list

I am making a to do list with java FXML using file reader and writer and scene builder. I have been trying to add a completed task function but tried many ways and am unable to figure out something which will work for me. I tried making a separate list where I keep my completed task but its still not working out for me. At this moment I have tried a lot by myself and am willing to go for another for another method to add this function. I am using To Do Date Class which is using to do Item class.
I have tried using it as predicate of filtered list and type casting accordingly but it hasn't worked out for me either.Rest of code works perfectly fine.
controller is:
package todolist;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.function.Predicate;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleButton;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.util.Callback;
/**
*
* #author Pc Planet
*/
public class FXMLDocumentController {
private List<ToDoItem> todoItems;
#FXML
private ListView<ToDoItem> todoListView;
#FXML
private TextArea itemDetailsTextArea;
#FXML
private Label deadlineLabel;
#FXML
private BorderPane mainBorderPane;
#FXML
private ContextMenu listContextMenu;
#FXML
private ToggleButton filterToggleButton;
#FXML
private Button exit,ADD;
private FilteredList<ToDoItem> filteredList;
private Predicate<ToDoItem> wantAllItems;
private Predicate<ToDoItem> wantTodaysItems;
private Predicate<ToDoItem> uncompleted;
private ObservableList<ToDoItem> completed;
public void initialize() {
// delete
listContextMenu = new ContextMenu();
MenuItem deleteMenuItem = new MenuItem("Delete");
deleteMenuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
ToDoItem item = todoListView.getSelectionModel().getSelectedItem();
deleteItem(item);
}
});
// Completed
listContextMenu = new ContextMenu();
MenuItem completedMenuItem = new MenuItem("Mark as complete");
completedMenuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
ToDoItem item = todoListView.getSelectionModel().getSelectedItem();
completedItem(item);
}
});
listContextMenu.getItems().addAll(deleteMenuItem);
listContextMenu.getItems().addAll(completedMenuItem);
//change
todoListView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<ToDoItem>() {
#Override
public void changed(ObservableValue<? extends ToDoItem> observable, ToDoItem oldValue, ToDoItem newValue) {
if(newValue != null) {
ToDoItem item = todoListView.getSelectionModel().getSelectedItem();
itemDetailsTextArea.setText(item.getDetails());
DateTimeFormatter df = DateTimeFormatter.ofPattern("MMMM d, yyyy"); // "d M yy");
deadlineLabel.setText(df.format(item.getDeadline()));
}
}
});
wantAllItems = (ToDoItem todoItem) -> true;
wantTodaysItems = (ToDoItem todoItem) -> (todoItem.getDeadline().equals(LocalDate.now()));
filteredList = new FilteredList<ToDoItem>(ToDoData.getInstance().getTodoItems(), wantAllItems);
// list sort
SortedList<ToDoItem> sortedList = new SortedList<ToDoItem>(filteredList,
new Comparator<ToDoItem>() {
#Override
public int compare(ToDoItem o1, ToDoItem o2) {
return o1.getDeadline().compareTo(o2.getDeadline());
}
});
todoListView.setItems(sortedList);
todoListView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
todoListView.getSelectionModel().selectFirst();
todoListView.setCellFactory(new Callback<ListView<ToDoItem>, ListCell<ToDoItem>>() {
#Override
public ListCell<ToDoItem> call(ListView<ToDoItem> param) {
ListCell<ToDoItem> cell = new ListCell<ToDoItem>() {
#Override
protected void updateItem(ToDoItem item, boolean empty) {
super.updateItem(item, empty);
if(empty) {
setText(null);
} else {
setText(item.getShortDescription());
if(item.getDeadline().isBefore(LocalDate.now().plusDays(1))) {
setTextFill(Color.RED);
} else {
setTextFill(Color.GREEN);
}
}
}
};
cell.emptyProperty().addListener(
(obs, wasEmpty, isNowEmpty) -> {
if(isNowEmpty) {
cell.setContextMenu(null);
} else {
cell.setContextMenu(listContextMenu);
}
});
return cell;
}
});
}
#FXML
public void showNewItemDialog() {
Dialog<ButtonType> dialog = new Dialog<>();
dialog.initOwner(mainBorderPane.getScene().getWindow());
dialog.setTitle("Add New Todo Item");
dialog.setHeaderText("Use this dialog to create a new todo item");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("todoitemdialog.fxml"));
try {
dialog.getDialogPane().setContent(fxmlLoader.load());
} catch(IOException e) {
System.out.println("Couldn't load the dialog");
e.printStackTrace();
return;
}
dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
Optional<ButtonType> result = dialog.showAndWait();
if(result.isPresent() && result.get() == ButtonType.OK) {
DialogController controller = fxmlLoader.getController();
ToDoItem newItem = controller.processResults();
todoListView.getSelectionModel().select(newItem);
}
}
#FXML
public void completedtasks(ActionEvent event){
}
#FXML
public void handleKeyPressed(KeyEvent keyEvent) {
ToDoItem selectedItem = todoListView.getSelectionModel().getSelectedItem();
if(selectedItem != null) {
if(keyEvent.getCode().equals(KeyCode.DELETE)) {
deleteItem(selectedItem);}
else{
completedItem(selectedItem);
}
}
}
public void handleClickListView() {
ToDoItem item = todoListView.getSelectionModel().getSelectedItem();
itemDetailsTextArea.setText(item.getDetails());
deadlineLabel.setText(item.getDeadline().toString());
}
public void deleteItem(ToDoItem item) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Delete Todo Item");
alert.setHeaderText("Delete item: " + item.getShortDescription());
alert.setContentText("Are you sure? Press OK to confirm or cancel to Back out.");
Optional<ButtonType> result = alert.showAndWait();
if(result.isPresent() && (result.get() == ButtonType.OK)) {
ToDoData.getInstance().deleteTodoItem(item);
}
}
public void completedItem(ToDoItem item) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Mark as Completed");
alert.setHeaderText("Completed task: " + item.getShortDescription());
alert.setContentText("Are you sure? Press OK to confirm or cancel to Back out.");
Optional<ButtonType> result = alert.showAndWait();
if(result.isPresent() && (result.get() == ButtonType.OK)) {
ToDoData.getInstance().completed(item);
}
}
#FXML
public void wantTodaysItems(){
ToDoItem selectedItem = todoListView.getSelectionModel().getSelectedItem();
filteredList.setPredicate(wantTodaysItems);
if(filteredList.isEmpty()) {
itemDetailsTextArea.clear();
deadlineLabel.setText("");
} else if(filteredList.contains(selectedItem)) {
todoListView.getSelectionModel().select(selectedItem);
} else {
todoListView.getSelectionModel().selectFirst();
}
}
#FXML
public void wantAllItems(){
ToDoItem selectedItem = todoListView.getSelectionModel().getSelectedItem();
filteredList.setPredicate(wantAllItems);
if(filteredList.isEmpty()) {
itemDetailsTextArea.clear();
deadlineLabel.setText("");
} else if(filteredList.contains(selectedItem)) {
todoListView.getSelectionModel().select(selectedItem);
} else {
todoListView.getSelectionModel().selectFirst();
}
}
#FXML
public void handleExit() {
Platform.exit();
}
}
ToDoData class is:
package todolist;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class ToDoData {
private static ToDoData instance = new ToDoData();
private static String filename = "TodoListItems.txt";
private ObservableList<ToDoItem> todoItems;
private ObservableList<ToDoItem> completed;
private DateTimeFormatter formatter;
public static ToDoData getInstance() {
return instance;
}
private ToDoData() {
formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
}
public ObservableList<ToDoItem> getTodoItems() {
return todoItems;
}
public void addTodoItem(ToDoItem item) {
todoItems.add(item);
}
public void loadTodoItems() throws IOException {
todoItems = FXCollections.observableArrayList();
Path path = Paths.get(filename);
BufferedReader br = Files.newBufferedReader(path);
String input;
try {
while ((input = br.readLine()) != null) {
String[] itemPieces = input.split("\t");
String shortDescription = itemPieces[0];
String details = itemPieces[1];
String dateString = itemPieces[2];
LocalDate date = LocalDate.parse(dateString, formatter);
ToDoItem todoItem = new ToDoItem(shortDescription, details, date);
todoItems.add(todoItem);
}
} finally {
if(br != null) {
br.close();
}
}
}
public void storeTodoItems() throws IOException {
Path path = Paths.get(filename);
BufferedWriter bw = Files.newBufferedWriter(path);
try {
Iterator<ToDoItem> iter = todoItems.iterator();
while(iter.hasNext()) {
ToDoItem item = iter.next();
bw.write(String.format("%s\t%s\t%s",
item.getShortDescription(),
item.getDetails(),
item.getDeadline().format(formatter)));
bw.newLine();
}
} finally {
if(bw != null) {
bw.close();
}
}
}
public void deleteTodoItem(ToDoItem item) {
todoItems.remove(item);
}
public void completed(ToDoItem item){
completed.add(item);
}
public ObservableList <ToDoItem> completed(){
return completed;
}
}
todoItem class is:
package todolist;
import java.time.LocalDate;
public class ToDoItem {
private String shortDescription;
private String details;
private LocalDate deadline;
public ToDoItem(String shortDescription, String details, LocalDate deadline) {
this.shortDescription = shortDescription;
this.details = details;
this.deadline = deadline;
}
public String getShortDescription() {
return shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
public LocalDate getDeadline() {
return deadline;
}
public void setDeadline(LocalDate deadline) {
this.deadline = deadline;
}
}
This answer is assuming I understand you correctly. In this example, I use a FilteredList on the TableView, and I used the FilteredList's Predicate to show the data in the TableView based on the Button that is pressed. I altered the answer from here.
KeyCode 1
This code allows the TableView to update when the CheckBox values changes.
todoItem -> new Observable[] { todoItem.completeProperty()}
Key Code 2
This code allows the FilteredList to set the TableView's data based on the Button that is pressed.
flToDoItems.setPredicate((todoItem) -> {
return todoItem.getComplete();
});
Main
import java.time.LocalDate;
import java.util.Arrays;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class App extends Application
{
final TableView<ToDoItem> selectionTableView = new TableView<>();
private final ObservableList<ToDoItem> toDoItems = FXCollections.observableList(
Arrays.asList(
new ToDoItem("Task 1", "This is Task 1", LocalDate.now().plusMonths(1)),
new ToDoItem("Task 2", "This is Task 2", LocalDate.now().plusMonths(2)),
new ToDoItem("Task 3", "This is Task 3", LocalDate.now().plusMonths(3)),
new ToDoItem("Task 4", "This is Task 4", LocalDate.now().plusMonths(4)),
new ToDoItem("Task 5", "This is Task 5", LocalDate.now().plusMonths(5))
),
todoItem -> new Observable[] { todoItem.completeProperty()}//This is needed for automatic updates in the TableView!!!!
);
final FilteredList<ToDoItem> flToDoItems = new FilteredList(toDoItems, p -> true);
public static void main(String[] args)
{
launch();
}
#Override
public void start(Stage stage)
{
final TableView<ToDoItem> todoListSelectionTableView = createTodoListSelectionTableView();
todoListSelectionTableView.setItems(flToDoItems);
Button btnAllTasks = new Button("All");
btnAllTasks.setOnAction((t) -> {
flToDoItems.setPredicate((todoItem) -> {
return true;
});
});
Button btnCompleteTasks = new Button("Complete");
btnCompleteTasks.setOnAction((t) -> {
flToDoItems.setPredicate((todoItem) -> {
return todoItem.getComplete();
});
});
Button btnIncompleteTask = new Button("Incomplete");
btnIncompleteTask.setOnAction((t) -> {
flToDoItems.setPredicate((todoItem) -> {
return !todoItem.getComplete();
});
});
VBox root = new VBox(new HBox(btnAllTasks, btnIncompleteTask, btnCompleteTasks), todoListSelectionTableView);
Scene scene = new Scene(root, 500, 500);
stage.setScene(scene);
stage.show();
}
private TableView<ToDoItem> createTodoListSelectionTableView() {
selectionTableView.setPrefSize(440, 180);
TableColumn<ToDoItem, String> shortDescriptionColumn = new TableColumn<>("Short Description");
shortDescriptionColumn.setCellValueFactory(cd -> cd.getValue().shortDescriptionProperty());
selectionTableView.getColumns().add(shortDescriptionColumn);
TableColumn<ToDoItem, String> detailsColumn = new TableColumn<>("Details");
detailsColumn.setCellValueFactory(cd -> cd.getValue().detailsProperty());
selectionTableView.getColumns().add(detailsColumn);
TableColumn<ToDoItem, LocalDate> deadlineColumn = new TableColumn<>("Deadline");
deadlineColumn.setCellValueFactory(cd -> cd.getValue().deadlineProperty());
selectionTableView.getColumns().add(deadlineColumn);
TableColumn<ToDoItem, Boolean> completeColumn = new TableColumn<>("Complete");
completeColumn.setCellValueFactory(cd -> cd.getValue().completeProperty());
completeColumn.setCellFactory(CheckBoxTableCell.forTableColumn(completeColumn));
selectionTableView.getColumns().add(completeColumn);
selectionTableView.setEditable(true);
return selectionTableView;
}
}
ToDoItem
import java.time.LocalDate;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class ToDoItem {
private final StringProperty shortDescription;
private final StringProperty details;
private final ObjectProperty<LocalDate> deadline;
private final BooleanProperty complete;
public ToDoItem(String shortDescription, String details, LocalDate deadline) {
this.shortDescription = new SimpleStringProperty(shortDescription);
this.details = new SimpleStringProperty(details);
this.deadline = new SimpleObjectProperty(deadline);
this.complete = new SimpleBooleanProperty(false);
}
public String getShortDescription() {
return shortDescription.get();
}
public void setShortDescription(String shortDescription) {
this.shortDescription.set(shortDescription);
}
public StringProperty shortDescriptionProperty()
{
return this.shortDescription;
}
public String getDetails() {
return details.get();
}
public void setDetails(String details) {
this.details.set(details);
}
public StringProperty detailsProperty()
{
return this.details;
}
public LocalDate getDeadline() {
return deadline.get();
}
public void setDeadline(LocalDate deadline) {
this.deadline.set(deadline);
}
public ObjectProperty<LocalDate> deadlineProperty()
{
return this.deadline;
}
public void setComplete(boolean complete)
{
this.complete.set(complete);
}
public boolean getComplete()
{
return this.complete.get();
}
public BooleanProperty completeProperty()
{
return this.complete;
}
}
Output

how can i fix my progress and seek slider to work for all media?

so im making a media player in javafx (eclipse) and i used to slider as a progress bar and scrubber but for some reason the sider only shows the progress for the first media , as soon as i press next the progress doesnt show anymore.
i can still seek to the position i was to but progress wont show
Here is the code for the main class
i have a class play List item which holds the names for all the files in a given directory
package application;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.util.Duration;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.input.MouseEvent;
import javafx.scene.media.Media;
import javafx.event.EventHandler;
public class MainController implements Initializable {
#FXML
private MediaView mv;
private MediaPlayer mp;
private Media me;
#FXML
private Label title;
#FXML
Slider volslider;
int pointer = 0;
#FXML
Slider progBar;
#Override
public void initialize(URL location, ResourceBundle resources) {
String path = new File("src/media/" + application.Playlist.playnext(pointer)).getAbsolutePath();
me = new Media(new File(path).toURI().toString());
mp = new MediaPlayer(me);
mv.setMediaPlayer(mp);
// mp.setAutoPlay(true);
DoubleProperty width = mv.fitWidthProperty();
DoubleProperty height = mv.fitHeightProperty();
width.bind(Bindings.selectDouble(mv.sceneProperty(), "width"));
height.bind(Bindings.selectDouble(mv.sceneProperty(), "height"));
mp.setOnReady(new Runnable() {
#Override
public void run() {
volslider.setValue(mp.getVolume() * 100);
volslider.valueProperty().addListener(new InvalidationListener() {
#Override
public void invalidated(Observable observable) {
mp.setVolume(volslider.getValue() / 100);
}
});
mp.currentTimeProperty().addListener(new ChangeListener<Duration>() {
#Override
public void changed(ObservableValue<? extends Duration> observable, Duration oldValue,
Duration newValue) {
progBar.setValue((newValue.toSeconds() / mp.getTotalDuration().toSeconds()) * 100);
}
});
progBar.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
mp.seek(Duration.seconds((progBar.getValue() / 100) * mp.getTotalDuration().toSeconds()));
}
});
}
});
}
public void play(ActionEvent event) {
mp.play();
}
public void pause(ActionEvent event) {
mp.pause();
}
public void speedup(ActionEvent event) {
mp.setRate(2);
}
public void normalspeed(ActionEvent event) {
mp.setRate(1);
}
public void slowmo(ActionEvent event) {
mp.setRate(0.5);
}
public void reload(ActionEvent event) {
progBar.setValue(0);
mp.seek(mp.getStartTime());
mp.stop();
}
public void end(ActionEvent event) {
progBar.setValue(100);
mp.seek(mp.getTotalDuration());
mp.stop();
}
public void next(ActionEvent event) {
progBar.setValue(0);
mp.seek(mp.getTotalDuration());
mp.stop();
pointer++;
pointer = application.Playlist.checkrange(pointer);
String path = new File("src/media/" + application.Playlist.playnext(pointer)).getAbsolutePath();
me = new Media(new File(path).toURI().toString());
mp = new MediaPlayer(me);
mv.setMediaPlayer(mp);
mp.play();
}
public void previous(ActionEvent event) {
// progBar.setValue(0);
mp.seek(mp.getTotalDuration());
mp.stop();
pointer--;
pointer = application.Playlist.checkrange(pointer);
String path = new File("src/media/" + application.Playlist.playnext(pointer)).getAbsolutePath();
me = new Media(new File(path).toURI().toString());
mp = new MediaPlayer(me);
mv.setMediaPlayer(mp);
mp.play();
}
}
In your next() method you create a new MediaPlayer but you don't update the reference to your currentTime property which has been bound in the initialize function. If you want to change that, unbind the old MediaPlayer's currentTime property and then bind it to your new MediaPlayer instance in next().

How to remove double click editing for ListCell

I have a ListView with the languages one employee can speak. It uses custom ListCells implemented with the help of setCellFactory. I have a ListCellFactory class where I stored the call for my custom ListCell. In my LanguageListCell (my custom ListCell class) I have a ContextMenu in which I have a MenuItem. The MenuItem fires an event to edit the selected ListCell. The only problem I have encountered in my project is having this double click editing. Whenever I click more than once (when the Cell is not selected) or once (when the Cell is selected) the startEdit gets called. What I want to accomplish is remove this double click editing. But what I have managed to write as a code causes too many problems. For example, when I click on the TextField which is used for the editing, the cancelEdit method is called. And, basically, I can't even click on the TextField without removing it.
See my code for reference
This is the LanguageListCell class
package application;
import javafx.beans.binding.Bindings;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
public class LanguageListCell extends ListCell<String> {
private TextField textField;
LanguageListCell cell = this;
int i = 0;
public LanguageListCell(ListView<String> languages) {
ContextMenu contextMenu = new ContextMenu();
cell.setEditable(true);
MenuItem editItem = new MenuItem();
editItem.textProperty().bind(Bindings.format("Edit \"%s\"", cell.itemProperty()));
editItem.setOnAction(event -> {
languages.edit(cell.getIndex());
//cell.startEdit();
});
contextMenu.getItems().add(editItem);
cell.textProperty().bind(cell.itemProperty());
cell.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
if (isNowEmpty) {
cell.setContextMenu(null);
} else {
if (getString() != "Add") {
cell.setContextMenu(contextMenu);
}
}
});
//This is what I have tried but i get the issue with cancelEdit
//where when I press the TextField it cancels the editing
cell.addEventFilter(MouseEvent.MOUSE_PRESSED, (MouseEvent e) -> {
if (e.getButton().equals(MouseButton.PRIMARY)) {
if (cell.isSelected() && e.getClickCount() >= 1) {
languages.getSelectionModel().clearSelection();
languages.getSelectionModel().select(cell.getItem());
e.consume();
}
if (e.getClickCount() > 1) {
e.consume();
}
}
});
}
public String getString() {
return getItem() == null ? "" : getItem().toString();
}
#Override
public void startEdit() {
super.startEdit();
if (textField == null) {
createTextField();
}
setText(null);
setGraphic(textField);
textField.selectAll();
textField.requestFocus();
}
#Override
public void cancelEdit() {
super.cancelEdit();
setGraphic(null);
setText(getItem());
textField = null;
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
cell.textProperty().unbind();
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(getGraphic());
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
if (textField.getText().trim() != "" && textField.getText().trim().length() > 3) {
commitEdit(textField.getText());
setGraphic(null);
setGraphic(getGraphic());
}
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
}
});
}
}
This is the LanguageCellFactory class
package application;
import javafx.beans.binding.Bindings;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.Pane;
import javafx.util.Callback;
import application.LanguageListCell;
public class LanguageCellFactory implements Callback<ListView<String>, ListCell<String>> {
public LanguageCellFactory()
{
}
#Override
public ListCell<String> call(ListView<String> languages)
{
return new LanguageListCell(languages);
}
}
And this is the Main class
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.control.ListView;
import java.util.ArrayList;
import application.LanguageCellFactory;
public class Main extends Application {
private ListView<String> languages;
private Stage stage;
#Override
public void init()
{
}
public void start(Stage primaryStage) {
try {
Pane root = new Pane();
Scene scene = new Scene(root,800,600);
ArrayList<String> list_items = new ArrayList<String>();
list_items.add("Russian");
list_items.add("English");
languages = new ListView<String>();
languages.relocate(150, 62);
languages.getItems().addAll(list_items);
root.getChildren().add(languages);
//languages.setEditable(true);
languages.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
languages.setCellFactory(new LanguageCellFactory());
primaryStage.setScene(scene);
primaryStage.setTitle("First JavaFX App");
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
If someone wants to know how to fix this, I tried removing the editing events for the ListCell and provided my own "editing" behaviour for the cells and now it is working
Here is the modified version of the LanguageListCell class
package application;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
public class LanguageListCell extends ListCell<String> {
private TextField textField;
LanguageListCell cell = this;
int i = 0;
private boolean textfield_state = false;
ContextMenu contextMenu = new ContextMenu();
MenuItem editItem = new MenuItem();
public LanguageListCell(ListView<String> languages) {
editItem.textProperty().bind(Bindings.format("Edit \"%s\"", cell.itemProperty()));
contextMenu.getItems().add(editItem);
cell.textProperty().bind(cell.itemProperty());
cell.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
if (isNowEmpty) {
cell.setContextMenu(null);
} else {
if (getString() != "Add") {
cell.setContextMenu(contextMenu);
}
}
});
}
public String getString() {
return getItem() == null ? "" : getItem().toString();
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
cell.textProperty().unbind();
//String thecellValue = getString();
if (empty) {
setText(null);
setGraphic(null);
} else {
if (textfield_state) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(getGraphic());
editItem.setOnAction(event -> {
textfield_state = true;
if(textField == null)
{
createTextField();
}
setText(null);
setGraphic(textField);
textField.requestFocus();
textField.selectAll();
});
}
}
}
private void createTextField() {
textField = new TextField(getString());
String CellValue = getString();
textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
if (textField.getText().trim() != "" && textField.getText().trim().length() > 3) {
setText(textField.getText().trim());
setGraphic(null);
}
} else if (t.getCode() == KeyCode.ESCAPE) {
//cancelEdit();
setGraphic(null);
setText(CellValue);
textField = null;
}
}
});
textField.focusedProperty().addListener((obs, isNotFocused, isFocused) -> {
if(isFocused)
{
LanguageListCell parent = (LanguageListCell) textField.getParent();
ListView<String> list = parent.getListView();
list.getSelectionModel().clearSelection();
list.getSelectionModel().select(parent.getIndex());
}
else
{
setGraphic(null);
setText(CellValue);
textField = null;
}
});
}
}

TreeTableView JavaFX 8: I need to make one of columns to use TextFIeld and ChoiceBox when editing

I have TreeTableView with 2 columns, so I want to be able something like that:
user double click in cell -> Someclass.getType() returns type of editing field ->in cell I see this type of editing field(TextField or ChoiceBox)
wnen I need to use TextField only, i can use someshing like that
TreeColumn1.setCellFactory(TextFieldTreeTableCell.forTreeTableColumn());
TreeColumn1.setOnEditCommit(firstColumnCommitHandler);
commitHandler:
private EventHandler<TreeTableColumn.CellEditEvent<SomeClass, String>> firstColumnCommitHandler = event -> {
final SomeClass item = event.getRowValue().getValue();
item.setVariable(event.getNewValue());
};
but i need different types, and have no idea howto do this
For this you need to implement the table cell yourself, and display the appropriate components when you go in and out of editing state. Here's a basic idea. The ChoiceBoxs look odd, you may need to work with some CSS to get them looking correct. In this example, if the box in the first column is checked, the second column will use a ChoiceBox for editing; otherwise it will use a TextField.
import java.util.function.Function;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TableWithVaryingEditor extends Application {
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
table.setEditable(true);
IntStream.rangeClosed(1, 20).mapToObj(i -> new Item("Item "+i)).forEach(table.getItems()::add);
TableColumn<Item, Boolean> fixedCol = column("Fixed", Item::fixedProperty);
table.getColumns().add(fixedCol);
fixedCol.setCellFactory(CheckBoxTableCell.forTableColumn(fixedCol));
TableColumn<Item, String> nameCol = column("Name", Item::nameProperty);
table.getColumns().add(nameCol);
nameCol.setCellFactory(col -> new TableCell<Item, String>() {
private TextField textField = new TextField();
private ChoiceBox<String> choice = new ChoiceBox<>();
private boolean ignoreChoiceBoxChange = false ;
// anonymous constructor:
{
choice.valueProperty().addListener((obs, oldValue, newValue) -> {
if (! ignoreChoiceBoxChange) {
commitEdit(newValue);
}
});
choice.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (! isNowFocused) {
cancelEdit();
}
});
choice.showingProperty().addListener((obs, wasShowing, isNowShowing) -> {
if (! isNowShowing) {
cancelEdit();
}
});
textField.setOnAction(e -> commitEdit(textField.getText()));
textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (! isNowFocused) {
cancelEdit();
}
});
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (isEditing()) {
updateEditor();
} else {
updateText();
}
}
#Override
public void startEdit() {
super.startEdit();
updateEditor();
}
#Override
public void cancelEdit() {
super.cancelEdit();
updateText();
}
#Override
public void commitEdit(String item) {
super.commitEdit(item);
updateText();
}
private void updateEditor() {
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
int index = getIndex();
Item item = getTableView().getItems().get(index);
if (item.isFixed()) {
ignoreChoiceBoxChange = true ;
choice.getItems().setAll(getItem(), "Choice 1", "Choice 2");
choice.getSelectionModel().select(getItem());
setGraphic(choice);
choice.show();
ignoreChoiceBoxChange = false ;
} else {
textField.setText(getItem());
setGraphic(textField);
}
}
private void updateText() {
setContentDisplay(ContentDisplay.TEXT_ONLY);
if (isEmpty()) {
setText(null);
} else {
setText(getItem());
}
}
});
primaryStage.setScene(new Scene(new BorderPane(table), 600, 400));
primaryStage.show();
}
private <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
return col ;
}
public static class Item {
private final BooleanProperty fixed = new SimpleBooleanProperty();
private final StringProperty name = new SimpleStringProperty();
public Item(String name) {
setName(name);
}
public final BooleanProperty fixedProperty() {
return this.fixed;
}
public final boolean isFixed() {
return this.fixedProperty().get();
}
public final void setFixed(final boolean fixed) {
this.fixedProperty().set(fixed);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
}
public static void main(String[] args) {
launch(args);
}
}

Categories