在javafx中的画布上平移

在javafx中的画布上平移,java,javafx-2,Java,Javafx 2,我正在尝试使用JavaFX2创建一个画布,用户可以在其中平移和缩放。对于静态内容,我的解决方案是有效的,但一旦用户在平移时内容得到更新,鼠标事件就会停止工作,直到释放并再次按下鼠标按钮 下面是一个演示该问题的简单示例。如果在白色区域中单击,则可以进行平移,但如果单击红色矩形开始平移,则内容更新时会中断 class Test extends StackPane { private Timer timer = new Timer(); private Rectangle rect;

我正在尝试使用JavaFX2创建一个画布,用户可以在其中平移和缩放。对于静态内容,我的解决方案是有效的,但一旦用户在平移时内容得到更新,鼠标事件就会停止工作,直到释放并再次按下鼠标按钮

下面是一个演示该问题的简单示例。如果在白色区域中单击,则可以进行平移,但如果单击红色矩形开始平移,则内容更新时会中断

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();
    }
}
类测试扩展StackPane
{
专用计时器=新计时器();
私有矩形矩形;
私人双按X,按Y;
公开考试()
{
setMinSize(600600);
setStyle(“-fx边框颜色:蓝色;”);
timer.schedule(新TimerTask()
{
@凌驾
公开募捐
{
Platform.runLater(新的Runnable()
{
@凌驾
公开募捐
{
if(rect!=null)
getChildren().remove(rect);
rect=新矩形(10,10,200,200);
矩形设置填充(颜色为红色);
getChildren().add(rect);
}
});
}
}, 0, 100);
setOnMousePressed(新的EventHandler()
{
公共无效句柄(MouseeEvent事件)
{
pressedX=event.getX();
pressedY=event.getY();
}
});
SetOnMouseDrawed(新的EventHandler()
{
公共无效句柄(MouseeEvent事件)
{
setTranslateX(getTranslateX()+event.getX()-按X);
setTranslateY(getTranslateY()+event.getY()-pressedY);
event.consume();
}
});
}
}
公共类TestApp扩展了应用程序
{
公共静态void main(字符串[]args)
{
发射(args);
}
@凌驾
公共无效开始(阶段primaryStage)
{
场景=新场景(新测试());
初级阶段。场景(场景);
primaryStage.show();
}
}

我在使用JDJ7u7的64位Windows 8上。

我认为您的代码还可以,对我来说似乎运行良好,在Windows 7上使用jdk7u7操作时没有任何明显问题

我想您可能需要调用
rect.setMouseTransparent(true)
,这样矩形就不会捕捉到点击。鼠标透明度的问题与添加和删除矩形无关,它只是JavaFX中拾取的工作方式

您可能想考虑将测试节点放置在一个可佩戴的,而不是实现您自己的摇摄-可能需要将其封装在组< /代码>中以获得适当的行为。但是您拥有的代码很简单,似乎工作正常,因此可能不需要使用

滚动窗格
,甚至可能会使事情更加混乱

Java中有一个类,它与您拥有的不同,因此调用节点而不是
Canvas
可能是一个好主意

这与您的问题无关,但我更喜欢使用一种方式来处理动画,而不是使用
计时器
,尽管
计时器
方法仍然有效,只要您正确使用
平台。请稍后运行

下面是一个修改过的示例,它使用了
时间线
.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();
  }
}
导入javafx.animation.*;
导入javafx.application.application;
导入javafx.beans.binding.Bindings;
导入javafx.beans.property.*;
导入javafx.event.*;
导入javafx.scene.scene;
导入javafx.scene.control.Label;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.StackPane;
导入javafx.scene.paint.Color;
导入javafx.scene.shape.Rectangle;
导入javafx.stage.stage;
导入javafx.util.Duration;
类测试扩展了StackPane{
私有矩形矩形;
私人双按X,按Y;
私有LongProperty框架=新的SimpleLongProperty();
公开考试(){
setMinSize(600600);
setStyle(“-fx边框颜色:蓝色;”);
标签计数=新标签();
count.textProperty().bind(Bindings.convert(frame));
getChildren().add(count);
count.setMouseTransparent(true);
setOnMousePressed(新的EventHandler(){
公共无效句柄(MouseeEvent事件){
pressedX=event.getX();
pressedY=event.getY();
}
});
SetOnMouseDrawed(新的EventHandler(){
公共无效句柄(MouseeEvent事件){
setTranslateX(getTranslateX()+event.getX()-按X);
setTranslateY(getTranslateY()+event.getY()-pressedY);
event.consume();
}
});
时间线t=新的时间线(新的关键帧(Duration.millis(100),新的EventHandler(){
@重写公共无效句柄(ActionEvent事件){
frame.set(frame.get()+1);
if(rect!=null){
getChildren().remove(rect);
}
rect=新矩形(10,10,200,200);
矩形设置填充(颜色为红色);
rect.setMouseTransparent(true);
getChildren().add(0,rect);
}
}));
t、 setCycleCount(Timeline.unfinite);
t、 play();
}
}
公共类TestApplication扩展了应用程序{
公共静态void main(字符串[]args){launch(args);}
@覆盖公共无效开始(阶段){
stage.setScene(新场景(新测试());
stage.show();
}
}

非常感谢!setMouseTransparent(true)方法正是我想要的。其他点也很好,但它们不适用于我的实际项目,仅适用于我的小示例,它们仍然是有效的点!