2017-09-28 1 views
3

J'ai une vue de table dans laquelle vous pouvez faire glisser des lignes pour repositionner les données. Le problème consiste à faire défiler automatiquement la vue de la table vers le haut ou vers le bas lorsque vous faites glisser la ligne au-dessus ou en dessous des enregistrements dans le port de vue.Table de défilement automatique JavaFX vers le haut ou le bas lorsque vous faites glisser des lignes à l'extérieur de la fenêtre

Des idées comment cela peut être réalisé dans JavaFX?

categoryProductsTable.setRowFactory(tv -> { 

     TableRow<EasyCatalogueRow> row = new TableRow<EasyCatalogueRow>(); 

     row.setOnDragDetected(event -> { 
      if (!row.isEmpty()) { 
       Dragboard db = row.startDragAndDrop(TransferMode.MOVE); 
       db.setDragView(row.snapshot(null, null)); 
       ClipboardContent cc = new ClipboardContent(); 
       cc.put(SERIALIZED_MIME_TYPE, new ArrayList<Integer>(categoryProductsTable.getSelectionModel().getSelectedIndices())); 
       db.setContent(cc); 
       event.consume(); 
      } 
     }); 

     row.setOnDragOver(event -> { 
      Dragboard db = event.getDragboard(); 
      if (db.hasContent(SERIALIZED_MIME_TYPE)) { 
       event.acceptTransferModes(TransferMode.COPY_OR_MOVE); 
       event.consume(); 

      } 
     }); 

     row.setOnDragDropped(event -> { 
      Dragboard db = event.getDragboard(); 
      if (db.hasContent(SERIALIZED_MIME_TYPE)) { 
       int dropIndex; 

       if (row.isEmpty()) { 
        dropIndex = categoryProductsTable.getItems().size(); 
       } else { 
        dropIndex = row.getIndex(); 
       } 

       ArrayList<Integer> indexes = (ArrayList<Integer>) db.getContent(SERIALIZED_MIME_TYPE); 

       for (int index : indexes) { 
        EasyCatalogueRow draggedProduct = categoryProductsTable.getItems().remove(index); 
        categoryProductsTable.getItems().add(dropIndex, draggedProduct); 
        dropIndex++; 
       } 

       event.setDropCompleted(true); 
       categoryProductsTable.getSelectionModel().select(null); 
       event.consume(); 

       updateSortIndicies(); 

      } 
     }); 

     return row; 
    }); 

Répondre

1

Ok, donc je l'ai compris. Je ne suis pas sûr que ce soit la meilleure façon de le faire, mais cela fonctionne. Fondamentalement j'ai ajouté un écouteur d'événement à la vue de table qui manipule l'événement de DragOver. Cet événement est déclenché tout en faisant glisser les lignes dans la vue de la table. Essentiellement, pendant que le drag est en cours, je travaille si nous avons besoin de faire défiler vers le haut ou vers le bas ou de ne pas faire défiler du tout. Ceci est fait en travaillant si les éléments en train d'être traînés sont dans les zones de proximité supérieure ou inférieure de la vue de la table.

Un thread séparé contrôlé par l'écouteur d'événement DragOver gère ensuite le défilement.

public class CategoryProductsReportController extends ReportController implements Initializable { 

    @FXML 
    private TableView<EasyCatalogueRow> categoryProductsTable; 

    private ObservableList<EasyCatalogueRow> categoryProducts = FXCollections.observableArrayList(); 

    public enum ScrollMode { 
     UP, DOWN, NONE 
    } 

    private AutoScrollableTableThread autoScrollThread = null; 

    /** 
    * Initializes the controller class. 
    */ 
    @Override 
    public void initialize(URL url, ResourceBundle rb) { 

     initProductTable(); 

    } 

