2015-04-17 18 views
5

Programımda birkaç satır görüntülemek için tablo görünümünü kullandım. Programım muhasebe için kullanılır ve bildiğiniz gibi bir sürü veri girişi vardır ve tablo görünümünü kullandım ve çok fazla sorunla karşılaştım:.JavaFX TableView Tek tıklatma ve otomatik ekleme satırı ile düzenle?

Sorun 1: Kullanıcı bir değeri değiştirmek istediğinde, kullanıcının herhangi bir satırı seçmesini ve yazmaya başlamasını istediğim hücreyi düzenlemek için çift tıklatacağım.

Sorun 2: Programda kullanıcı 100 günlük satır ekleyebilir, örneğin satır eklediğinde otomatik olarak satır eklemeye yönelik bir stratejiye ihtiyacım var. Veri girişini tamamlamak için geçerli satırın altına boş bir satır eklemelidir kolayca .

Lütfen bu sorunları çözmeme yardımcı olun, her gün çok fazla veri girmem için kullanıyorum. teşekkürler.

+0

teşekkür pek @James_D o ı ile birleştirmek için çalışacağız gerçekten iyi uygulama s benim ihtiyaçlarımı karşılamak için benim uygulama. –

cevap

8

İşte

  • kısa sürede odaklanmış hücreye
  • üzerine yazarken düzenleme moduna girer sen (sadece bir örnek olarak) son sırada enter tuşuna yeni bir satır oluşturan bir örnek bu. Alternatif olarak, yeni bir satır eklemek için bir düğmeyi tıklayabilirsiniz. Yeni bir satır oluşturmak için son satırda sekmeyi kullanmak isterseniz, kodu uygun şekilde değiştirmeniz gerekecektir.

Modelinizde göründükleri için boş satırları kullanmamanızı öneriyorum.

InlineEditingWithDynamicRowAdding.java

import javafx.application.Application; 
import javafx.scene.control.TableView; 
import javafx.collections.ObservableList; 
import javafx.stage.Stage; 
import javafx.util.Callback; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableCell; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.beans.property.DoubleProperty; 
import javafx.collections.FXCollections; 
import javafx.scene.input.KeyEvent; 
import javafx.event.EventHandler; 
import javafx.scene.control.SelectionMode; 
import javafx.scene.input.KeyCode; 
import javafx.scene.control.TablePosition; 
import javafx.scene.layout.FlowPane; 
import javafx.scene.control.Button; 
import javafx.scene.layout.BorderPane; 
import javafx.util.StringConverter; 
import javafx.scene.Scene; 
import javafx.scene.control.cell.TextFieldTableCell; 

public class InlineEditingWithDynamicRowAdding extends Application { 

    private final ObservableList<Data> data = 
     FXCollections.observableArrayList(
       new Data(1.,5.), 
       new Data(2.,6.), 
       new Data(3.,7.), 
       new Data(4.,8.) 
     ); 

    private TableView<Data> table; 

    @Override 
    public void start(Stage stage) { 

     // create edtiable table 
     table = new TableView<Data>(); 
     table.setEditable(true); 

     // column 1 contains numbers 
     TableColumn<Data, Number> number1Col = new TableColumn<>("Number 1"); 
     number1Col.setMinWidth(100); 
     number1Col.setCellValueFactory(cellData -> cellData.getValue().number1Property()); 
     number1Col.setCellFactory(createNumberCellFactory()); 

     // column 2 contains numbers 
     TableColumn<Data, Number> number2Col = new TableColumn<>("Number 2"); 
     number2Col.setMinWidth(100); 
     number2Col.setCellValueFactory(cellData -> cellData.getValue().number2Property()); 
     number2Col.setCellFactory(createNumberCellFactory()); 

     // add columns & data to table 
     table.setItems(data); 
     table.getColumns().addAll(number1Col, number2Col); 




     // switch to edit mode on keypress 
     // this must be KeyEvent.KEY_PRESSED so that the key gets forwarded to the editing cell; it wouldn't be forwarded on KEY_RELEASED 
     table.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() { 
      @Override 
      public void handle(KeyEvent event) { 

       if(event.getCode() == KeyCode.ENTER) { 
//     event.consume(); // don't consume the event or else the values won't be updated; 
        return; 
       } 

       // switch to edit mode on keypress, but only if we aren't already in edit mode 
       if(table.getEditingCell() == null) { 
        if(event.getCode().isLetterKey() || event.getCode().isDigitKey()) { 

         TablePosition focusedCellPosition = table.getFocusModel().getFocusedCell(); 
         table.edit(focusedCellPosition.getRow(), focusedCellPosition.getTableColumn()); 

        } 
       } 

      } 
     }); 

