2015-05-08 17 views
6

ProblemaCome rilevare il movimento del mouse sul nodo mentre si preme il pulsante?

È possibile aggiungere un listener di eventi per un nodo che rileva il movimento del mouse su di esso. Questo non funziona se si preme un pulsante del mouse prima di spostarsi sul nodo.

Domanda

Qualcuno sa come rilevare il movimento del mouse mentre si tiene premuto il tasto? Finora ho trovato una soluzione solo usando l'evento MOUSE_DRAGGED e poi invece di usare getSource() usando getPickResult() e valutando i dati PickResult.

Ecco il codice inclusa la soluzione di Uluk. La soluzione vecchio e nuovo sono commutabili tramite l'useNewVersion (versione del Uluk) booleano:

import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.scene.Node; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.input.PickResult; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.Pane; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class Main extends Application { 

    boolean useNewVersion= true; 

    int rows = 10; 
    int columns = 20; 
    double width = 1024; 
    double height = 768; 

    @Override 
    public void start(Stage primaryStage) { 
     try { 
      BorderPane root = new BorderPane(); 

      // create grid 
      Grid grid = new Grid(columns, rows, width, height); 

      MouseGestures mg = new MouseGestures(); 

      // fill grid 
      for (int row = 0; row < rows; row++) { 
       for (int column = 0; column < columns; column++) { 

        Cell cell = new Cell(column, row); 

        mg.makePaintable(cell); 

        grid.add(cell, column, row); 
       } 
      } 

      root.setCenter(grid); 

      // create scene and stage 
      Scene scene = new Scene(root, width, height); 
      scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 



     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

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

    private class Grid extends Pane { 

     int rows; 
     int columns; 

     double width; 
     double height; 

     Cell[][] cells; 

     public Grid(int columns, int rows, double width, double height) { 

      this.columns = columns; 
      this.rows = rows; 
      this.width = width; 
      this.height = height; 

      cells = new Cell[rows][columns]; 

     } 

     /** 
     * Add cell to array and to the UI. 
     */ 
     public void add(Cell cell, int column, int row) { 

      cells[row][column] = cell; 

      double w = width/columns; 
      double h = height/rows; 
      double x = w * column; 
      double y = h * row; 

      cell.setLayoutX(x); 
      cell.setLayoutY(y); 
      cell.setPrefWidth(w); 
      cell.setPrefHeight(h); 

      getChildren().add(cell); 

     } 

    } 

    private class Cell extends StackPane { 

     int column; 
     int row; 

     public Cell(int column, int row) { 

      this.column = column; 
      this.row = row; 

      getStyleClass().add("cell"); 

      Label label = new Label(this.toString()); 

      getChildren().add(label); 
     } 

     public void highlight() { 
      getStyleClass().add("cell-highlight"); 
     } 

     public void unhighlight() { 
      getStyleClass().remove("cell-highlight"); 
     } 

     public String toString() { 
      return this.column + "/" + this.row; 
     } 
    } 

    public class MouseGestures { 

     public void makePaintable(Node node) { 

      if(useNewVersion) { 

       node.setOnMousePressed(onMousePressedEventHandler); 
       node.setOnDragDetected(onDragDetectedEventHandler); 
       node.setOnMouseDragEntered(onMouseDragEnteredEventHandler); 

      } else { 

       node.setOnMousePressed(onMousePressedEventHandler); 
       node.setOnMouseDragged(onMouseDraggedEventHandler); 
       node.setOnMouseReleased(onMouseReleasedEventHandler); 

      } 

     } 

     /* old version */ 

     EventHandler<MouseEvent> onMousePressedEventHandler = event -> { 

      Cell cell = (Cell) event.getSource(); 

      if(event.isPrimaryButtonDown()) { 
       cell.highlight(); 
      } else if(event.isSecondaryButtonDown()) { 
       cell.unhighlight(); 
      } 
     }; 

     EventHandler<MouseEvent> onMouseDraggedEventHandler = event -> { 

      PickResult pickResult = event.getPickResult(); 
      Node node = pickResult.getIntersectedNode(); 

      if(node instanceof Cell) { 

       Cell cell = (Cell) node; 

       if(event.isPrimaryButtonDown()) { 
        cell.highlight(); 
       } else if(event.isSecondaryButtonDown()) { 
        cell.unhighlight(); 
       }  

      } 

     }; 

     EventHandler<MouseEvent> onMouseReleasedEventHandler = event -> { 
     }; 

     EventHandler<MouseEvent> onDragDetectedEventHandler = event -> { 

      Cell cell = (Cell) event.getSource(); 
      cell.startFullDrag(); 

     }; 

     EventHandler<MouseEvent> onMouseDragEnteredEventHandler = event -> { 

      Cell cell = (Cell) event.getSource(); 

      if(event.isPrimaryButtonDown()) { 
       cell.highlight(); 
      } else if(event.isSecondaryButtonDown()) { 
       cell.unhighlight(); 
      }  

     }; 

    } 

} 

Alla fine si dovrebbe essere in grado di dipingere tramite il pulsante principale del mouse e cancellare la vernice tramite pulsante del mouse secondario:

enter image description here

+1

È il 'node' diverso dal' Button'? Non ho esattamente la tua domanda. Stai provando a leggere il movimento del mouse sullo stesso pulsante quando viene premuto? – ItachiUchiha

+3

Il nodo che gestisce l'evento DRAG_DETECTED iniziale deve richiamare sourceNode.startFullDrag(), quindi il nodo di destinazione sarà in grado di gestire gli eventi MOUSE_DRAG_OVER con il metodo targetNode.setOnMouseDragOver(). –

+1

@ ItachiUchia: intendevo il pulsante del mouse. L'ho cambiato e ho aggiunto il codice inclusa la versione di Uluk. Ne avevo bisogno per l'algoritmo A * che ho postato ieri, in modo che sia più facile dipingere diversi tipi di muri con il semplice trascinamento del mouse (pur avendo il pulsante principale premuto). Funzionava, ma usare PickResult era strano. – Roland

risposta

2

la (sorgente) nodo che gestisce l'iniziale DRAG_DETECTED evento dovrebbe invocare sourceNode.startFullDrag(), allora il nodo di destinazione sarà in grado di gestire una delle MouseDragEvent s, ad esempio MOUSE_DRAG_OVER o MOUSE_DRAG_ENTERED evento di rispettivi targetNode.setOn<MouseDragEvent>() metodo.

6

Una soluzione consiste nell'aggiungere un filtro eventi alla scena che abilita sourceNode.startFullDrag(). Funzionerà anche se inizi a trascinare il mouse all'esterno dell'area di disegno (se desideri uno spazio senza nodi nell'applicazione).

Ti piace questa:

scene.addEventFilter(MouseEvent.DRAG_DETECTED , new EventHandler<MouseEvent>() { 
    @Override 
    public void handle(MouseEvent mouseEvent) { 
     scene.startFullDrag(); 
    } 
}); 

E allora si potrebbe:

node.setOnMouseDragEntered(new EventHandler<MouseEvent>() { 
    @Override 
    public void handle(MouseEvent event) { 
     led.setOn(true); 
    } 
}); 
Problemi correlati