绘制tableview内的行

时间:2019-01-28 08:35:01

标签: java javafx javafx-8

我有一个TableView和两个文本字段。当用户将数字写入文本字段并按下按钮时。所有桌布都应按百分比绘制。例如,30%应该是黄色,70%应该是绿色。 enter image description here

我试图使用查找方法来查找TableView对象。添加新的CSS类会更改表行的颜色。但是这种解决方案不是很好。查找只能找到可见的元素。

@FXML
void confirmPercentage(ActionEvent event) {
    clearSelectionsOfTestingTbaleView();
    TableRow[] tableRows = selectTrainingDataTableView.lookupAll(".table-row-cell").toArray(new TableRow[0]);

    double percent = Double.parseDouble(this.trainingSetPercentageTextField.getText());
    percent = percent > 1 ? percent / 100 : percent;
    int trainIndexes = (int) (Math.round(tableRows.length * percent));

    for (int i = 0 ; i < trainIndexes; i++){
        tableRows[i].getStyleClass().add("selected-as-train");
    }
}

我有15个音符,但只有13个... enter image description here

那么绘制所有表行的方式是什么?

解决方案

最后,我明白了!

enter image description here

因此,我创建了两组以保留选定的索引。而且,我只是根据此索引设置了PseudoClass ...

void init()
    Set<Integer> testSetIndexes = new HashSet<>();
    Set<Integer> trainSetIndexes = new HashSet<>();
    tableView.setRowFactory( tableView2 -> {

        PseudoClass train = PseudoClass.getPseudoClass("train");
        PseudoClass test = PseudoClass.getPseudoClass("test");
        PseudoClass trainAndTest = PseudoClass.getPseudoClass("train-and-test");
        /*Percentage selection with button*/
        final TableRow<List<Double>> row = new TableRow<List<Double>>(){

            @Override
            public void updateItem(List<Double> item, boolean empty){

                if (item != null) {
                    int index = dataInsideTableView.indexOf(item);
                    this.pseudoClassStateChanged(train, trainSetIndexes.contains(index));
                    this.pseudoClassStateChanged(test, testSetIndexes.contains(index));
                    this.pseudoClassStateChanged(trainAndTest, trainSetIndexes.contains(index) && testSetIndexes.contains(index));
                } else {
                    this.pseudoClassStateChanged(train, false);
                    this.pseudoClassStateChanged(test, false);
                    this.pseudoClassStateChanged(trainAndTest, false);
                }
            }
        };

        /*Mouse selection*/
        row.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if (manualSelectionCheckBox.isSelected()) {
                    if (event.isPrimaryButtonDown()) {
                        int index = dataInsideTableView.indexOf(row.getTableView().getItems().get(row.getIndex()));
                        if(trainSetIndexes.contains(index)){
                            trainSetIndexes.remove(index);
                        } else {
                            trainSetIndexes.add(index);
                        }
                        selectTrainingDataTableView.refresh(); //call update
                    } else if (event.isSecondaryButtonDown()) {
                        int index = dataInsideTableView.indexOf(row.getTableView().getItems().get(row.getIndex()));
                        if(testSetIndexes.contains(index)){
                            testSetIndexes.remove(index);
                        } else {
                            testSetIndexes.add(index);
                        }
                        tableView.refresh();
                    }
                }
            }
        });

        return row;
    });

我单击“刷新”按钮,confirmPercentage方法只是重新计算索引并刷新表。

@FXML
void confirmPercentage(ActionEvent event) {
    trainSetIndexes.clean();
    testSetIndexes.clean();

    double percent = Double.parseDouble(this.trainingSetPercentageTextField.getText());
    percent = percent > 1 ? percent / 100 : percent;
    trainSize = (int) (Math.floor(usedData.size() * percent));
    percent = Double.parseDouble(this.testingSetPercentageTextField .getText());
    percent = percent > 1 ? percent / 100 : percent;
    testSize = (int) (Math.floor(usedData.size() * percent));

    //put indexes
    for (int i = 0 ; i < trainSize; i++){
        trainSetIndexes.add(i);
    }

    for (int i = usedData.size()-1 ; i >= usedData.size()-1-testSize; i--){
        testSetIndexes.add(i);
    }
    this.tableView.refresh();
}

1 个答案:

答案 0 :(得分:-1)

您可以将TableRow StyleClass作为TableView数据模型中的字段

fxml视图

