取消表编辑后,组合框选择将消失



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

工作>工作类别>劳动力。

我有一个非常特殊的问题。编辑表格时,您可以单击任何框以获取基于其他字段的可用选择的相应列表。 这工作正常。 它爆炸的地方是当没有做出选择时。 为了使事情更有趣,它只影响工作和工作类别组合框,劳动力框完美运行。

症状:

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

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

以下是重现症状的步骤:

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

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

新选择制作了 IMG

3) 单击作业框并启用编辑

4)单击作业框,然后单击同一行中的作业类别或人工框取消编辑

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

失去工作类别/工作选择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);
}

下面是设置表视图的代码:

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和编码不熟悉。 我在一家小公司工作,所以我是他们唯一的程序员。 不幸的是,这限制了我能自学的东西,所以可能有一些更有效的方法来完成同样的任务。 无论如何,如果有人能帮助我弄清楚发生了什么,将不胜感激。

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

经过仔细检查和大量调试,我发现这条线

 t.getRowValue().setJob(ssp);

实际上应该是

 t.getRowValue().setJobCat(ssp);

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

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 );
            }
        }
    }
}

这段代码是由 Uluk Biy 在 thread:在 javaFx 表视图中为每一行动态填充组合框列表的响应提供的

稍微调整了他的代码,以专门满足我的需求。 这解决了值从作业类别字段以及从作业类别字段传输到作业字段的数据中消失的问题。

这是我必须排除故障的较难的代码之一。 这是ComboBoxTableCell的运作方式,我的组合框的动态数据以及我调用的哪个二传手的滑倒的组合。 这是一场完美的风暴,因此该计划没有例外。

谢谢你的帮助

最新更新