     table.addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() { 
      @Override 
      public void handle(KeyEvent event) { 

       if(event.getCode() == KeyCode.ENTER) { 


        // move focus & selection 
        // we need to clear the current selection first or else the selection would be added to the current selection since we are in multi selection mode 
        TablePosition pos = table.getFocusModel().getFocusedCell(); 

        if (pos.getRow() == -1) { 
         table.getSelectionModel().select(0); 
        } 
        // add new row when we are at the last row 
        else if (pos.getRow() == table.getItems().size() -1) { 
         addRow(); 
        } 
        // select next row, but same column as the current selection 
        else if (pos.getRow() < table.getItems().size() -1) { 
         table.getSelectionModel().clearAndSelect(pos.getRow() + 1, pos.getTableColumn()); 
        } 


       } 

      } 
     });  

     // single cell selection mode 
     table.getSelectionModel().setCellSelectionEnabled(true); 

     // add row index column as 1st column 
     // ------------------------------------- 
     TableColumn<Data, Data> indexCol = new TableColumn<Data, Data>("#"); 

     indexCol.setCellFactory(new Callback<TableColumn<Data, Data>, TableCell<Data, Data>>() { 
      @Override public TableCell<Data, Data> call(TableColumn<Data, Data> param) { 
       return new TableCell<Data, Data>() { 
        @Override protected void updateItem(Data item, boolean empty) { 
         super.updateItem(item, empty); 

         if (this.getTableRow() != null) { 

          int index = this.getTableRow().getIndex(); 

          if(index < table.getItems().size()) { 
           int rowNum = index + 1; 
           setText(String.valueOf(rowNum)); 
          } else { 
           setText(""); 
          } 

         } else { 
          setText(""); 
         } 

        } 
       }; 
      } 
     }); 

     table.getColumns().add(0, indexCol); // number column is at index 0 

     // allow multi selection 
     table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 

     // buttons 
     // -------------------------------------------- 
     FlowPane buttonBar = new FlowPane(); 

     // add new row button 
     Button addButton = new Button("Add"); 
     addButton.setOnAction(e -> { 
      addRow(); 
     }); 
     addButton.setFocusTraversable(false);// don't let it get the focus or else the table would lose it when we click the button and we's have to request the focus on the table in the event handler 

     // remove selected rows button 
     Button removeButton = new Button("Remove"); 
     removeButton.setOnAction(e -> { 
      removeSelectedRows(); 
     }); 
     removeButton.setFocusTraversable(false);// don't let it get the focus or else the table would lose it when we click the button and we's have to request the focus on the table in the event handler 

     buttonBar.getChildren().addAll(addButton, removeButton); 

     // add nodes to stage 
     BorderPane root = new BorderPane(); 
     root.setCenter(table); 
     root.setBottom(buttonBar); 

     Scene scene = new Scene(root, 800,600); 
     scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 

     stage.setScene(scene); 
     stage.show(); 


     // select first cell 
     // TODO: why isn't this selecting the 1st cell in the index column? 
     table.getSelectionModel().selectFirst(); 

    } 

    /** 
    * Insert a new default row to the table, select a cell of it and scroll to it. 
    */ 
    public void addRow() { 

     // get current position 
     TablePosition pos = table.getFocusModel().getFocusedCell(); 

     // clear current selection 
     table.getSelectionModel().clearSelection(); 

     // create new record and add it to the model 
     Data data = new Data(0d,0d); 
     table.getItems().add(data); 

     // get last row 
     int row = table.getItems().size() - 1; 
     table.getSelectionModel().select(row, pos.getTableColumn()); 

     // scroll to new row 
     table.scrollTo(data); 

    } 

    /** 
    * Remove all selected rows. 
    */ 
    public void removeSelectedRows() { 

     table.getItems().removeAll(table.getSelectionModel().getSelectedItems()); 

     // table selects by index, so we have to clear the selection or else items with that index would be selected 
     table.getSelectionModel().clearSelection(); 


    } 

    /** 
    * Number cell factory which converts strings to numbers and vice versa. 
    * @return 
    */ 
    private Callback<TableColumn<Data, Number>, TableCell<Data, Number>> createNumberCellFactory() { 

     Callback<TableColumn<Data, Number>, TableCell<Data, Number>> factory = TextFieldTableCell.forTableColumn(new StringConverter<Number>() { 

      @Override 
      public Number fromString(String string) { 
       return Double.parseDouble(string); 
      } 

      @Override 
      public String toString(Number object) { 
       return object.toString(); 
      } 
     }); 

     return factory; 
    } 

    /** 
    * Table data container 
    */ 
    public static class Data { 

     private final SimpleDoubleProperty number1; 
     private final SimpleDoubleProperty number2; 

     private Data(Double number1, Double number2) { 
      this.number1 = new SimpleDoubleProperty(number1); 
      this.number2 = new SimpleDoubleProperty(number2); 
     } 

     public final DoubleProperty number1Property() { 
      return this.number1; 
     } 

     public final double getNumber1() { 
      return this.number1Property().get(); 
     } 

     public final void setNumber1(final double number1) { 
      this.number1Property().set(number1); 
     } 

     public final DoubleProperty number2Property() { 
      return this.number2; 
     } 

     public final double getNumber2() { 
      return this.number2Property().get(); 
     } 

     public final void setNumber2(final double number2) { 
      this.number2Property().set(number2); 
     } 


    } 

    public static void main(String[] args) { 
     launch(args); 
    } 


} 

