Disabling dates in DatePicker without enabling previously disabled dates - java

import java.time.DayOfWeek;
import java.time.LocalDate;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.scene.layout.VBox;
public class Example extends Application {
#Override public void start(Stage stage) {
VBox container = new VBox();
DatePicker datePicker = new DatePicker();
disableSomeDates(datePicker);
Button disableMondaysButton = new Button("No Mondays!");
disableMondaysButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
disableSomeMoreDates(datePicker);
}
});
container.getChildren().add(datePicker);
container.getChildren().add(disableMondaysButton);
Scene scene = new Scene(container);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
public void disableSomeDates(DatePicker datePicker) {
datePicker.setDayCellFactory(param -> new DateCell() {
#Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
//Disables dates before current date
setDisable(empty || date.compareTo(LocalDate.now()) < 0 );
}
});
}
public void disableSomeMoreDates(DatePicker datePicker) {
datePicker.setDayCellFactory(param -> new DateCell() {
#Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
//Disables mondays
setDisable(empty || date.getDayOfWeek() == DayOfWeek.MONDAY);
}
});
}
}
In this example code I create a DatePicker and disable some dates (dates before today). Then by pressing the button it should disable Mondays and thus we should have all dates before today and all mondays disabled. In this case we'll end up with only mondays disabled.
How do I make it so that the button disables mondays without re-enabling dates before today?

I'd recommend using a single cell factory, generating cells which observe properties that can then be changed.
E.g.:
import java.time.DayOfWeek;
import java.time.LocalDate;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Example extends Application {
#Override public void start(Stage stage) {
BooleanProperty mondaysDisabled = new SimpleBooleanProperty(false);
VBox container = new VBox();
DatePicker datePicker = new DatePicker();
datePicker.setDayCellFactory(dp -> new DateCell() {
{
mondaysDisabled.addListener((obs, mondaysWereDisabled, mondaysAreNowDisabled)
-> updateDisabledStatus());
}
#Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
updateDisabledStatus();
}
private void updateDisabledStatus() {
if (isEmpty()) {
setDisable(true);
} else {
LocalDate date = getItem();
if (date.isBefore(LocalDate.now())) {
setDisable(true);
} else {
if (mondaysDisabled.get() && date.getDayOfWeek() == DayOfWeek.MONDAY) {
setDisable(true);
} else {
setDisable(false);
}
}
}
}
});
Button disableMondaysButton = new Button("No Mondays!");
disableMondaysButton.setOnAction(event -> mondaysDisabled.set(true));
container.getChildren().add(datePicker);
container.getChildren().add(disableMondaysButton);
Scene scene = new Scene(container);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
For something of a more modular approach, you could keep an observable list of filters to check. E.g.
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.function.Predicate;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Example extends Application {
#Override public void start(Stage stage) {
ObservableList<Predicate<LocalDate>> dayFilters = FXCollections.observableArrayList();
dayFilters.add(date -> date != null);
dayFilters.add(date -> ! date.isBefore(LocalDate.now()));
VBox container = new VBox();
DatePicker datePicker = new DatePicker();
datePicker.setDayCellFactory(dp -> new DateCell() {
{
dayFilters.addListener((Change<? extends Predicate<LocalDate>> change) -> updateDisabledStatus());
}
#Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
updateDisabledStatus();
}
private void updateDisabledStatus() {
setDisable(false);
for (Predicate<LocalDate> check : dayFilters) {
if (! check.test(getItem())) {
setDisable(true);
break ;
}
}
}
});
Button disableMondaysButton = new Button("No Mondays!");
disableMondaysButton.setOnAction(event -> dayFilters.add(date -> date.getDayOfWeek() != DayOfWeek.MONDAY));
container.getChildren().add(datePicker);
container.getChildren().add(disableMondaysButton);
Scene scene = new Scene(container);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}

Related

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 to get the Cell (of a ListView) under the mouse pointer?

