注意:这是一个非常具体的错误,而不是Programmatically change the TableView row appearance的重复,但它与该问题非常相关。
我有一个带有CheckBox的表,当用户选择该行时(即点击CheckBox),我改变了该行的样式,以明确选择了一行。
但是,当用户应用过滤器来更改TableView上显示的数据时,我无法根据select属性设置每一行的样式。当我调试时,我发现实际上它应该设置样式,但根本没有样式更改。
以下是我可以用来重现此错误的最小代码:
DataView.java
package table;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class DataView extends Application{
TableView<DataRow> table = new TableView<DataRow>();
ComboBox<Integer> cb = new ComboBox<Integer>();
ObservableList<DataRow> masterData = FXCollections.observableArrayList();
ObservableList<DataRow> filteredData = FXCollections.observableArrayList();
@Override
public void start(Stage stage) throws Exception {
VBox root = new VBox();
initializeGUI();
addDummyData();
applyFilters();
root.getChildren().addAll(cb,table);
Scene scene = new Scene(root);
// scene.getStylesheets().add("/res/styleSummary.css");
scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
stage.setScene(scene);
stage.show();
}
private void applyFilters() {
filteredData = FXCollections.observableArrayList(new Callback<DataRow, Observable[]>() {
@Override
public Observable[] call(DataRow tr) {
return new Observable[] { tr.selectedProperty() };
}
});
filteredData.addListener(new ListChangeListener<DataRow>() {
@Override
public void onChanged(javafx.collections.ListChangeListener.Change<? extends DataRow> change) {
try{
while (change.next()) {
if (change.wasUpdated()) {
int i = 0;
for (Node n: table.lookupAll("TableRow")){
if(i==change.getFrom()){
@SuppressWarnings("unchecked")
TableRow<DataRow> row = (TableRow<DataRow>) n;
if (table.getItems().get(i).getSelected())
row.getStyleClass().add("selected");
else
row.getStyleClass().remove("selected");
}
i++;
}
updateMaster(filteredData.get(change.getFrom()));
}
}
}catch(Exception e){
}
}
private void updateMaster(table.DataRow changed) {
for (DataRow tr : masterData) {
if (tr.getNumSlices()==changed.getNumSlices()) {
tr.selectedProperty().set(changed.getSelected());
break;
}
}
}
});
filteredData.addAll(masterData);
for(DataRow dr: masterData){
if(dr.getNumSlices()==cb.getValue()){
filteredData.remove(dr);
}
}
table.setItems(filteredData);
//This fails:
int i = 0;
for (Node n: table.lookupAll("TableRow")){
TableRow<DataRow> row = (TableRow<DataRow>) n;
if (table.getItems().get(i).getSelected())
row.getStyleClass().add("selected");
else
row.getStyleClass().remove("selected");
i++;
if (i == table.getItems().size())
break;
}
}
@SuppressWarnings("unchecked")
public void initializeGUI(){
//combobox
cb.getItems().addAll(null,2,4,5);
cb.valueProperty().addListener(new ChangeListener<Number>(){
@Override
public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
applyFilters();
}
});
//table
TableColumn<DataRow, Integer> numColumn = new TableColumn<DataRow, Integer>();
numColumn.setCellValueFactory(new PropertyValueFactory<DataRow, Integer>("numSlices"));
TableColumn<DataRow, Boolean> selectionColumn = new TableColumn<DataRow, Boolean>();
selectionColumn.setCellValueFactory(new PropertyValueFactory<DataRow, Boolean>("selected"));
final Callback<TableColumn<DataRow, Boolean>, TableCell<DataRow, Boolean>> cellFactory = CheckBoxTableCell
.forTableColumn(selectionColumn);
selectionColumn.setCellFactory(new Callback<TableColumn<DataRow, Boolean>, TableCell<DataRow, Boolean>>() {
@Override
public TableCell<DataRow, Boolean> call(TableColumn<DataRow, Boolean> column) {
TableCell<DataRow, Boolean> cell = cellFactory.call(column);
cell.setAlignment(Pos.CENTER);
return cell;
}
});
selectionColumn.setCellFactory(cellFactory);
selectionColumn.setEditable(true);
table.getColumns().addAll(numColumn,selectionColumn);
table.setEditable(true);
}
public void addDummyData(){
for(int i=0;i<13;i++)
masterData.add(new DataRow(i,false));
}
public static void main(String[] args) throws Exception { launch(args); }
}
DataRow本质上是一个整数和布尔类型:
DataRow.java
package table;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
public class DataRow {
private Integer numSlices;
private BooleanProperty selected;
public DataRow(int numSlices, boolean selected) {
this.selected = new SimpleBooleanProperty(selected);
this.numSlices = numSlices;
}
public Integer getNumSlices() {return numSlices;}
public void setNumSlices(int num){this.numSlices = num;}
public void setSelected(boolean value) {selected.set(value);}
public boolean getSelected() {return selected.get();}
public BooleanProperty selectedProperty(){return selected;}
}
的style.css
.selected {
-fx-font-weight: bold;
-fx-font-size: 13;
}
只是为了使其更具体,错误可能在这里:
//(DataView.java) -- line 89
//This fails:
int i = 0;
for (Node n: table.lookupAll("TableRow")){
TableRow<DataRow> row = (TableRow<DataRow>) n;
if (table.getItems().get(i).getSelected())
row.getStyleClass().add("selected");
else
row.getStyleClass().clear();
i++;
if (i == table.getItems().size())
break;
}
答案 0 :(得分:2)
为什么不在链接的答案中使用该方法。您永远不知道哪个单元格是哪个,因此您必须在创建单元格(或行)时添加所需的所有内容。
我刚刚在您的initializeGUI()
中添加了此内容,并删除了复杂的侦听器。似乎工作正常。如果你真的想要一个样式类,那么使用像james_D链接的答案中的监听器。或者甚至更好,制作一个psuedoClass。
table.setRowFactory(new Callback<TableView<DataRow>, TableRow<DataRow>>() {
@Override
public TableRow<DataRow> call(TableView<DataRow> tableView) {
final TableRow<DataRow> row = new TableRow<DataRow>() {
@Override
protected void updateItem(DataRow row, boolean empty) {
super.updateItem(row, empty);
if (!empty)
styleProperty().bind(Bindings.when(row.selectedProperty())
.then("-fx-font-weight: bold; -fx-font-size: 16;")
.otherwise(""));
}
};
return row;
}
});