Javafx 8 Tableview选择与复选框

时间:2015-02-05 18:07:17

标签: javafx tableview

我已经设置了一个支持多选的tableview,并尝试将一个插入一个列的复选框附加到一个列的选择模型中。

checkBoxTableColumn.setCellValueFactory(
            cellData -> {
                CheckBox checkBox = new CheckBox();
                ObjectProperty<CheckBox> sop = new SimpleObjectProperty<CheckBox>();
                sop.setValue(checkBox);
                sop.getValue().setText("");



                sop.getValue().selectedProperty().addListener(
                        (obsv, oldv, newv) -> {
                            ArrayList<Job> tempSelectionArray = new ArrayList<>();

                            if(newv.booleanValue()){
                                tempSelectionArray.addAll(jobTableView.getSelectionModel().getSelectedItems().stream().collect(Collectors.toList()));
                                this.jobTableView.getSelectionModel().clearSelection();
                                for(Job job: tempSelectionArray){
                                    jobTableView.getSelectionModel().select(job);
                                }

                                tempSelectionArray.clear();
                            }
                            else{
                                tempSelectionArray.addAll(this.jobTableView.getSelectionModel().getSelectedItems().stream().collect(Collectors.toList()));
                                this.jobTableView.getSelectionModel().clearSelection();
                                tempSelectionArray.remove(getJobTableView().getFocusModel().getFocusedItem());
                                for(Job job: tempSelectionArray){
                                    this.jobTableView.getSelectionModel().select(job);
                                }
                                tempSelectionArray.clear();
                            }
                        }
                );
                ObservableValue<CheckBox> ov = sop;

                return ov;
            }

但这并没有改变表的选择。

编辑为jurge陈述

        checkBoxTableColumn.setCellFactory(new Callback<TableColumn<Job, Boolean>, TableCell<Job, Boolean>>() {
        @Override
        public TableCell<Job, Boolean> call(TableColumn<Job, Boolean> param) {
            return new CheckBoxCell(jobTableView);


        }
    });

和复选框单元格为

class CheckBoxCell extends TableCell<Job, Boolean>{
private CheckBox checkBox;
private TableView<Job> jobTableView;

public CheckBoxCell(TableView<Job> tableView){
    this.jobTableView = tableView;
}
@Override
public void updateItem(Boolean item, boolean empty) {
    super.updateItem(item, empty);

    checkBox = new CheckBox();
    setGraphic(checkBox);

    checkBox.selectedProperty().addListener(
            (obsv, oldv, newv) -> {
                ArrayList<Job> tempSelectionArray = new ArrayList<>();

                if(newv.booleanValue()){
                    tempSelectionArray.addAll(jobTableView.getSelectionModel().getSelectedItems().stream().collect(Collectors.toList()));
                    this.jobTableView.getSelectionModel().clearSelection();
                    for(Job job: tempSelectionArray){
                        jobTableView.getSelectionModel().select(job);
                    }

                    tempSelectionArray.clear();
                }
                else{
                    tempSelectionArray.addAll(this.jobTableView.getSelectionModel().getSelectedItems().stream().collect(Collectors.toList()));
                    this.jobTableView.getSelectionModel().clearSelection();
                    tempSelectionArray.remove(jobTableView.getFocusModel().getFocusedItem());
                    for(Job job: tempSelectionArray){
                        this.jobTableView.getSelectionModel().select(job);
                    }
                    tempSelectionArray.clear();
                }
            }
    );
}

}

这次听众不会工作.....

编辑 - #2

在控制器的初始化方法中:

        jobTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);


    checkBoxTableColumn.setEditable(true);
    checkBoxTableColumn.setCellValueFactory(
            new PropertyValueFactory<Job, Boolean>("isContextSelected")
    );

    checkBoxTableColumn.setCellFactory(
            new Callback<TableColumn<Job, Boolean>, TableCell<Job, Boolean>>() {
                @Override
                public TableCell<Job, Boolean> call(TableColumn<Job, Boolean> param) {
                    return new CheckBoxTableCell<Job, Boolean>(){
                        {
                            setAlignment(Pos.CENTER);
                        }

                        @Override
                        public void updateItem(Boolean item, boolean empty){
                            if(!empty){
                                TableRow row = getTableRow();

                                if(row != null){
                                    Integer rowNumber = row.getIndex();
                                    TableView.TableViewSelectionModel sm = getTableView().getSelectionModel();

                                    if(item){
                                        sm.select(rowNumber);

                                    }
                                    else{
                                        sm.clearSelection(rowNumber);

                                    }
                                }
                            }
                            super.updateItem(item, empty);
                        }
                    };
                }
            }
    );

