2012-09-11 116 views
3

我想創建一個用戶可以平移和縮放的javafx 2的畫布。對於靜態內容,我的解決方案可以工作,但只要內容在用戶平移時更新,鼠標事件就會停止工作,直到釋放並再次按下鼠標按鈕。在javafx的畫布上平移

以下是演示該問題的最簡單示例。如果您點擊白色區域,您可以平移,但如果通過點擊紅色矩形開始平移,則在更新內容時它會中斷。

class Test extends StackPane 
{ 
    private Timer timer = new Timer(); 
    private Rectangle rect; 
    private double pressedX, pressedY; 

    public Test() 
    { 
     setMinSize(600, 600); 
     setStyle("-fx-border-color: blue;"); 

     timer.schedule(new TimerTask() 
     { 
      @Override 
      public void run() 
      { 
       Platform.runLater(new Runnable() 
       { 
        @Override 
        public void run() 
        { 
         if (rect != null) 
          getChildren().remove(rect); 

         rect = new Rectangle(10, 10, 200, 200); 
         rect.setFill(Color.RED); 
         getChildren().add(rect); 
        } 
       }); 
      } 
     }, 0, 100); 

     setOnMousePressed(new EventHandler<MouseEvent>() 
     { 
      public void handle(MouseEvent event) 
      { 
       pressedX = event.getX(); 
       pressedY = event.getY(); 
      } 
     }); 

     setOnMouseDragged(new EventHandler<MouseEvent>() 
     { 
      public void handle(MouseEvent event) 
      { 
       setTranslateX(getTranslateX() + event.getX() - pressedX); 
       setTranslateY(getTranslateY() + event.getY() - pressedY); 

       event.consume(); 
      } 
     }); 
    } 
} 

public class TestApp extends Application 
{ 
    public static void main(String[] args) 
    { 
     launch(args); 
    } 

    @Override 
    public void start(Stage primaryStage) 
    { 
     Scene scene = new Scene(new Test()); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 
} 

我在使用JDJ7u7的Windows 8 64位。

回答

2

嗯,我想你的代碼是確定的,似乎爲我運行良好,並使用jdk7u7窗戶上沒有任何明顯的問題,運營7.

我想也許你想打電話rect.setMouseTransparent(true),使矩形不捕捉點擊。鼠標透明度與添加和去除矩形無關,它只是JavaFX中拾取工作的方式。

您可能需要考慮將您的測試節點置於pannable ScrollPane而不是自己實現平移 - 可能需要將其包裝在Group以獲得適當的行爲。但是你的代碼很簡單,似乎很好,所以使用ScrollPane是不必要的,甚至可能會讓事情更加混亂。

在Java中有一個Canvas類,這與你有什麼不同,所以調用你的節點而不是Canvas可能是一個好主意。

不要做你的問題,但使用Timeline是我的首選處理動畫,而不是一個Timer,雖然Timer方法仍將只要你正確地使用Platform.runLater因爲你正在做的工作方式。

下面是一個修改後的示例,使用Timeline.mouseTransparent()以及添加的幀計數器,以便清楚地看到動畫正在發生。

import javafx.animation.*; 
import javafx.application.Application; 
import javafx.beans.binding.Bindings; 
import javafx.beans.property.*; 
import javafx.event.*; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.StackPane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Rectangle; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

class Test extends StackPane { 
    private Rectangle rect; 
    private double pressedX, pressedY; 
    private LongProperty frame = new SimpleLongProperty(); 

    public Test() { 
    setMinSize(600, 600); 
    setStyle("-fx-border-color: blue;"); 
    Label count = new Label(); 
    count.textProperty().bind(Bindings.convert(frame)); 
    getChildren().add(count); 
    count.setMouseTransparent(true); 

    setOnMousePressed(new EventHandler<MouseEvent>() { 
     public void handle(MouseEvent event) { 
     pressedX = event.getX(); 
     pressedY = event.getY(); 
     } 
    }); 

    setOnMouseDragged(new EventHandler<MouseEvent>() { 
     public void handle(MouseEvent event) { 
     setTranslateX(getTranslateX() + event.getX() - pressedX); 
     setTranslateY(getTranslateY() + event.getY() - pressedY); 

     event.consume(); 
     } 
    }); 

    Timeline t = new Timeline(new KeyFrame(Duration.millis(100), new EventHandler<ActionEvent>() { 
     @Override public void handle(ActionEvent event) { 
     frame.set(frame.get() + 1); 

     if (rect != null) { 
      getChildren().remove(rect); 
     } 

     rect = new Rectangle(10, 10, 200, 200); 
     rect.setFill(Color.RED); 
     rect.setMouseTransparent(true); 
     getChildren().add(0, rect); 
     } 
    })); 
    t.setCycleCount(Timeline.INDEFINITE); 
    t.play(); 
    } 
} 

public class TestApplication extends Application { 
    public static void main(String[] args) { launch(args); } 
    @Override public void start(Stage stage) { 
    stage.setScene(new Scene(new Test())); 
    stage.show(); 
    } 
} 

Sample program output

+0

非常感謝您! setMouseTransparent(true)方法是我正在尋找的。其他的觀點也非常好,但是他們不適用於我的真實項目,只是對我的小例子來說,它們仍然是有效的點數! – Christian