    private void initProductTable() { 

     categoryProductsTable.setItems(categoryProducts); 
     ... 

     ... 

     // Multi Row Drag And Drop To Allow Items To Be Re-Positioned Within 
     // Table 
     categoryProductsTable.setRowFactory(tv -> { 

      TableRow<EasyCatalogueRow> row = new TableRow<EasyCatalogueRow>(); 

      row.setOnDragDetected(event -> { 
       if (!row.isEmpty()) { 
        Dragboard db = row.startDragAndDrop(TransferMode.MOVE); 
        db.setDragView(row.snapshot(null, null)); 
        ClipboardContent cc = new ClipboardContent(); 
        cc.put(SERIALIZED_MIME_TYPE, new ArrayList<Integer>(categoryProductsTable.getSelectionModel().getSelectedIndices())); 
        db.setContent(cc); 
        event.consume(); 
       } 
      }); 

      row.setOnDragOver(event -> { 
       Dragboard db = event.getDragboard(); 
       if (db.hasContent(SERIALIZED_MIME_TYPE)) { 
        event.acceptTransferModes(TransferMode.COPY_OR_MOVE); 
        event.consume(); 

       } 
      }); 

      row.setOnDragDropped(event -> { 
       Dragboard db = event.getDragboard(); 
       if (db.hasContent(SERIALIZED_MIME_TYPE)) { 
        int dropIndex; 

        if (row.isEmpty()) { 
         dropIndex = categoryProductsTable.getItems().size(); 
        } else { 
         dropIndex = row.getIndex(); 
        } 

        ArrayList<Integer> indexes = (ArrayList<Integer>) db.getContent(SERIALIZED_MIME_TYPE); 

        for (int index : indexes) { 
         EasyCatalogueRow draggedProduct = categoryProductsTable.getItems().remove(index); 
         categoryProductsTable.getItems().add(dropIndex, draggedProduct); 
         dropIndex++; 
        } 

        event.setDropCompleted(true); 
        categoryProductsTable.getSelectionModel().select(null); 
        event.consume(); 

        updateSortIndicies(); 

       } 
      }); 

      return row; 
     }); 

     categoryProductsTable.addEventFilter(DragEvent.DRAG_DROPPED, event -> { 
      if (autoScrollThread != null) { 
       autoScrollThread.stopScrolling(); 
       autoScrollThread = null; 
      } 
     }); 

     categoryProductsTable.addEventFilter(DragEvent.DRAG_OVER, event -> { 

      double proximity = 100; 

      Bounds tableBounds = categoryProductsTable.getLayoutBounds(); 

      double dragY = event.getY(); 

      //System.out.println(tableBounds.getMinY() + " --> " + tableBounds.getMaxY() + " --> " + dragY); 
      // Area At Top Of Table View. i.e Initiate Upwards Auto Scroll If 
      // We Detect Anything Being Dragged Above This Line. 
      double topYProximity = tableBounds.getMinY() + proximity; 

      // Area At Bottom Of Table View. i.e Initiate Downwards Auto Scroll If 
      // We Detect Anything Being Dragged Below This Line. 
      double bottomYProximity = tableBounds.getMaxY() - proximity; 

      // We Now Make Use Of A Thread To Scroll The Table Up Or Down If 
      // The Objects Being Dragged Are Within The Upper Or Lower 
      // Proximity Areas 
      if (dragY < topYProximity) { 
       // We Need To Scroll Up 
       if (autoScrollThread == null) { 
        autoScrollThread = new AutoScrollableTableThread(categoryProductsTable); 
        autoScrollThread.scrollUp(); 
        autoScrollThread.start(); 
       } 

      } else if (dragY > bottomYProximity) { 
       // We Need To Scroll Down 
       if (autoScrollThread == null) { 
        autoScrollThread = new AutoScrollableTableThread(categoryProductsTable); 
        autoScrollThread.scrollDown(); 
        autoScrollThread.start(); 
       } 

      } else { 
       // No Auto Scroll Required We Are Within Bounds 
       if (autoScrollThread != null) { 
        autoScrollThread.stopScrolling(); 
        autoScrollThread = null; 
       } 
      } 

     }); 

    } 
} 

class AutoScrollableTableThread extends Thread { 

    private boolean running = true; 
    private ScrollMode scrollMode = ScrollMode.NONE; 
    private ScrollBar verticalScrollBar = null; 

    public AutoScrollableTableThread(TableView tableView) { 
     super(); 
     setDaemon(true); 
     verticalScrollBar = (ScrollBar) tableView.lookup(".scroll-bar:vertical"); 

    } 

    @Override 
    public void run() { 

     try { 
      Thread.sleep(300); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 

     while (running) { 

      Platform.runLater(() -> { 
       if (verticalScrollBar != null && scrollMode == ScrollMode.UP) { 
        verticalScrollBar.setValue(verticalScrollBar.getValue() - 0.01); 
       } else if (verticalScrollBar != null && scrollMode == ScrollMode.DOWN) { 
        verticalScrollBar.setValue(verticalScrollBar.getValue() + 0.01); 
       } 
      }); 

      try { 
       sleep(50); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    public void scrollUp() { 
     System.out.println("Start To Scroll Up"); 
     scrollMode = ScrollMode.UP; 
     running = true; 
    } 

    public void scrollDown() { 
     System.out.println("Start To Scroll Down"); 
     scrollMode = ScrollMode.DOWN; 
     running = true; 
    } 

    public void stopScrolling() { 
     System.out.println("Stop Scrolling"); 
     running = false; 
     scrollMode = ScrollMode.NONE; 
    } 

}