工作班:

    private  BooleanProperty isContextSelected;
    public BooleanProperty isContextSelectedProperty() {
    return isContextSelected;
    }

edit-- 忽略不必要的部分。请求的整个代码: 控制器:

 package BillControl.view;

import BillControl.Controller.PopulateView;
import BillControl.Controller.Validator;
import BillControl.MainApp;
import BillControl.model.Article;
import BillControl.model.Job;
import javafx.beans.property.*;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.Callback;


import java.util.ArrayList;
import java.util.TreeSet;


public class ArticleJobAssignmentController {
    private Article article;
    private Stage jobAssignStage;
    private boolean okClicked = false;
    private MainApp mainApp;
    ArrayList<Job> selectedJobList = new ArrayList<>();
    private ObservableList<Job> masterJobList = FXCollections.observableArrayList();
    private ObservableList<Job> currentJobList = FXCollections.observableArrayList();
    private ObservableList<Job> articleEngagementList = FXCollections.observableArrayList();
    private TreeSet rowIndices = new TreeSet();
@FXML
private Label articleNameLabel;
@FXML
private Label noOfJobsLabel;
@FXML
private Button okButton;
@FXML
private Button cancelButton;
@FXML
private Label errorLabel;



@FXML
private TableView<Job> jobTableView;
@FXML
private TableColumn<Job, Boolean> checkBoxTableColumn;
@FXML
private TableColumn<Job, String> jobNameColumn;
@FXML
private TableColumn<Job, String> clientNameColumn;
@FXML
private TableColumn<Job, Integer> noOfArticlesColumn;
@FXML
private TableColumn<Job, String> alreadyEngagedColumn;


public ArticleJobAssignmentController(){

}

public void initialize(){


    errorLabel.setVisible(false);
    jobTableView.setEditable(true);
    jobTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);


    checkBoxTableColumn.setEditable(true);
    checkBoxTableColumn.setCellValueFactory(
            new PropertyValueFactory<Job, Boolean>("isContextSelected")
    );

    checkBoxTableColumn.setCellFactory(
            new Callback<TableColumn<Job, Boolean>, TableCell<Job, Boolean>>() {
                @Override
                public TableCell<Job, Boolean> call(TableColumn<Job, Boolean> param) {
                    return new CheckBoxTableCell<Job, Boolean>(){
                        {
                            setAlignment(Pos.CENTER);
                        }

                        @Override
                        public void updateItem(Boolean item, boolean empty){
                            if(!empty){
                                TableRow row = getTableRow();

                                if(row != null){
                                    Integer rowNumber = row.getIndex();
                                    TableView.TableViewSelectionModel sm = getTableView().getSelectionModel();

                                    if(item){
                                        sm.select(rowNumber);

                                    }
                                    else{
                                        sm.clearSelection(rowNumber);

                                    }
                                }
                            }
                            super.updateItem(item, empty);
                        }
                    };
                }
            }
    );



    jobNameColumn.setCellValueFactory(
            cellData -> cellData.getValue().nameProperty()
    );

    noOfArticlesColumn.setCellValueFactory(
            cellData -> {
                SimpleIntegerProperty sip = new SimpleIntegerProperty(cellData.getValue().numberOfArticlesProperty().getValue());
                ObservableValue<Integer> ov = sip.asObject();
                return ov;
            }

    );

    alreadyEngagedColumn.setCellValueFactory(
        cellData -> {
            Boolean engaged = false;
            for(Job job: articleEngagementList){
                if(job.getNumberID().equals(cellData.getValue().getNumberID())){
                    engaged = true;
                }
            }

            if(engaged){
                SimpleStringProperty sbp = new SimpleStringProperty("Yes");
                ObservableValue<String> ov = sbp;
                return ov;
            }
            else {
                SimpleStringProperty sbp = new SimpleStringProperty("No");
                ObservableValue<String> ov = sbp;
                return ov;
            }
        }
    );

    jobTableView.getSelectionModel().getSelectedItems().addListener(
            new ListChangeListener<Job>() {
                @Override
                public void onChanged(Change<? extends Job> c) {
                    noOfJobsLabel.setText(String.valueOf(c.getList().size()));
                }
            }
    );






}

public void filterMasterList(){
    for(Job job : masterJobList){
        if(!job.getIsCompleted()){
            currentJobList.add(job);
        }
    }

    for(Job currentJob : currentJobList){
        currentJob.setIsContextSelected(false);
    }
}


