当表格编辑取消时,组合框选择消失

时间:2016-02-17 20:07:52

标签: javafx combobox tableview javafx-8 tablecell

好的,我开始对这个失去理智。我有一个tableview,其中有3个组合框表格单元格。第一个是用户可以选择作业的框,所选作业会更改下一个组合框的选项(作业类别)。作业类别选择会更改人工框中的选项。所以流程是:

工作>工作类别>劳动。

我有一个非常奇怪的问题。编辑表格时,您可以单击任何框以根据其他字段获取相应的可用选择列表。这很好用。爆炸的地方是选择 ISN' T 。为了使事情变得更有趣,它只影响工作和工作类别组合框,工作箱完美无瑕。

症状:

- 通过esc或焦点丢失取消编辑时,作业类别选择消失

- 当通过esc取消编辑或失去焦点时,在作业类别字段中选择的选择将被放入作业字段

以下是重新创建症状的步骤:

1)点击工作类别框并启用编辑模式

2)从下拉列表中进行新选择

new selection made img

3)点击工作框并启用编辑

4)单击工作框并通过单击同一行中的工作类别或人工框取消编辑

5)启用作业类别编辑,然后通过单击人工/人工框或使用esc取消作业类别编辑

lose the job category / job selections img

这是在图形出现时初始化图形的代码:

public void initialize(URL location, ResourceBundle resources) {

    /* this is here because the screen handler will load up the Main screen in the
    in the hashmap; no connection data will be assigned to the user at that time.
    Without this block, when the hashmap attempts to load the Main data this
    will cause the screenhandler to error and the main application
    to not load correctly.  The block below initiatializes the connection to
    prevent this from happening.*/

    if ( vUsers.getConn() == null){
        try {
            //establishes a user's connection to the database
            vUsers.ConnecrDB();

        } catch (SQLException | IOException ex) {
            //debugging catch
            System.out.println(ex);
        }
    }

    //set the job box list for the user
    cmbxJobT.setItems(cmbxPopulator.getJobComboBox());

    cmbxJobT.valueProperty().addListener(new ChangeListener<String>(){
        @Override
        //reads the user's selectino and returns the appropriate labor codes for the Employee
        public void changed(ObservableValue o, String oldValue, String newValue){
            if (newValue != null){
                cmbxJobCatT.getItems().clear();
                cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(newValue));
            }else {
                cmbxJobCatT.getItems().clear();
                cmbxJobCatT.getItems().add(null);
            }
        }
    });

    cmbxJobCatT.valueProperty().addListener(new ChangeListener<String>(){
        @Override
        //reads the user's selectino and returns the appropriate labor codes for the Employee
        public void changed(ObservableValue o, String oldValue, String newValue){
            if (newValue != null){
                cmbxLaborT.getItems().clear();
                cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(newValue));
            }else {
                cmbxLaborT.getItems().clear();
                cmbxLaborT.getItems().add(null);
            }
        }
    });

    tblviewTime.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSel) ->{
        if (newSel != null){

            Model_Time current = tblviewTime.getSelectionModel().getSelectedItem();

            cmbxJobCatT.getItems().clear();
            cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(current.getJob()));

            cmbxLaborT.getItems().clear();                
            cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(current.getJobCat()));              
        }

        if (newSel == null){

             Model_Time current = tblviewTime.getSelectionModel().getSelectedItem();

            cmbxJobCatT.getItems().clear();
            cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(current.getJob()));

            cmbxLaborT.getItems().clear();                
            cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(current.getJobCat()));

        }
    });
    addDragListeners(bertaTabPane);
}

这里是设置tableview的代码:

public void btnTimeSearch(ActionEvent event){


   //makes an instance of the toolkit needed to query user time.
   Database_RetrievesTime userData = new Database_RetrievesTime();

   //grabs data from the userinput fields to set the toolkit
   userData.setDateSelect(lblPickDateT.getValue());  
   userData.setJobBoxSelect(jobTbl.getIdByDesc(cmbxJobT.getValue()));
   userData.setLaborBoxSelect(laborTbl.getIdByDesc(cmbxLaborT.getValue()));
   userData.setJobCatSelect(jobCatTbl.getIdByDesc(cmbxJobCatT.getValue()));

    /*creates cell factories in each column and maps the cell values to the
    observable array list's IDs. The section also sets the columns up for user
    editing to be available and the methods to execute upon an editted cell
    being committed to entry.

    **NOTE:  The values are retrieved by the model class's getter methods. 
    Changing a name in the model class requires the user to update the getters.  
    Naming convention does apply.  So for example: a variable
    named cscHelp is added, it would need to have a getter called getCscHelp otherwise
    the corresponding column will return blanks.*/

    //setup ID column
    IDcol.setCellValueFactory(new PropertyValueFactory<>("ID"));

    //setup Datecol
    Datecol.setCellValueFactory(new PropertyValueFactory<>("userDate"));
    Datecol.setCellFactory(DatePickerTableCell.forTableColumn());
    //created a custom datepicker callback that can be reused throughout the code's interfaces
    Datecol.setOnEditCommit((CellEditEvent<Model_Time,LocalDate> t) -> {

            //generate a temporary variable to convert the LocalDate returned into a SimpleObjectProperty
            ObjectProperty<LocalDate> temp = new SimpleObjectProperty(t.getNewValue());
            //store the new value to the object's model
            t.getRowValue().setUserDate(temp);

            //store row's object to the change list
            Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
            //signaling to the program that a change had been made
            isChanged = true;
    });

    //job column setup
    Jobcol.setCellValueFactory(new PropertyValueFactory<>("Job"));
    Jobcol.setCellFactory(ComboBoxTableCell.forTableColumn(cmbxPopulator.getJobComboBox()));
    /*creates a combobox filled with the populated items found at initialization of the screen
    user inputs are automatically commited
    */

    Jobcol.setOnEditCommit((CellEditEvent<Model_Time,String> t) -> {

            SimpleStringProperty ssp = new SimpleStringProperty(t.getNewValue());
            //store selection to the object's model (unprocessed so values will show something like '6002: Kobota'
            t.getRowValue().setJob(ssp);
            //store row's object to the change list
            Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
            cmbxJobCatT.getItems().clear();
            cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(t.getRowValue().getJob()));
            //signaling a change has been made
            isChanged = true;
    });


    jobCatCol.setCellValueFactory(new PropertyValueFactory<>("JobCat"));
    jobCatCol.setCellFactory(ComboBoxTableCell.forTableColumn(cmbxPopulator.getJobCatComboBox(cmbxJobT.getValue())));
    jobCatCol.setOnEditCommit((CellEditEvent<Model_Time,String> t)->{

             SimpleStringProperty ssp = new SimpleStringProperty(t.getNewValue());
            //store selection to the object's model (unprocessed so values will show something like '6002: Kobota'
            t.getRowValue().setJob(ssp);
            //store row's object to the change list
            Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
            cmbxLaborT.getItems().clear();
            cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(t.getRowValue().getJob()));
            //signaling a change has been made
            isChanged = true;

    });

    //labor column setup works just like the job column
    Laborcol.setCellValueFactory(new PropertyValueFactory<>("Labor"));
    Laborcol.setCellFactory(ComboBoxTableCell.forTableColumn(cmbxPopulator.getLaborComboBox(cmbxJobCatT.getValue())));   
    Laborcol.setOnEditCommit((CellEditEvent<Model_Time,String> t) -> {

        SimpleStringProperty ssp = new SimpleStringProperty(t.getNewValue());
        t.getRowValue().setLabor(ssp);    
        Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
        t.getTableView().getItems().get(t.getTablePosition().getRow()).setLabor(ssp);
        isChanged = true;
    });

    //time column setup.  
    Timecol.setCellValueFactory(new PropertyValueFactory<>("Time"));
    Timecol.setCellFactory(TextFieldTableCell.<Model_Time, Float>forTableColumn(new FloatStringConverter()));
    Timecol.setOnEditCommit((CellEditEvent<Model_Time,Float> t) -> {

        //temp variable initialiation
        float token = t.getNewValue();
        //generate a temporary variable to convert the float return to a SimpleFloatProperty
        SimpleFloatProperty temp = new SimpleFloatProperty(token);
        //now update the row's object
        t.getRowValue().setTime(temp);
        //store row's object to the change list
        Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
        isChanged = true;
    });

    //set tableView editable
    tblviewTime.setEditable(true);

    //sets tableView to allow multiline selection
    TableViewSelectionModel<Model_Time> tvt = tblviewTime.getSelectionModel();
    tvt.setSelectionMode(SelectionMode.MULTIPLE); 

    /* checks if edits have been made.  If there are edits, it commits to the 
    database before wiping the arraylists and updating the table*/
    if (isChanged == true){
        /*makes sure there are no duplicate entries in the arraylist.  Throws out
        previous edits and takes the most recent*/
        Helper_TimShArrGen.validateMatrixEntries();
        //commits changes and resets the "isChanged" value.
        isChanged = Helper_TimShArrGen.confirmChanges(vUsers, jobTbl, jobCatTbl, laborTbl, isChanged);
    }

    /*tells the kit to run the querytime Method which uses the user input data
    and user data to search the timesheet tables and returns the user's time.*/
    if (isChanged == false){
        try {
            rs = userData.queryTime(vUsers.getConn(), vUsers.getLogin_ID());
        } catch (SQLException ex) {
            System.out.println(ex);
        }
    } else {
        return;
    }

    //sets up the observablelist for the tableview
    renderTable.setTableView(tblviewTime);
    ObservableList n = renderTable.generateTable(jobTbl, jobCatTbl, laborTbl, rs, vUsers.getConn());

    //renders the data on the screen`
    tblviewTime.setItems(n);


    Helper_TimeBreakDown breakdown = new Helper_TimeBreakDown();
    breakdown.setTblArr(n);
    breakdown.BreakDwnTim();
    lblMonTim.setText(String.valueOf(breakdown.getMon()));
    lblTuesTim.setText(String.valueOf(breakdown.getTues()));
    lblWedsTim.setText(String.valueOf(breakdown.getWeds()));
    lblThursTim.setText(String.valueOf(breakdown.getThurs()));
    lblFriTim.setText(String.valueOf(breakdown.getFri()));
    lblSatTim.setText(String.valueOf(breakdown.getSat()));
    lblSunTim.setText(String.valueOf(breakdown.getSun()));
    lblWkTim.setText(String.valueOf(breakdown.getWeek()));
}

