我有一个TableView,其中包含的列始终显示可写的文本字段。如果column1的“ BigDecimal”值大于column2的值,我想让文本字段更改颜色。我可以在EditableTextCell类中设置文本字段的样式(例如,如果文本不是有效数字),但似乎无法访问模型进行其他比较。这是我的代码:
EditableTextCell.java
package tester;
import java.util.Objects;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.WritableValue;
import javafx.geometry.Pos;
import javafx.scene.control.TableCell;
import javafx.scene.control.TextField;
public class EditableTextCell<E> extends TableCell<E, String>
{
private final TextField textField;
private boolean updating = false;
public EditableTextCell(boolean editable)
{
textField = new TextField();
textField.setAlignment(Pos.CENTER_RIGHT);
textField.setEditable(editable);
textField.textProperty().addListener((ObservableValue<? extends String> o, String oldValue, String newValue) ->
{
if (!updating)
{
((WritableValue<String>) getTableColumn().getCellObservableValue((E) getTableRow().getItem())).setValue(newValue);
getTableView().scrollTo(getTableRow().getIndex());
getTableView().scrollToColumn(getTableColumn());
}
// this is where I would like stylize the textfield based on the input
});
}
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (empty)
{
setGraphic(null);
} else
{
setGraphic(textField);
if (!Objects.equals(textField.getText(), item))
{
// prevent own updates from moving the cursor
updating = true;
textField.setText(item);
updating = false;
}
}
}
}
LineItem.java
package tester;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class LineItem
{
private final StringProperty string1;
private final StringProperty string2;
public LineItem()
{
this.string1 = new SimpleStringProperty();
this.string2 = new SimpleStringProperty();
}
public final StringProperty getString1Property()
{
return this.string1;
}
public final StringProperty getString2Property()
{
return this.string2;
}
}
Tester.java
package tester;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class Tester extends Application
{
@Override
public void start(Stage primaryStage)
{
TableView<LineItem> table = new TableView<>();
table.setRowFactory(p ->
{
final TableRow<LineItem> row = new TableRow<>();
row.setOnMouseClicked(event ->
{
if (event.getClickCount() == 2 && (!row.isEmpty()))
{
LineItem rowData = row.getItem();
System.out.println(rowData.getString1Property().get() + " "+rowData.getString2Property().get());
}
});
return row;
});
Callback<TableColumn<LineItem, String>, TableCell<LineItem, String>> textFactoryEditable = (TableColumn<LineItem, String> p) -> new EditableTextCell(true);
TableColumn<LineItem, String> column1 = new TableColumn<>("Test1");
column1.setCellValueFactory(cellData -> cellData.getValue().getString1Property());
column1.setEditable(true);
column1.setCellFactory(textFactoryEditable);
table.getColumns().add(column1);
TableColumn<LineItem, String> column2 = new TableColumn<>("Test2");
column2.setCellValueFactory(cellData -> cellData.getValue().getString2Property());
column2.setEditable(true);
column2.setCellFactory(textFactoryEditable);
table.getColumns().add(column2);
table.getItems().add(new LineItem());
HBox root = new HBox();
root.getChildren().addAll(table);
Scene scene = new Scene(root, 500, 500);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
答案 0 :(得分:2)
我通过粘贴整个代码重新编辑了答案。我在代码中留下了注释。
CSS代码:
.red{
-fx-background-color:red;
}
.white{
-fx-background-color:white;
}
Tester
类:
package tester;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;
import java.util.ArrayList;
public class Tester extends Application
{
private static ArrayList<TableColumn<LineItem, String>> tableColumnArrayList;
@Override
public void start(Stage primaryStage)
{
TableView<LineItem> table = new TableView<>();
table.setRowFactory(p ->
{
final TableRow<LineItem> row = new TableRow<>();
row.setOnMouseClicked(event ->
{
if (event.getClickCount() == 2 && (!row.isEmpty()))
{
LineItem rowData = row.getItem();
System.out.println(rowData.getString1Property().get() + " "+rowData.getString2Property().get());
}
});
return row;
});
ArrayList<TableColumn<LineItem, String>> tableColumnArrayList = new ArrayList<>();
Callback<TableColumn<LineItem, String>, TableCell<LineItem, String>> textFactoryEditable = (TableColumn<LineItem, String> p) -> new EditableTextCell(true);
TableColumn<LineItem, String> column1 = new TableColumn<>("Test1");
column1.setCellValueFactory(cellData -> cellData.getValue().getString1Property());
column1.setEditable(true);
column1.setCellFactory(textFactoryEditable);
//I add each column
tableColumnArrayList.add(column1);
table.getColumns().add(column1);
TableColumn<LineItem, String> column2 = new TableColumn<>("Test2");
column2.setCellValueFactory(cellData -> cellData.getValue().getString2Property());
column2.setEditable(true);
column2.setCellFactory(textFactoryEditable);
//I add
tableColumnArrayList.add(column2);
table.getColumns().add(column2);
table.getItems().add(new LineItem());
//here I put the TableColumnArrayList to a static field
Tester.tableColumnArrayList = tableColumnArrayList;
HBox root = new HBox();
root.getChildren().addAll(table);
Scene scene = new Scene(root, 500, 500);
//here I set the stylesheet
scene.getStylesheets().add(getClass().getResource("stylesheet.css").toExternalForm());
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* static getter
* @return ArrayList object containing TableColumn objects
*/
public static ArrayList<TableColumn<LineItem, String>> getTableColumnArrayList() {
return tableColumnArrayList;
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
EditableTextCell
类:
package tester;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Objects;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.WritableValue;
import javafx.geometry.Pos;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextField;
public class EditableTextCell<E> extends TableCell<E, String>
{
private final TextField textField;
private boolean updating = false;
public EditableTextCell(boolean editable)
{
textField = new TextField();
textField.setAlignment(Pos.CENTER_RIGHT);
textField.setEditable(editable);
textField.textProperty().addListener((ObservableValue<? extends String> o, String oldValue, String newValue) ->
{
if (!updating)
{
((WritableValue<String>) getTableColumn().getCellObservableValue((E) getTableRow().getItem())).setValue(newValue);
getTableView().scrollTo(getTableRow().getIndex());
getTableView().scrollToColumn(getTableColumn());
}
// this is where I would like stylize the textfield based on the input
ArrayList<TableColumn<LineItem, String>> tableColumnArrayList = Tester.getTableColumnArrayList();
for(int i = 0; i < tableColumnArrayList.size(); i++){
if(i == 0){
this.textField.getStyleClass().clear(); //remove all old classes
this.textField.getStyleClass().add("white"); //add new class
} else {
String bd1String = tableColumnArrayList.get(i-1).getCellObservableValue(0).getValue();//first row
String bd2String = tableColumnArrayList.get(i).getCellObservableValue(0).getValue();
BigDecimal bd1, bd2;
try {
bd1 = new BigDecimal(bd1String);
bd2 = new BigDecimal(bd2String);
} catch(NullPointerException e){ //start imput will be null if You don't set anything
bd1 = BigDecimal.ZERO;
bd2 = BigDecimal.ZERO;
}
System.out.println(bd1 + " + " + bd2);
this.textField.getStyleClass().clear();
this.textField.getStyleClass().add(
(bd1.compareTo(bd2) > 0) ? "red" : "white"
);
System.out.println(this.textField.getStyleClass());
}
}
});
}
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (empty)
{
setGraphic(null);
} else
{
setGraphic(textField);
if (!Objects.equals(textField.getText(), item))
{
// prevent own updates from moving the cursor
updating = true;
textField.setText(item);
updating = false;
}
}
}
}
我没有在LineItem
类中进行任何更改。
我创建了一个静态字段TableTable对象的ArrayList,并为其创建了一个静态吸气剂。我在场景中添加了样式表(您可能会注意到路径中没有斜杠-样式表不在资源中,而是在与类相同的路径中)。
在类EditableTextCell中用注释标记的地方,我从Tester类获得了ArrayList,对其进行了循环,并为存储在TableColumn对象中的单元格设置了样式类。
我创建了一个try / catch块,在其中初始化了BigDecimal对象,因为该方法将null拉到那里。
答案 1 :(得分:2)
I figured it out. This is the line to get access to the model class.
LineItem lineItem = (LineItem) getTableRow().getItem();
However, my issue was that I was also changing the class declaration on EditableTextCell to match the type:
public class EditableTextCell<E> extends TableCell<E, String>
to:
public class EditableTextCell<LineItem> extends TableCell<LineItem, String>
This stopped me from using the properties under getTableRow().getItem()
with this error:
cannot find symbol
symbol: method getString1Property()
location: variable lineItem of type LineItem
where LineItem is a type-variable:
LineItem extends Object declared in class EditableTextCell`