@FXML
public void handleOkClicked(){
    if(!Validator.articleJobAssignment(this)){

        for(Job job : jobTableView.getSelectionModel().getSelectedItems()){
            selectedJobList.add(job);
        }
        okClicked = true;
        jobAssignStage.close();
    }
    else {
        errorLabel.setText("Select at least one job");
        errorLabel.setVisible(true);
    }
}

@FXML
public void handleCancelClicked(){
    jobAssignStage.close();
}

public void setArticle(Article article) {
    this.article = article;
    articleNameLabel.setText(article.getName());

}

public void setJobAssignStage(Stage jobAssignStage) {
    this.jobAssignStage = jobAssignStage;
}

public void setOkClicked(boolean okClicked) {
    this.okClicked = okClicked;
}

public void setMainApp(MainApp mainApp) {
    this.mainApp = mainApp;
    setMasterJobList(mainApp.getJobObservableList());
    filterMasterList();
    jobTableView.setItems(currentJobList);

    if(article != null){
        articleEngagementList = PopulateView.articleCurrentEngagementList(articleEngagementList, article.getId(), mainApp.getClientObservableList());
    }
}

public Label getArticleNameLabel() {
    return articleNameLabel;
}

public Label getNoOfJobsLabel() {
    return noOfJobsLabel;
}

public Button getOkButton() {
    return okButton;
}

public Button getCancelButton() {
    return cancelButton;
}

public TableView<Job> getJobTableView() {
    return jobTableView;
}

public TableColumn<Job, String> getJobNameColumn() {
    return jobNameColumn;
}

public TableColumn<Job, String> getClientNameColumn() {
    return clientNameColumn;
}

public TableColumn<Job, Integer> getNoOfArticlesColumn() {
    return noOfArticlesColumn;
}

public ObservableList<Job> getMasterJobList() {
    return masterJobList;
}

public void setMasterJobList(ObservableList<Job> masterJobList) {
    this.masterJobList = masterJobList;
}

public boolean isOkClicked() {
    return okClicked;
}

public ArrayList<Job> getSelectedJobList() {
    return selectedJobList;
}
}

作业类(忽略构造函数):

package BillControl.model;


import BillControl.Controller.PopulateItems;
import BillControl.GeneralUtils.DateUtil;
import javafx.beans.property.*;
import javafx.collections.ObservableList;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;


public class Job {
    private  String numberID;
    private  StringProperty name;
    private  ObjectProperty<Client> client;
    private  StringProperty clientName;
    private  ObjectProperty<Date> startPeriod;
    private  ObjectProperty<Date> endPeriod;
    private  ObjectProperty<Date> startDate;
    private  ObjectProperty<Date> targetDate;
    private  BooleanProperty isDelayed;
    private  LongProperty remainingDays;
    private  LongProperty delayedDays;
    private  BooleanProperty isCompleted;
    private  ObjectProperty<Date> completionDate;
    private  LongProperty daysToComplete;
    private  StringProperty partner;
    private  IntegerProperty numberOfArticles;
    private  BooleanProperty isContextSelected;

private String clientID;

public Job(Client client){


    this.numberID = null;

        this.client = new SimpleObjectProperty<Client>(client);
        this.clientName = new SimpleStringProperty(client.getName());
        this.name = new SimpleStringProperty("");
        this.partner = new SimpleStringProperty("");
        this.startDate = new SimpleObjectProperty<Date>();
        this.targetDate = new SimpleObjectProperty<Date>();
        this.completionDate = new SimpleObjectProperty<Date>();
        this.isCompleted = new SimpleBooleanProperty(false);
        this.startPeriod = new SimpleObjectProperty<Date>();
        this.endPeriod = new SimpleObjectProperty<Date>();
        this.fillOthers(false);
    //        todo check fill others logic


    }

