3

ユーザーがパンおよびズームできる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();
    }
}

私はJDJ7u7を搭載したWindows864ビットを使用しています。

4

1 に答える 1

3

さて、あなたのコードは大丈夫だと思います。私にとっては問題なく動作し、Windows7でjdk7u7を使用しても明確な問題なく動作するようです。

rect.setMouseTransparent(true)長方形がクリックをキャッチしないように、呼び出したいと思うかもしれません。マウスの透明度は、長方形の追加と削除とは関係ありません。これは、JavaFXでピッキングが機能する方法にすぎません。

ScrollPane自分でパンを実装するのではなく、テストノードをパン可能に配置することを検討することをお勧めしますGroup。適切な動作を得るには、テストノードをでラップする必要があります。しかし、あなたが持っているコードは単純でうまく機能しているように見えるので、おそらくaの使用ScrollPaneは不要であり、さらに混乱する可能性があります。

Javaにはクラスがありますが、これは現在のCanvasクラスとは異なるものであるため、ノードを別の名前で呼び出すことをおCanvas勧めします。

あなたの質問とは関係ありませんが、Timelineアニメーションを処理するための私の好ましい方法は、ではなくaを使用することです。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();
  }
}

サンプルプログラム出力

于 2012-09-11T20:33:07.900 に答える