application.css

/* edit cell appearance */ 

/* If the padding is 0, then there's a grey area. If you set it to 2, then there won't be a great area. 
* However if you use a border color, then the border requires its size, so the padding is set to 2 - 1 = 1. 
* You have to toy around with the border. If necessary give it a width of 2 and make it the same color as the background color. 
*/ 
.text-field-table-cell .text-field { 
    -fx-padding: 1; 
    -fx-border-color:red; 
    -fx-border-width:1; 
    -fx-background-color:yellow; 
} 
.table-cell:focused { 
    -fx-padding: 0; 
} 

/* right-align the cell content in view mode */ 
.table-cell { 
    -fx-alignment: CENTER-RIGHT; 
} 
/* right-align the cell content in edit mode */ 
.text-field { 
    -fx-alignment: CENTER-RIGHT; 
} 

/* colorize background only of rows which have data */ 
.table-row-cell:empty { 
    -fx-background-color: white; 
} 

.table-row-cell:empty .table-cell { 
    -fx-border-width: 0px; 
} 

enter image description here

+0

Bu örnek için gerçekten çok teşekkürlerRoland benim için çok iyi ama satırların sayısı görünümü aştığında bir sorun var com.sun.javafx.scene.control.skin.VirtualFlow addTrailingCells INFO: index maxCellCount'u aşıyor. Sınıf için boy hesaplamalarını kontrol edin javafx.scene.control.TableRow Bilmiyorum ama işe yaradı ve son sıraya ilerleyin –

+0

@Hassan Kbbewar: Biliyorum, zaten oluşturdum [bir soru ve javafx jira'da bir sorun] Kodu yazdıktan sonra http://stackoverflow.com/questions/29714267/how-to-correctly-add-new-data-to-tableview-and-scroll-to-it). İşe yarıyor ama çirkin değil. – Roland

+0

@Roland Harika çalışma. Eklendiğinde yeni eklenen satırı düzenleme modunda nasıl yapabiliriz? –