    public Job(ObservableList clientList, String numberID){
        this.numberID = numberID;
//        this.numberID = null;
        this.name = new SimpleStringProperty("");
        this.partner = new SimpleStringProperty("");
        this.startDate = new SimpleObjectProperty<Date>();
        this.targetDate = new SimpleObjectProperty<Date>();
        this.completionDate = new SimpleObjectProperty<Date>();
        this.isCompleted = new SimpleBooleanProperty(false);
        this.startPeriod = new SimpleObjectProperty<Date>();
        this.endPeriod = new SimpleObjectProperty<Date>();
        this.client = new SimpleObjectProperty<Client>();
        this.clientName = new SimpleStringProperty();
        this.numberOfArticles = new SimpleIntegerProperty();
        this.isContextSelected = new SimpleBooleanProperty(false);
        PopulateItems.populateJob(this);
        Client selectedClient = null;
    for(Object clientObject :  clientList){
        Client queriedClient = (Client) clientObject;
        String name =  queriedClient.getName();
        String queriedName = PopulateItems.clientID2NameHelper(this.getClientID());
        if(name.equals(queriedName)){
            selectedClient = (Client) clientObject;
            break;
        }
    }
    this.setClient(selectedClient);
    this.setClientName(this.getClient().getName());

    this.fillOthers(true);
}

public Job(){
    this.numberID = null;
    this.client = new SimpleObjectProperty<Client>();
    this.clientName = new SimpleStringProperty("");
    this.name = new SimpleStringProperty("");
    this.partner = new SimpleStringProperty("");
    this.startDate = new SimpleObjectProperty<Date>();
    this.targetDate = new SimpleObjectProperty<Date>();
    this.completionDate = new SimpleObjectProperty<Date>();
    this.isCompleted = new SimpleBooleanProperty(false);
    this.startPeriod = new SimpleObjectProperty<Date>();
    this.endPeriod = new SimpleObjectProperty<Date>();
    this.fillOthers(false);
}

public void fillOthers(Boolean filledJob){
    if(filledJob){

        DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        try {
            Date startDate = this.getStartDate();
            Date completionDate = this.getCompletionDate();
            Date currentDate = DateUtil.getCurrentDate();
            Date targetDate = this.getTargetDate();



            if (this.getIsCompleted()){
//                completion days
                    this.daysToComplete = new SimpleLongProperty();
                    long duration = completionDate.getTime() - startDate.getTime();
                    long diffInDays = TimeUnit.MILLISECONDS.toDays(duration);
                    this.setDaysToComplete(diffInDays);

            }
            else{
                this.remainingDays = new SimpleLongProperty();
                this.isDelayed = new SimpleBooleanProperty();
                if (targetDate.after(currentDate) && !this.getIsCompleted()){

                    //            remaining days
                    long duration = targetDate.getTime() - currentDate.getTime();
                    long diffInDays = TimeUnit.MILLISECONDS.toDays(duration);
                    this.setRemainingDays(diffInDays);
                    this.setIsDelayed(false);
                }
                else if (targetDate.before(currentDate) && !this.getIsCompleted()) {
//                delayed days
                        this.delayedDays = new SimpleLongProperty();
                        this.setIsDelayed(true);
                        long duration = currentDate.getTime() - targetDate.getTime();
                        long diffInDays = TimeUnit.MILLISECONDS.toDays(duration);
                        this.setRemainingDays(0);
                        this.setDelayedDays(diffInDays);
                    }
                }

            }

        catch (Exception e){
            e.printStackTrace();
        }
    }
    else {
//TODO client creation form job
    }

}

public String getName() {
    return name.get();
}

public StringProperty nameProperty() {
    return name;
}

public void setName(String name) {
    this.name.set(name);
}

public Client getClient() {
    return client.get();
}

public ObjectProperty<Client> clientProperty() {
    return client;
}

public void setClient(Client client) {
    this.client.set(client);
}

public Date getStartDate() {
    return startDate.get();
}

public ObjectProperty<Date> startDateProperty() {
    return startDate;
}

public void setStartDate(Date startDate) {
    this.startDate.set(startDate);
}

public Date getTargetDate() {
    return targetDate.get();
}

public ObjectProperty<Date> targetDateProperty() {
    return targetDate;
}

public void setTargetDate(Date targetDate) {
    this.targetDate.set(targetDate);
}

public boolean getIsDelayed() {
    return isDelayed.get();
}

public BooleanProperty isDelayedProperty() {
    return isDelayed;
}

public void setIsDelayed(boolean isDelayed) {
    this.isDelayed.set(isDelayed);
}

public long getRemainingDays() {
    return remainingDays.get();
}

public LongProperty remainingDaysProperty() {
    return remainingDays;
}

public void setRemainingDays(long remainingDays) {
    this.remainingDays.set(remainingDays);
}

public long getDelayedDays() {
    return delayedDays.get();
}

public LongProperty delayedDaysProperty() {
    return delayedDays;
}

public void setDelayedDays(long delayedDays) {
    this.delayedDays.set(delayedDays);
}

public boolean getIsCompleted() {
    return isCompleted.get();
}

public BooleanProperty isCompletedProperty() {
    return isCompleted;
}

public void setIsCompleted(boolean isCompleted) {
    this.isCompleted.set(isCompleted);
}

public Date getCompletionDate() {
    return completionDate.get();
}

public ObjectProperty<Date> completionDateProperty() {
    return completionDate;
}

public void setCompletionDate(Date completionDate) {
    this.completionDate.set(completionDate);
}

public long getDaysToComplete() {
    return daysToComplete.get();
}

public LongProperty daysToCompleteProperty() {
    return daysToComplete;
}

public void setDaysToComplete(long daysToComplete) {
    this.daysToComplete.set(daysToComplete);
}

public String getPartner() {
    return partner.get();
}

public StringProperty partnerProperty() {
    return partner;
}

public void setPartner(String partner) {
    this.partner.set(partner);
}

public Integer getNumberOfArticles() {
    return numberOfArticles.get();
}

public IntegerProperty numberOfArticlesProperty() {
    return numberOfArticles;
}

public void setNumberOfArticles(int numberOfArticles) {
    this.numberOfArticles.set(numberOfArticles);
}

public String getNumberID() {
    return numberID;
}

public String getClientName() {
    return clientName.get();
}

public StringProperty clientNameProperty() {
    return clientName;
}

public void setClientName(String clientName) {
    this.clientName.set(clientName);
}

public Date getStartPeriod() {
    return startPeriod.get();
}

public ObjectProperty<Date> startPeriodProperty() {
    return startPeriod;
}

public void setStartPeriod(Date startPeriod) {
    this.startPeriod.set(startPeriod);
}

public Date getEndPeriod() {
    return endPeriod.get();
}

public ObjectProperty<Date> endPeriodProperty() {
    return endPeriod;
}

public void setEndPeriod(Date endPeriod) {
    this.endPeriod.set(endPeriod);
}

public String getClientID() {
    return clientID;
}

public void setClientID(String clientID) {
    this.clientID = clientID;
}

public boolean getIsContextSelected() {
    return isContextSelected.get();
}

public BooleanProperty isContextSelectedProperty() {
    return isContextSelected;
}

public void setIsContextSelected(boolean isContextSelected) {
    this.isContextSelected.set(isContextSelected);
}
}

