i'm trying to make custom table cell with a DatePicker. and having Filtered list in the table that filters the contents depending on radio button selection. when i select a date for a cell everything works fine.
Screenshot 1
but when trying to filter and fire the predicate, the date looks going down to the bottom of the table. and when re-selecting the old radio button, it appears in the correct row.
Screenshot 2
any Ideas?
my controller :
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.Callback;
import javafx.util.converter.IntegerStringConverter;
import java.net.URL;
import java.time.LocalDate;
import java.util.ResourceBundle;
public class Controller implements Initializable {
@FXML
private TableColumn<SetterGetter, String> colStatus;
@FXML
private TableColumn<SetterGetter, Integer> colCode;
@FXML
private TableColumn<SetterGetter, LocalDate> colDueDate;
@FXML
private TableColumn<SetterGetter, String> colName;
@FXML
private RadioButton rdAll;
@FXML
private RadioButton rdDelayed;
@FXML
private RadioButton rdDone;
@FXML
private TableView<SetterGetter> tableTasks;
private RadioButton selectedRadioButton;
ObservableList<SetterGetter> mainTaskList = FXCollections.observableArrayList();
FilteredList<SetterGetter> tableTaskList = new FilteredList<>(mainTaskList, p -> true);
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
selectedRadioButton = rdAll;
colCode.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<SetterGetter, Integer>>() {
@Override
public void handle(TableColumn.CellEditEvent<SetterGetter, Integer> event) {
SetterGetter row = event.getRowValue();
row.setId(event.getNewValue());
}
});
colName.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<SetterGetter, String>>() {
@Override
public void handle(TableColumn.CellEditEvent<SetterGetter, String> event) {
SetterGetter row = event.getRowValue();
row.setName(event.getNewValue());
}
});
colStatus.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<SetterGetter, String>>() {
@Override
public void handle(TableColumn.CellEditEvent<SetterGetter, String> event) {
SetterGetter row = event.getRowValue();
row.setStatus(event.getNewValue().equals("منجز") ? 0 : 1);
}
});
colCode.setCellValueFactory(b -> new SimpleIntegerProperty(b.getValue().getId()).asObject());
colDueDate.setCellValueFactory(b -> b.getValue().getDate());
colName.setCellValueFactory(b -> new SimpleStringProperty(b.getValue().getName()));
colStatus.setCellValueFactory(b -> new SimpleStringProperty(
b.getValue().getStatus() == 0 ? "منجز"
: "لم ينجز بعد")
);
colCode.setCellFactory(TextFieldTableCell.forTableColumn(new IntegerStringConverter()));
colName.setCellFactory(TextFieldTableCell.forTableColumn());
colStatus.setCellFactory(ComboBoxTableCell.forTableColumn(FXCollections.observableArrayList(
"منجز",
"لم ينجز بعد")
)
);
colDueDate.setCellFactory(new Callback<TableColumn<SetterGetter, LocalDate>, TableCell<SetterGetter, LocalDate>>() {
@Override
public TableCell<SetterGetter, LocalDate> call(TableColumn<SetterGetter, LocalDate> setterGetterStringTableColumn) {
return new DatePickerTableCell();
}
});
mainTaskList.addAll(
new SetterGetter(0, null, null, 1),
new SetterGetter(1, null, null, 1)
);
tableTasks.setItems(tableTaskList);
}
@FXML
void addCheck(ActionEvent event) {
mainTaskList.add(new SetterGetter(0,
null,
null,
0)
);
}
@FXML
void selectRadioButton(ActionEvent event) {
if (event.getSource() != selectedRadioButton) {
RadioButton newRadio = (RadioButton) event.getSource();
newRadio.setStyle("-fx-font-family:arial;-fx-font-size:14;-fx-font-weight:bold;-fx-border-color:red;-fx-border-radius:20;");
selectedRadioButton.setStyle("-fx-font-family:arial;-fx-font-size:14;-fx-font-weight:bold;");
selectedRadioButton = newRadio;
}
firePredicate();
}
private void firePredicate() {
tableTaskList.setPredicate(p -> {
if (selectedRadioButton.equals(rdDone) && p.getStatus() != 0)
return false;
else if (selectedRadioButton.equals(rdDelayed) && p.getStatus() != 1)
return false;
else return true;
});
}
}
DatePickerTableCell class:
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TableCell;
import java.time.LocalDate;
public class DatePickerTableCell extends TableCell<SetterGetter, LocalDate> {
private final DatePicker datePicker = new DatePicker();
public DatePickerTableCell() {
super();
}
@Override
public void startEdit() {
super.startEdit();
setGraphic(datePicker);
setText(null);
datePicker.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
commitEdit(datePicker.getValue());
}
});
}
@Override
public void commitEdit(LocalDate s) {
super.commitEdit(s);
setText(s.toString());
setGraphic(null);
setItem(s);
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText(datePicker.getValue() == null ? null : datePicker.getValue().toString());
setGraphic(null);
}
}
SetterGetter class:
import javafx.beans.property.ObjectProperty;
import java.time.LocalDate;
public class SetterGetter {
int id;
String name;
ObjectProperty<LocalDate> date;
int status;
public SetterGetter(int id, String name, ObjectProperty<LocalDate> date, int status) {
this.id = id;
this.name = name;
this.date = date;
this.status = status;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ObjectProperty<LocalDate> getDate() {
return date;
}
public void setDate(ObjectProperty<LocalDate> date) {
this.date = date;
}
}
Main class :
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 565, 551));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
fxml file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="551.0" prefWidth="565.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<TableView fx:id="tableTasks" editable="true" layoutX="16.0" layoutY="163.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="400.0" prefWidth="554.0" style="-fx-font-family: arial; -fx-font-size: 15;" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0">
<columns>
<TableColumn fx:id="colDueDate" prefWidth="112" style="-fx-font-family: arial; -fx-font-size: 15;" text="التاريخ" />
<TableColumn fx:id="colStatus" prefWidth="112" style="-fx-font-family: arial; -fx-font-size: 15;" text="الحالة" />
<TableColumn fx:id="colName" prefWidth="112" style="-fx-font-family: arial; -fx-font-size: 15;" text="الأسم" />
<TableColumn fx:id="colCode" prefWidth="112" style="-fx-font-family: arial; -fx-font-size: 15;" text="الكود" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
<HBox alignment="CENTER" layoutX="160.0" layoutY="27.0" spacing="15.0">
<children>
<RadioButton fx:id="rdDelayed" mnemonicParsing="false" onAction="#selectRadioButton" style="-fx-font-family: arial; -fx-font-size: 14; -fx-font-weight: bold;" text="لم ينجز بعد">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<toggleGroup>
<ToggleGroup fx:id="radioGroup" />
</toggleGroup>
</RadioButton>
<RadioButton fx:id="rdDone" mnemonicParsing="false" onAction="#selectRadioButton" style="-fx-font-family: arial; -fx-font-size: 14; -fx-font-weight: bold;" text="منجز" toggleGroup="$radioGroup">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</RadioButton>
<RadioButton fx:id="rdAll" mnemonicParsing="false" onAction="#selectRadioButton" selected="true" style="-fx-font-family: arial; -fx-font-size: 14; -fx-font-weight: bold; -fx-border-color: red; -fx-border-radius: 20 20 20 20;" text="الكل" toggleGroup="$radioGroup">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</RadioButton>
</children>
</HBox>
<Button layoutX="473.0" layoutY="31.0" mnemonicParsing="false" onAction="#addCheck" prefHeight="34.0" prefWidth="77.0" style="-fx-font-family: arial; -fx-font-size: 18;" text="إضافة">
<font>
<Font name="Arial" size="17.0" />
</font>
</Button>
</children>
</AnchorPane>