Как настроить CellValueFactory для функций различных свойств в javafx? - PullRequest
0 голосов
/ 19 сентября 2018

Я строил менеджер загрузок в javafx по шаблону MVC и столкнулся с некоторыми проблемами.Я хотел перечислить загрузки в TableView со всеми свойствами в различных столбцах.

Предположим, у меня есть такая модель.

class Download{
    private SimpleObjectProperty<Integer> part1;
    private SimpleObjectProperty<Integer> part2;

    public SimpleObjectProperty<Integer> getPart1Property(){
        return part1;
    }
    public SimpleObjectProperty<Integer> getPart2Property(){
        return part2;
    }
}

Теперь у меня есть графический интерфейс javafx с табличным представлением, подобным этому.

TableView<Download> table=new TableView<Download>();
table.setItems(.. Observable list of Download objects ...);

Если бы я хотелдобавив столбец в табличное представление для значения part1, я мог бы сделать это следующим образом.

 TableColumn<Download,Integer> part1 = new TableColumn<Download,Integer>("Part 1 value");
 part1.setCellValueFactory(
            (TableColumn.CellDataFeatures<Download, Integer> download) -> download.getValue().getPart1Property());

Теперь мне нужен столбец в табличном представлении, который показывает сумму значенийчасть1 и часть2 . Как мне добиться этого в javafx?

Я прочитал документы здесь , но, к сожалению, не смог найти способа, которым я мог бы это сделать.Любая помощь будет оценена.

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Nevermind.Оказывается, мне нужно использовать привязки, чтобы выполнить то, что я искал.Ниже приведен улучшенный пример кода от @Sai, который делает то, что мне нужно.Соответствующие документы здесь .

import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import javafx.beans.binding.Bindings;

public class test extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        ObservableList<Download>  downloads = FXCollections.observableArrayList();
        downloads.add(new Download(23,56));
        downloads.add(new Download(56,43));
        downloads.add(new Download(97,3));
        downloads.add(new Download(67,23));

        TableView<Download> tableView = new TableView<>();
        TableColumn<Download, Integer> part1Col = new TableColumn<>("Part 1");
        part1Col.setCellValueFactory(param -> param.getValue().part1Property());

        TableColumn<Download, Integer> part2Col = new TableColumn<>("Part 2");
        part2Col.setCellValueFactory(param -> param.getValue().part2Property());

        TableColumn<Download, Integer> totalCol = new TableColumn<>("Total");
        totalCol.setCellValueFactory(param -> {
            return Bindings.createObjectBinding(()-> { return (param.getValue().getPart1()+param.getValue().getPart2());} ,param.getValue().part1Property(),param.getValue().part2Property());
            });


        tableView.getColumns().addAll(part1Col,part2Col, totalCol);
        tableView.setItems(downloads);
        Scene sc = new Scene(tableView);
        primaryStage.setScene(sc);
        primaryStage.show();
        downloads.get(1).setPart1(300);
    }

    class Download{
        SimpleObjectProperty<Integer> part1 = new SimpleObjectProperty<>(0);
        SimpleObjectProperty<Integer> part2= new SimpleObjectProperty<>(0);
        public Download(int p1, int p2){
            part1.set(p1);
            part2.set(p2);

        }

        public int getPart1() {
            return part1.get();
        }

        public SimpleObjectProperty<Integer> part1Property() {
            return part1;
        }

        public void setPart1(int part1) {
            this.part1.set(part1);
        }

        public int getPart2() {
            return part2.get();
        }

        public SimpleObjectProperty<Integer> part2Property() {
            return part2;
        }

        public void setPart2(int part2) {
            this.part2.set(part2);
        }
    }
}
0 голосов
/ 20 сентября 2018

Хорошо, учитывая ваше требование, я думаю, что сначала вам нужно определить свои свойства как IntegerProperty, а не оборачивать Integer в ObjectProperty (согласно стандартам javafx).Таким образом, для добавления вы можете напрямую использовать привязку номера, предоставленную IntegerProperty.Конечно, с этим изменением вам нужно определить тип данных TableColumn как Number.

Если вы очень хотите определить тип данных столбца как только Integer, то вы можете вызвать метод asObject () в своей ячейке cellValueFactory.Лично я не предпочитаю дополнительный уровень создания объекта с использованием asObject () и приведение к IntegerBinding:)

IntegerProperty part1 = new SimpleIntegerProperty();

TableColumn<Download, Integer> part1Col = new TableColumn<>("Part 1");
part1Col.setCellValueFactory(param -> param.getValue().part1Property().asObject());