2 个答案:

答案 0 :(得分:8)

好的,所以这是一种方法。您需要在支持模型中使用BooleanProperty来保存复选框的值,以便表格将“记住”是否应选择行复选框,如果行滚出视图然后再返回。

TableColumn<Job,Boolean>  checkCol = new TableColumn<>("Check");
checkCol.setCellValueFactory( new PropertyValueFactory<Job,Boolean>( "checkBoxValue" ) );
checkCol.setCellFactory( new Callback<TableColumn<Job,Boolean>, TableCell<Job,Boolean>>()
{
    @Override
    public TableCell<Job,Boolean> call( TableColumn<Job,Boolean> param )
    {
        return new CheckBoxTableCell<Job,Boolean>()
        {
            {
                setAlignment( Pos.CENTER );
            }
            @Override
            public void updateItem( Boolean item, boolean empty )
            {
                if ( ! empty )
                {
                    TableRow  row = getTableRow();

                    if ( row != null )
                    {
                        int rowNo = row.getIndex();
                        TableViewSelectionModel  sm = getTableView().getSelectionModel();

                        if ( item )  sm.select( rowNo );
                        else  sm.clearSelection( rowNo );
                    }
                }

                super.updateItem( item, empty );
            }
        };
    }
} );
checkCol.setEditable( true );
checkCol.setMaxWidth( 50 );
checkCol.setMinWidth( 50 );

答案 1 :(得分:3)

您错误地使用了checkBoxTableColumn.setCellValueFactory

您的TableView具有类型为T的数据项,并且列上的setCellValueFactory方法用于告知列必须从要显示的类型T的对象中提取的值。

然而,您返回包含GUI组件(CheckBox)的可观察值,而您应返回从cellData中提取的可观察布尔值。

请参阅此处获取有关TableView的Oracle教程:http://docs.oracle.com/javafx/2/ui_controls/table-view.htm#CJAGAAEE

将复选框列添加到表格中,其中表格的更改复选框被传回模型对象非常简单:

TableColumn<Job,Boolean>  checkCol = new TableColumn<>("Check");
checkCol.setCellValueFactory( new PropertyValueFactory<Job,Boolean>( "checkBoxValue" ) );
checkCol.setCellFactory( CheckBoxTableCell.forTableColumn( checkCol ) );

请注意,“checkBoxValue”是Job中属性方法的部分名称,名为checkBoxValue Property (),返回BooleanProperty。 (它不必被称为checkBoxValue,你可以给它一个不同的名字,但它必须以Property结尾。)