gpt4 book ai didi

javafx - 使用自定义 DatePicker TableCell JavaFX 过滤表时出现问题

转载 作者:行者123 更新时间:2023-12-02 01:34:11 25 4
gpt4 key购买 nike

我正在尝试使用 DatePicker 制作自定义表格单元格。并在表中提供过滤列表,根据单选按钮的选择过滤内容。当我为单元格选择日期时,一切正常。

截图1

screenshot

但是当尝试过滤和触发谓词时,日期看起来会一直到表的底部。当重新选择旧的单选按钮时,它会出现在正确的行中。

截图2

screenshot 2

有什么想法吗?

我的 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 类:

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 类:

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;
}
}

主类:

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 文件:

<?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>

最佳答案

您的演示中缺少很多内容。其中,@jewelsea 在他的评论中已经提到了其中一个。

问题#1:

我注意到您没有为日期列添加提交事件。您需要将值(日期)保留到行对象中才能在过滤时获得正确的结果。

初始化方法中的代码将如下所示:

colDueDate.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<SetterGetter, LocalDate>>() {
@Override
public void handle(TableColumn.CellEditEvent<SetterGetter, LocalDate> event) {
SetterGetter row = event.getRowValue();
if(row.date==null){
row.setDate(new SimpleObjectProperty<>());
}
row.date.set(event.getNewValue());
}
});

问题#2:

正如@jewelsea所提到的,在定义自定义单元格时,您需要重写TableCell的updateItem()方法。 DatePickerTableCell 中的代码如下:

@Override
protected void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
if (isEditing()) {
setText(null);
setGraphic(datePicker);
} else {
setGraphic(null);
if (item != null) {
setText(item.toString());
} else {
setText(null);
}
}
}

updateItem 中缺少 if-else 条件是导致单元格值出现在不适当位置的实际问题的主要原因。

VirtualFlow 重用单元并可以将其放置在任何位置。我们有责任确保它在调用 updateItem 时正确呈现。如果缺少 if-else 条件,您会看到单元格使用了错误的值。

问题#3:不完全是一个问题;)

对 SetterGetter 类中可观察属性的 setter/getter 使用正确的命名约定。

public LocalDate getDate() {
return date.get();
}

public void setDate(LocalDate date) {
this.date.set(date);
}

public ObjectProperty<LocalDate> dateProperty() {
return date;
}

关于javafx - 使用自定义 DatePicker TableCell JavaFX 过滤表时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72780488/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com