I wrote a thread that checks constantly if the mouse is over a ListView, because I want to show a Popup containing info about the cell I point with the mouse.
So no problem to check if the mouse is over the ListView.
But how do I check if the mouse is over a certain cell since I cannot use ListCell.localToScreen(ListCell.getBoundsInLocal()); to get the cell coordinates on screen?
I prefer not to use ListCell event such as onMouseEntered.
Either register handlers for mouseEntered and mouseExited events on each ListCell, or observe the ListCell's hoverProperty. Here's an example using the second method:
import java.util.stream.IntStream;
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Popup;
import javafx.stage.Stage;
import javafx.util.Duration;
public class PopupOnListCellHover extends Application {
private Popup popup ;
private Node popupContent ;
private Label titleLabel ;
private Label detailsLabel ;
private FadeTransition fadeOut ;
#Override
public void start(Stage primaryStage) {
ListView<Item> listView = new ListView<>();
popup = new Popup();
titleLabel = new Label();
titleLabel.setStyle("-fx-font-size: 1.5em ; -fx-font-weight: bold;");
detailsLabel = new Label();
popupContent = new VBox(10, titleLabel, detailsLabel);
popupContent.setStyle("-fx-background-color: -fx-background; "+
"-fx-background: lightskyblue; -fx-padding:12px;");
popup.getContent().add(popupContent);
fadeOut = new FadeTransition(Duration.millis(500), popupContent);
fadeOut.setFromValue(1.0);
fadeOut.setToValue(0.0);
fadeOut.setOnFinished(e -> popup.hide());
listView.setCellFactory(lv -> {
ListCell<Item> cell = new ListCell<Item>() {
#Override
public void updateItem(Item item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
setText(item.getName());
}
}
};
cell.hoverProperty().addListener((obs, wasHovered, isNowHovered) -> {
if (isNowHovered && ! cell.isEmpty()) {
showPopup(cell);
} else {
hidePopup();
}
});
return cell ;
});
IntStream.rangeClosed(1, 100).mapToObj(i -> new Item("Item "+i, i))
.forEach(listView.getItems()::add);
BorderPane root = new BorderPane(listView);
Scene scene = new Scene(root, 250, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private void showPopup(ListCell<Item> cell) {
fadeOut.stop();
popupContent.setOpacity(1.0);
Bounds bounds = cell.localToScreen(cell.getBoundsInLocal());
popup.show(cell, bounds.getMaxX(), bounds.getMinY());
Item item = cell.getItem() ;
titleLabel.setText(item.getName());
detailsLabel.setText(String.format("This is %s.%nIt has value %d.",
item.getName(), item.getValue()));
}
private void hidePopup() {
fadeOut.playFromStart();
}
public static class Item {
private final int value ;
private final String name ;
public Item(String name, int value) {
this.name = name ;
this.value = value ;
}
public int getValue() {
return value ;
}
public String getName() {
return name ;
}
}
public static void main(String[] args) {
launch(args);
}
}
To use handlers for mouseEntered and mouseExited, replace
cell.hoverProperty().addListener((obs, wasHovered, isNowHovered) -> {
if (isNowHovered && ! cell.isEmpty()) {
showPopup(cell);
} else {
hidePopup();
}
});
with
cell.setOnMouseEntered(e -> showPopup(cell));
cell.setOnMouseExited(e -> hidePopup());

JavaFX: CheckBoxTableCell get ActionEvent when user check a checkBox

I want to trigger a method or action when the user check or uncheck a checkbox in the tableView. the coursData.addListener(...) doesn't get triggered when the user use the checkBox .
Here is my code it compiles and the windows appears with the tableView with checkbox.
package testCheckBox2;
import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBase;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class CheckBoxTableCellTest extends Application {
private TableView<cours> tableView;
public ObservableList<cours> coursData ;//= FXCollections.observableArrayList();
#Override
public void start(Stage primaryStage) {
this.tableView = new TableView<cours>();
final TableColumn<cours, String> Cours = new TableColumn<cours, String>("Cours");
final TableColumn<cours, Boolean> checkedCol = new TableColumn<cours, Boolean>("Checked");
this.coursData =FXCollections.observableArrayList(
new cours("Analyse", "3"),
new cours("Analyse TP", "4"),
new cours("Thermo", "5"),
new cours("Thermo TP", "7"),
new cours("Chimie", "8"));
tableView.setItems(this.coursData);
tableView.getColumns().addAll(Cours, checkedCol);
Cours.setCellValueFactory(new PropertyValueFactory<cours, String>("cours"));
checkedCol.setCellValueFactory(new PropertyValueFactory<cours, Boolean>("checked"));
checkedCol.setCellFactory(CheckBoxTableCell.forTableColumn(checkedCol));
checkedCol.setEditable(true);
tableView.setEditable(true);
final BorderPane root = new BorderPane();
root.setCenter(tableView);
coursData.addListener(new InvalidationListener() {
#Override public void invalidated(Observable o) {
System.out.println("checkBox change state ");
//Here is my problem.
//When the user click on a checkBox , the method isn't call .
}
});
Scene scene = new Scene(root, 300, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public static class cours {
private StringProperty cours;
private StringProperty coursID;
private BooleanProperty checked;
public cours(String cours, String coursID) {
this.cours = new SimpleStringProperty(cours);
this.coursID = new SimpleStringProperty(coursID);
this.checked = new SimpleBooleanProperty(false);
}
public String getCours() {
return cours.get();
}
public String getCoursID() {
return coursID.get();
}
public boolean isChecked() {
return checked.get();
}
public void setCours(String cours) {
this.cours.set(cours);
}
public void setCoursID(String coursID) {
this.coursID.set(coursID);
}
public void setChecked(boolean checked) {
this.checked.set(checked);
}
public StringProperty coursProperty() {
return cours;
}
public StringProperty coursIDProperty() {
return coursID;
}
public BooleanProperty checkedProperty() {
return checked;
}
}
}
You have two ways of getting a notification when any of the check boxes is clicked.
One: providing a callback as argument for CheckBoxTableCell.forTableColumn instead of the tableColumn:
checkedCol.setCellFactory(CheckBoxTableCell.forTableColumn(new Callback<Integer, ObservableValue<Boolean>>() {
#Override
public ObservableValue<Boolean> call(Integer param) {
System.out.println("Cours "+items.get(param).getCours()+" changed value to " +items.get(param).isChecked());
return items.get(param).checkedProperty();
}
}));
Two: providing a callback to the collection:
final List<Cours> items=Arrays.asList(new Cours("Analyse", "3"),
new Cours("Analyse TP", "4"),
new Cours("Thermo", "5"),
new Cours("Thermo TP", "7"),
new Cours("Chimie", "8"));
this.coursData = FXCollections.observableArrayList(new Callback<Cours, Observable[]>() {
#Override
public Observable[] call(Cours param) {
return new Observable[] {param.checkedProperty()};
}
});
coursData.addAll(items);
and now listening to changes in the collection:
coursData.addListener(new ListChangeListener<Cours>() {
#Override
public void onChanged(ListChangeListener.Change<? extends Cours> c) {
while (c.next()) {
if (c.wasUpdated()) {
System.out.println("Cours "+items.get(c.getFrom()).getCours()+" changed value to " +items.get(c.getFrom()).isChecked());
}
}
}
});

javafx adding button to grid pane

I am adding button to grid pane dynamically but after giving them function they all show same function and i don't knows why?
import java.awt.Panel;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
public class TestController implements Initializable {
#FXML
Panel mpanel;
#FXML
GridPane gpnael;
int x=0,y=0,i=0,y1=0;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
private void add(ActionEvent event) {
y1++;
Button temp = new Button("Button " + i);
temp.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
System.out.println("button"+y1);
}
});
gpnael.add(temp,i++,1);
}
}
now i have added three button to grid pane when i click on each button they show same output.
I want that they all show different output as assigned .
You are not defining it in the buttons, you are always using a non final int to express your values you should try do make them with unique values or to set an id for each button and get the value from the id:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class ButtonsOnGPanel extends Application {
private int i = 0;
private GridPane gpnael = new GridPane();
#Override
public void start(Stage stage) throws Exception {
Pane root = new Pane();
while(i<3){
addButton();
}
root.getChildren().add(gpnael);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private void addButton() {
i++;
final Button temp = new Button("Button " + i);
final int numButton= i;
temp.setId("" + i);
temp.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
System.out.println("id(" + temp.getId() + ") = " + numButton);
}
});
gpnael.add(temp, i, 1);
}
public static void main(String[] args) {
launch(args);
}
}
And if you want to use lambda expressions:
temp.setOnAction((ActionEvent e) -> {
System.out.println("id(" + temp.getId() + ") = " + numButton);
});

ListView.scrollTo works slow with huge number of items

The scrollTo method in the code below works really slow. Is there any way to speed up it or may be some alternative variant? I need to display almost 100000 items in the application. Probably there are some alternative components. Thanks.
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
final ListView<String> listView = new ListView<>();
Button button = new Button("goto");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
int i = 99998;
System.out.println("before scroll");
long startTime = System.currentTimeMillis();
listView.scrollTo(i);
long elapsedTime = System.currentTimeMillis() - startTime;
System.out.println(elapsedTime);
listView.getFocusModel().focus(i);
}
});
List<String> items = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
items.add(UUID.randomUUID().toString());
}
listView.setItems(FXCollections.observableArrayList(items));
StackPane pane = new StackPane();
VBox vbox = new VBox();
vbox.getChildren().add(button);
vbox.getChildren().add(listView);
pane.getChildren().add(vbox);
stage.setScene(new Scene(pane));
stage.show();
}
}

Categories