TableColumn<Download, Integer> totalCol = new TableColumn<>("Total");
    totalCol.setCellValueFactory(param -> ((IntegerBinding)param.getValue().part1Property().add(param.getValue().part2Property())).asObject());

Ниже приведен обновленный код (немного более чистый) предыдущей демонстрации с вышеуказанными изменениями, которыйобновит значение Part1 первой строки, а общее значение столбца обновится автоматически.

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import javafx.util.Duration;

public class CustomCellValueFactoryDemo extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        ObservableList<Download> downloads = FXCollections.observableArrayList();
        downloads.add(new Download(23, 56));
        downloads.add(new Download(56, 43));
        downloads.add(new Download(97, 3));
        downloads.add(new Download(67, 23));

        TableView<Download> tableView = new TableView<>();
        TableColumn<Download, Number> part1Col = new TableColumn<>("Part 1");
        part1Col.setCellValueFactory(param -> param.getValue().part1Property());

        TableColumn<Download, Number> part2Col = new TableColumn<>("Part 2");
        part2Col.setCellValueFactory(param -> param.getValue().part2Property());

        TableColumn<Download, Number> totalCol = new TableColumn<>("Total");
        totalCol.setCellValueFactory(param -> param.getValue().part1Property().add(param.getValue().part2Property()));


        tableView.getColumns().addAll(part1Col, part2Col, totalCol);
        tableView.setItems(downloads);

        Scene sc = new Scene(tableView);
        primaryStage.setScene(sc);
        primaryStage.show();

        // Updating the value dynamically.
        Download firstRow = downloads.get(0);
        Timeline tl = new Timeline(new KeyFrame(Duration.millis(1000), e -> firstRow.setPart1(firstRow.getPart1() + 1)));
        tl.setCycleCount(50);
        tl.play();
    }

    class Download {
        IntegerProperty part1 = new SimpleIntegerProperty();
        IntegerProperty part2 = new SimpleIntegerProperty();

        public Download(int p1, int p2) {
            part1.set(p1);
            part2.set(p2);

        }

        public int getPart1() {
            return part1.get();
        }

        public IntegerProperty part1Property() {
            return part1;
        }

        public void setPart1(int part1) {
            this.part1.set(part1);
        }

        public int getPart2() {
            return part2.get();
        }

        public IntegerProperty part2Property() {
            return part2;
        }

        public void setPart2(int part2) {
            this.part2.set(part2);
        }
    }
}
0 голосов
/ 19 сентября 2018

Вам необходимо вернуть сумму требуемых значений в cellValueFactory.

TableColumn<Download, Integer> totalCol = new TableColumn<>("Total");
        totalCol.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue().getPart1() + param.getValue().getPart2()));

Полная рабочая демонстрация приведена ниже:

import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

public class CustomCellValueFactoryDemo extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        ObservableList<Download>  downloads = FXCollections.observableArrayList();
        downloads.add(new Download(23,56));
        downloads.add(new Download(56,43));
        downloads.add(new Download(97,3));
        downloads.add(new Download(67,23));

        TableView<Download> tableView = new TableView<>();
        TableColumn<Download, Integer> part1Col = new TableColumn<>("Part 1");
        part1Col.setCellValueFactory(param -> param.getValue().part1Property());

        TableColumn<Download, Integer> part2Col = new TableColumn<>("Part 2");
        part2Col.setCellValueFactory(param -> param.getValue().part2Property());

        TableColumn<Download, Integer> totalCol = new TableColumn<>("Total");
        totalCol.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue().getPart1() + param.getValue().getPart2()));


        tableView.getColumns().addAll(part1Col,part2Col, totalCol);
        tableView.setItems(downloads);

        Scene sc = new Scene(tableView);
        primaryStage.setScene(sc);
        primaryStage.show();
    }

    class Download{
        SimpleObjectProperty<Integer> part1 = new SimpleObjectProperty<>(0);
        SimpleObjectProperty<Integer> part2= new SimpleObjectProperty<>(0);
        public Download(int p1, int p2){
            part1.set(p1);
            part2.set(p2);

        }

        public int getPart1() {
            return part1.get();
        }

        public SimpleObjectProperty<Integer> part1Property() {
            return part1;
        }

        public void setPart1(int part1) {
            this.part1.set(part1);
        }

        public int getPart2() {
            return part2.get();
        }

        public SimpleObjectProperty<Integer> part2Property() {
            return part2;
        }

        public void setPart2(int part2) {
            this.part2.set(part2);
        }
    }
}
...