这是来自类的段,用于处理进入列表的数据。

public ObservableList<String> getJobComboBox(){

    //clear the jobList to clean out junk data between calls
    jobList.clear();

    //looks at the job table to determine if the job is active. If active, it reads the entry
    for (count=0; count<= jobTbl.getTblArray().size()-1; count++){
       if(jobTbl.getTblArray().get(count).isActive()){ 

           /*here we scroll through the JobIDList and match the IDs to the jobtbl
           data.  When a match is hit, we grab up the number on the job and the description
           this is added to another array that will become the combobox's list
           */
           for(inCount = 0; inCount <= jobIDList.size()-1; inCount++){
               if(jobIDList.get(inCount).getCol2ID() == jobTbl.getTblArray().get(count).getID()){
                   jobList.add(jobTbl.getNumById(jobIDList.get(inCount).getCol2ID()) 
                           + ": " + jobTbl.getDescById(jobIDList.get(inCount).getCol2ID()));
               }
           }
       }
    }

    /* there's probably a better dataset to use that won't allow duplicates
    due to my lack of knowledge at this time, I elected to create a hashset, pass the arrayList
    to the hashset to wipe out duplicates, and then pass it back to the arrayList to be used in the combobox
    */
   Set<String> tmp = new HashSet();

   tmp.addAll(jobList);
   jobList.clear();
   jobList.addAll(tmp);
   jobList.add(null);

    return jobList;
}

/**
 * 
 * @param job Argument for the selected Job String
 * @return returns the ObservableList of strings for the Job Category ComboBox 
 */
public ObservableList<String> getJobCatComboBox(String job){

    //clearing out old artifact data from the previous selection
    jobCatList.clear();

    //splitting the user's string selection apart (number as string, description as string)
    int jID=0;
    if (job != null){
        if (job.contains(": ")){
            String[] tmp = job.split(": ");
            job = tmp[1];
        }
    }

    // here we comb the job Table for a matching description and vacuum up the associated ID number
    for(count=0; count<=jobTbl.getTblArray().size()-1; count++){
        if(jobTbl.getTblArray().get(count).getDesc().equals(job)){
            jID = jobTbl.getTblArray().get(count).getID();
        }
    }

    /*using that jobID number to examine the fKey in the category table.
    once we match the JobID to the fKey ID in the jobCat table, we scoop up the
    the job Category code and description to create a list for the combobox
    */
    for (count=0; count<= jobCTbl.getTblArray().size()-1; count++){  
        for(inCount = 0; inCount <= jobCatIDList.size()-1; inCount++){

            if(jobCatIDList.get(inCount).getID() == jobCTbl.getTblArray().get(count).getID()){
                if(jobCTbl.getTblArray().get(count).getfKeyId() == jID){
                    jobCatList.add(jobCTbl.getNumById(jobCatIDList.get(inCount).getID()) 
                        + ": " + jobCTbl.getDescById(jobCatIDList.get(inCount).getID()));
                }
            }
        }
    }

    //same house keeping to remove duplicates as described above
    Set<String> tmp = new HashSet();
    tmp.addAll(jobCatList);
    jobCatList.clear();
    jobCatList.addAll(tmp);
    jobCatList.add(null);

    return jobCatList;
}

/**
 * 
 * @param jobCat Argument for the selected Job Category String
 * @return ObservableList of strings for the Labor ComboBox
 */
