2016-09-09 41 views
0

我目前正在使用TableView,包括RadioButton在一個TableCell中的應用程序。爲此,我創建了自己的RadioButtonCell類。我也有一個「添加新行」 - 按鈕讓用戶添加一些額外的行。第三次單擊「添加」按鈕後,我得到的行數多於行數。我在代碼中找不到錯誤。JavaFX - 具有添加數據按鈕的TableCell中的RadioButtons

這裏點擊Button第三時間後的截圖:

part of the tableview

RadioButtonCell:

import java.util.EnumSet; 

import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.geometry.Pos; 
import javafx.scene.control.RadioButton; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.Toggle; 
import javafx.scene.control.ToggleGroup; 
import javafx.scene.layout.HBox; 

public class RadioButtonCell<S,T extends Enum<T>> extends TableCell<S,T>{ 

    private EnumSet<T> enumeration; 

    public RadioButtonCell(EnumSet<T> enumeration) { 
     this.enumeration = enumeration; 
    } 

    @Override 
    protected void updateItem(T item, boolean empty) 
    { 
     super.updateItem(item, empty); 
     if (!empty) 
     { 
      // GUI 
      HBox hb = new HBox(7); 
      hb.setAlignment(Pos.CENTER); 
      final ToggleGroup group = new ToggleGroup(); 

      // create a radio button for each 'element' of the enumeration 
      for (Enum<T> enumElement : enumeration) { 
       RadioButton radioButton = new RadioButton(enumElement.toString()); 
       radioButton.setUserData(enumElement); 
       radioButton.setToggleGroup(group); 
       hb.getChildren().add(radioButton); 
       if (enumElement.equals(item)) { 
        radioButton.setSelected(true); 
       } 
      } 

      // issue events on change of the selected radio button 
      group.selectedToggleProperty().addListener(new ChangeListener<Toggle>() { 

       @SuppressWarnings("unchecked") 
       @Override 
       public void changed(ObservableValue<? extends Toggle> observable, 
         Toggle oldValue, Toggle newValue) { 
        getTableView().edit(getIndex(), getTableColumn()); 
        RadioButtonCell.this.commitEdit((T) newValue.getUserData()); 
       } 
      }); 
      setGraphic(hb); 
     } 
    } 
} 

型號:

public class Points { 

    private final SimpleObjectProperty<Participation> participation = new SimpleObjectProperty<Participation>(); // radio buttons 


    public static enum Participation { 
     NONE, HALO, BORDER; 

     public String toString() { 
      return super.toString().toLowerCase(); 
     }; 
    } 

    /** 
    * Constructor. 
    * @param <Participation> 
    */ 
    public Points(Participation p) { 

     this.participation.setValue(p); 

    public void setParticipation(Participation p){ 
     participation.set(p); 
    } 

    public Participation getParticipation(){ 
     return participation.get(); 
    } 

    public SimpleObjectProperty<Participation> ParticipationProperty() { 
     return participation; 
    } 
} 

FXML:

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.control.Button?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.control.SplitPane?> 
<?import javafx.scene.control.Tab?> 
<?import javafx.scene.control.TabPane?> 
<?import javafx.scene.control.TableColumn?> 
<?import javafx.scene.control.TableView?> 
<?import javafx.scene.control.TextField?> 
<?import javafx.scene.layout.AnchorPane?> 
<?import javafx.scene.layout.HBox?> 
<?import javafx.scene.layout.VBox?> 

<VBox prefHeight="900.0" prefWidth="1250.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="address.view.DataOverviewController"> 
    <children> 
     <SplitPane fx:id="splitPaneVertical" prefHeight="776.0" prefWidth="1200.0" VBox.vgrow="ALWAYS"> 
     <items> 
      <TabPane fx:id="tabPane" stylesheets="@Theme.css"> 
       <tabs> 
        <Tab text="Points"> 
        <content> 
         <SplitPane fx:id="splitPaneHorizontal" dividerPositions="0.949874686716792" orientation="VERTICAL" stylesheets="@Theme.css"> 
          <items> 
           <TableView fx:id="pointsDataTable"> 
           <columns>         
            <TableColumn fx:id="pointsBackgroundColumn" prefWidth="200.0" resizable="false" text="Background" />         
           </columns>            
           </TableView> 
          <AnchorPane SplitPane.resizableWithParent="false"> 
           <children> 
            <HBox fx:id="pointsHBoxButton" alignment="CENTER" prefHeight="35.0" prefWidth="1016.0" spacing="20.0" stylesheets="@Theme.css" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> 
             <children> 
              <Button fx:id="pointsAddButton" mnemonicParsing="false" onAction="#handleAddPoints" text="Add" />      
            </children> 
           </HBox> 
          </children> 
          </AnchorPane> 
         </items> 
        </SplitPane> 
       </content> 
       </Tab> 
      </tabs> 
     </TabPane> 
    </items> 
    </SplitPane> 

控制器:

public class DataOverviewController { 
     @FXML 
     private TableView<Points> pointsDataTable; 

     @FXML 
     private TableColumn<Points, Participation> pointsBackgroundColumn; 

     @FXML 
     private Button pointsButtonAdd; 

     public DataOverviewController() { 
     } 

     @FXML 
     private void initialize() { 
      // select multipe rows, make rows editable 
      pointsDataTable.setEditable(true); 
      pointsDataTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 
      linesDataTable.setEditable(true); 

      pointsBackgroundColumn.setCellFactory((param) -> new RadioButtonCell<Points, Participation>(EnumSet.allOf(Participation.class))); 
      pointsBackgroundColumn.setCellValueFactory(new PropertyValueFactory<Points, Participation>("Participation")); 
      pointsBackgroundColumn.setOnEditCommit(
         new EventHandler<CellEditEvent<Points, Participation>>() { 
          @Override 
          public void handle(CellEditEvent<Points, Participation> t) { 
           ((Points) t.getTableView().getItems().get(
            t.getTablePosition().getRow()) 
            ).setParticipation(t.getNewValue()); 
          } 
         } 
        ); 

     public void setMainConfig(MainConfig mainConfig) { 
      // Add observable list data to the table 
      pointsDataTable.setItems(mainConfig.getTableDataPoints()); 
     } 

     @FXML 
     private void handleAddPoints() { 
      // create new record and add it to the tableview 
      Points dataPoints = new Points(0, "Points", "TabFileName.tab",Participation.NONE, false, false, 18, "new"); 
      pointsDataTable.getItems().add(dataPoints); 
     } 
    } 
} 

我我的代碼減少的重要部件。也許有人可以幫忙? 謝謝。

回答

1

可以添加以及從TableCell s中刪除的項目。這意味着您需要處理TableCell變空的情況,方法是在添加項目時取消對單元格所做的任何更改。否則可能有TableCell,看起來好像它們包含一個項目,儘管它們實際上是空的。

一個updateItem方法應該是這樣的:

@Override 
protected void updateItem(T item, boolean empty) { 
    super.updateItem(item, empty); 

    if (empty) { 
     // modifications to restore the empty state 
    } else { 
     // customized way of displaying the item 
    } 
} 

而且我不建議重新創建Node S代表在小區的每個項目改變時顯示的項目,因爲這意味着你將有一個很多不必要的節點創建,這是TableView正試圖通過重用單元避免的事情。將它們存放在田間,並保存起來以備後用。