<VBox fx:id="root" prefHeight="300.0" prefWidth="600.0" fx:controller="sample.View"
      xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" >
    <stylesheets>
        <URL value="@app.css" />
    </stylesheets>

    <ToolBar>
        <Button fx:id="set" mnemonicParsing="false" onAction="#set" text="Set" />
        <Button fx:id="reset" mnemonicParsing="false" onAction="#reset" text="Reset" />
    </ToolBar>


    <TableView fx:id="tvDevices" VBox.vgrow="ALWAYS">
        <columns>
            <TableColumn fx:id="colNum1" text="Num1">
                <cellValueFactory>
                    <PropertyValueFactory property="num1" />
                </cellValueFactory>
            </TableColumn>
            <TableColumn fx:id="colNum2" text="Num2">
                <cellValueFactory>
                    <PropertyValueFactory property="num2" />
                </cellValueFactory>
            </TableColumn><TableColumn fx:id="colNum3" text="Num3">
                <cellValueFactory>
                    <PropertyValueFactory property="num3" />
                </cellValueFactory>
            </TableColumn>
        </columns>
    </TableView>
</VBox>

数据视图模型类

public class Foo {
    private DoubleProperty num1;
    private DoubleProperty num2;
    private DoubleProperty num3;
    private StringProperty styleClass;

    public Foo(int num1, int num2, int num3) {
        this.num1 = new SimpleDoubleProperty(num1);
        this.num2 = new SimpleDoubleProperty(num2);
        this.num3 = new SimpleDoubleProperty(num3);
        this.styleClass = new SimpleStringProperty();
    }

    public double getNum1() {
        return num1.get();
    }

    public DoubleProperty num1Property() {
        return num1;
    }

    public void setNum1(double num1) {
        this.num1.set(num1);
    }

    public double getNum2() {
        return num2.get();
    }

    public DoubleProperty num2Property() {
        return num2;
    }

    public void setNum2(double num2) {
        this.num2.set(num2);
    }

    public double getNum3() {
        return num3.get();
    }

    public DoubleProperty num3Property() {
        return num3;
    }

    public void setNum3(double num3) {
        this.num3.set(num3);
    }

    public String getStyleClass() {
        return styleClass.get();
    }

    public StringProperty styleClassProperty() {
        return styleClass;
    }

    public void setStyleClass(String styleClass) {
        this.styleClass.set(styleClass);
    }
}

视图控制器

public class View implements Initializable {

    @FXML
    private TableView<Foo> tvDevices;

    @Override
    public void initialize(URL location, ResourceBundle resources) {    
            tvDevices.setRowFactory(param -> {
            TableRow<Foo> row = new TableRow<>();
            //This listener will monitor the Change in the Modal StyleClass to keep row updated when StyleClass value chenge.
            ChangeListener<String> listener = (observable, oldValue, newValue) -> {
                if (newValue == null) {
                    //reset StyleClass to default by removing any additional class's
                    row.getStyleClass().remove(3,row.getStyleClass().size());
                } else {
                    //removing any additional class's and add the new one
                    row.getStyleClass().remove(3,row.getStyleClass().size());
                    row.getStyleClass().add(newValue);
                }
            };
            //This listener will monitor the particular Modal attached to this row.
            row.itemProperty().addListener((observable, oldValue, newValue) -> {
                if (oldValue != null) {
                    //remover the listener from the old item
                    oldValue.styleClassProperty().removeListener(listener);
                }
                if (newValue != null) {
                    // attach the listener to the new item
                    newValue.styleClassProperty().addListener(listener);
                    // update row StyleClass to new item StyleClass
                    if (newValue.styleClassProperty() == null) {
                        row.getStyleClass().remove(3,row.getStyleClass().size());
                    } else {
                        row.getStyleClass().remove(3,row.getStyleClass().size());
                        row.getStyleClass().add(newValue.getStyleClass());
                    }
                } else {
                    //reset StyleClass to default because new item is null
                    row.getStyleClass().remove(3,row.getStyleClass().size());
                }
            });
            return row;
        });

        for (int i = 0; i < 50; i++) {
            tvDevices.getItems().add(new Foo(1, 2, 3));
        }
    }

    @FXML
    private void reset(ActionEvent actionEvent) {
        tvDevices.getItems().forEach(foo -> foo.setStyleClass(null));
        actionEvent.consume();
    }

    @FXML
    private void set(ActionEvent actionEvent) {
        tvDevices.getItems().get(10).setStyleClass("class1");
        tvDevices.getItems().get(20).setStyleClass("class2");
        tvDevices.getItems().get(40).setStyleClass("class3");
        actionEvent.consume();
    }
}