public ObservableList<String> getLaborComboBox(String jobCat){

    //temp arrays I needed to decode the affiliated connections
    ArrayList<Integer> jCID = new ArrayList();
    ArrayList<Integer> laborID = new ArrayList();

    //house keeping to remove artifact data from previous selections
    if(jCID != null){
    jCID.clear();
    }

    if(laborID != null){
    laborID.clear();
    }

    if(laborList !=null){
        laborList.clear();
    }

    //split user's string selection for the job category (numerical code as sting, description as string)
    if(jobCat != null){
        if (jobCat.contains(": ")){
            String[] tmp = jobCat.split(": ");
            jobCat = tmp[1];
        }
    }
    //use the description to find the affiliated job category ID
    for(count=0; count<=jobCTbl.getTblArray().size()-1; count++){
        if(jobCTbl.getTblArray().get(count).getDesc().equals(jobCat)){
            jCID.add(jobCTbl.getTblArray().get(count).getID());
        }
    }

    //use the job category ID to find the associated labor IDs from the associate entity table 
    for(count=0; count<=jCLTbl.getTblArray().size()-1; count++){
        for(inCount=0; inCount<=jCID.size()-1; inCount++){
            if(jCLTbl.getTblArray().get(count).getCol1ID() == jCID.get(inCount)){
                laborID.add(jCLTbl.getTblArray().get(count).getCol2ID());
            }     
        }
    }

    //use the labor ID to look up the needed data from the labor table.
    for (count=0; count<= laborTbl.getTblArray().size()-1; count++){
        for(inCount = 0; inCount <= laborID.size()-1; inCount++){
            if(laborID.get(inCount) == laborTbl.getTblArray().get(count).getID()){
                    laborList.add(laborTbl.getNumById(laborID.get(inCount)) 
                        + ": " + laborTbl.getDescById(laborID.get(inCount)));
                }
            }
        }

    //more housekeeping to remove duplicate entries.
    Set<String> tmp = new HashSet();
    tmp.addAll(laborList);
    laborList.clear();
    laborList.addAll(tmp);
    laborList.add(null);

    return laborList;
}   

我知道这里可能有更好的办法。我还是JAVA和编码新手。我在一家小公司工作,所以我是他们雇佣的唯一一个编码员。不幸的是,这限制了我自己可以教给自己的东西,因此可能有一些更有效的方法来完成同样的任务。无论如何,如果有人能帮我弄清楚发生了什么,我们将不胜感激。

1 个答案:

答案 0 :(得分:0)

这个问题的答案实际上是在jobcatCol的SetOnEdit部分找到的。

经过仔细检查和大量调试,我发现了这一行

 t.getRowValue().setJobCat(ssp);

实际上应该是

public class JobComboBoxCell extends TableCell<Model_Time, String>
{

    private ComboBox<String> comboBox;
    private Helper_UserSpecificTimDat cmbxPopulator = new Helper_UserSpecificTimDat();

    public JobComboBoxCell(Helper_UserSpecificTimDat cmbxPopulator)
    {
        comboBox = new ComboBox<>();
        this.cmbxPopulator = cmbxPopulator;
    }


    @Override
    public void startEdit()
    {
        if ( !isEmpty() )
        {
            super.startEdit();


            comboBox.setItems( cmbxPopulator.getJobComboBox() );
            comboBox.getSelectionModel().select( this.getItem() );

            comboBox.focusedProperty().addListener( new ChangeListener<Boolean>()
            {
                @Override
                public void changed( ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue )
                {
                    if ( !newValue )
                    {
                        commitEdit( comboBox.getSelectionModel().getSelectedItem() );
                    }
                }
            } );

            setText( null );
            setGraphic( comboBox );
        }
    }


    @Override
    public void cancelEdit()
    {
        super.cancelEdit();

        setText( ( String ) this.getItem() );
        setGraphic( null );
    }


    @Override
    public void updateItem( String item, boolean empty )
    {
        super.updateItem( item, empty );

        if ( empty )
        {
            setText( null );
            setGraphic( null );
        }
        else
        {
            if ( isEditing() )
            {
                setText( null );
                setGraphic( comboBox );
            }
            else
            {
                setText( this.getItem() );
                setGraphic( null );
            }
        }
    }

}

我还选择放弃ComboBoxTableCell API并为每个单元格编写自己的组合框实现。这是一个非常基本的版本:

/* 
   Line 1: this is line one
   Line 2: this could also be line one
   Line 3: this is the line I'm interested in because is the one 
   Line 4: just some random line
   Line 5: this is not the line I want, it's not the one
*/

此代码由Uluk Biy的回复提供:Populate combo box list dynamically for each row in javaFx table view

我根据自己的需要调整了一些代码。这解决了值从作业类别字段和从作业类别字段传输到作业字段的数据消失的问题。

这是我不得不排除故障的代码之一。它结合了ComboBoxTableCell的运行方式,我的组合框的动态数据,以及我调用的那个setter的漏洞。这是关于一个完美的流感风暴,该计划没有例外的结果。

感谢您的帮助