0

ユーザーがシーンの上部3%にカーソルを合わせると、シーンの上部からスライドするメニューがありますWebView。それ以外の場合は、シーンの高さ全体を占めます。スライドアニメーション中に「ちらつき」を取り除くことができません。


コントローラのFXMLのアイデアは次のとおりです。

<fx:root type="javafx.scene.layout.StackPane" minHeight="768.0" minWidth="1024.0" xmlns:fx="http://javafx.com/fxml">
  <children>
    <WebView fx:id="wv" onKeyPressed="#onKeyDown" onMouseMoved="#onMouseMove" prefHeight="768.0" prefWidth="1024.0" />
    <VBox fx:id="vbox_slideview" fillWidth="true" maxHeight="326.0" maxWidth="1024.0" minHeight="326.0" minWidth="1024.0" prefHeight="326.0" prefWidth="1024.0" visible="false" StackPane.alignment="TOP_CENTER">
      ...
      <StackPane.margin>
       <Insets top="-326.0" />
      </StackPane.margin>
    </VBox>
  </children>
</fx:root>

root要素は、を拡張する私のコントローラークラスであることに注意してくださいStackPane

これが基本的なonMouseMoveです(今のところ、正しくスライドさせたいだけです):

public void onMouseMove(MouseEvent e)
{
    if (e.getSceneY() < 0.03 * stage.getScene().getHeight())
    {
        this.vbox_slideview.setVisible(true);
        TimelineBuilder.create().keyFrames(
            new KeyFrame(
                Duration.millis(300),
                new KeyValue(this.vbox_slideview.layoutYProperty(),
                0)))
            .build().play();
    }
}

これはちらつくので、別のアニメーションが1つの方法である間、新しいアニメーションの実行を停止する「ブロックメカニズム」を追加します。

Timeline    anim    = null;
boolean     blocked = false;

public boolean isBlocked()
{
    return blocked;
}

public void setBlocked(boolean blocked)
{
    this.blocked = blocked;
}

public void onMouseMove(MouseEvent e)
{
    if (isBlocked())
        return;

    setBlocked(true);

    if (e.getSceneY() < 0.03 * stage.getScene().getHeight())
    {
        this.vbox_slideview.setVisible(true);
        this.anim = TimelineBuilder.create().keyFrames(new KeyFrame(Duration.millis(300), new KeyValue(this.vbox_slideview.layoutYProperty(), 0))).build();
        this.anim.statusProperty().addListener(new ChangeListener<Status>() {
            @Override
            public void changed(ObservableValue<? extends Status> observableValue, Status oldValue, Status newValue)
            {
                if (newValue == Status.STOPPED)
                {
                    setBlocked(false);
                }
            }
        });
        this.anim.play();
        return;
    }

    setBlocked(false);
}

アニメーションをクラス変数に入れていることに気付くでしょう。これは、この質問の投稿で提案されている、アニメーションをブロックする他のいくつかの方法を試したためです。トランジションがノードですでに実行されているかどうかを確認するにはどうすればよいですか?これらの方法はすべて同じ結果を提供します。

スライドメニューのYプロパティのリスナーも紹介しますinitialize()

vbox_slideview.layoutYProperty().addListener(new ChangeListener<Number>() {
    @Override
    public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2)
    {
        System.out.println("y = " + arg0.getValue().intValue());
    }
});

結果は奇妙です(私の強調):

(Status == RUNNING)
y = -325
y = -308
y = -287
y = -269
y = -326 <<
y = -218
y = -326 <<
y = -196
y = -178
y = -326 <<
y = -158
y = -326 <<
y = -132
y = -120
y = -326 <<
y = -96
y = -326 <<
y = -76
y = -60
y = -326 <<
y = -28
y = -326 <<
y = -2
y = 0
(Status == STOPPED)

プロパティは、layoutYアニメーション中にランダムに開始値に設定されます。さらに、マウスカーソルがメニュー上にある場合onMouseMove、はのハンドラーにすぎないため、は起動しないはずWebViewです。ただし、アニメーションが完了し、ウィンドウの上部3%の下にカーソルを移動すると、vbox_slideview消えてlayoutYすぐにに設定され-326ます。これは、以上の場合には発生しないはずvbox_slideviewです。

なぜvbox_slideview常に開始位置にリセットされているのですか?


アップデート

カーソルを上位3%にすばやく移動して、カーソルがそこにとどまらないようにすると、アニメーションは正常に実行されます。これにより、イベントは順番にではなく並列に処理されていると思います。最初のイベントは後続のイベントの処理をブロックしますが、処理されている他のイベントはすでにたくさんあります。

4

2 に答える 2

1

スライダーの「ポップアップ」部分を見せてくれましたが、完全に調べるには自動非表示部分も必要です。ポップアップのスライド中と終了後の両方で、自動非表示部分が継続的にトリガーされていると思われます。とにかく、なぜ毎回タイムラインを作成するのか、そのインスタンスを1つだけ使用してください。
私のテストケース(Javafxバージョン2.2.0)では、同じようなコードを使用していますが、アニメーションが終了した後、スライダーはちらつきなく表示され、layoutY=0で画面に表示されたままになります。

Sample.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.web.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<StackPane id="StackPane" minHeight="568.0" minWidth="824.0" xmlns:fx="http://javafx.com/fxml" fx:controller="demo.SampleController">
  <children>
    <WebView fx:id="wv" onMouseMoved="#onMouseMove" prefHeight="568.0" prefWidth="824.0" />
    <VBox fx:id="vbox_slideview" fillWidth="true" maxHeight="326.0" maxWidth="824.0" minHeight="326.0" minWidth="824.0" prefHeight="326.0" prefWidth="824.0"
          visible="false" StackPane.alignment="TOP_CENTER" style="-fx-background-color: green">
      <StackPane.margin>
       <Insets top="-326.0" />
      </StackPane.margin>
    </VBox>
  </children>
</StackPane>

SampleController

public class SampleController implements Initializable {

    @FXML
    private VBox vbox_slideview;

    private Timeline timeline;

    @FXML
    public void onMouseMove(MouseEvent e) {
        if (e.getSceneY() < 0.03 * JavaFXApplication110.instance.stage.getScene().getHeight()) {
            this.vbox_slideview.setVisible(true);
            if (timeline.getStatus().equals(Animation.Status.STOPPED)) {
                timeline.play();
            }
        }
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        vbox_slideview.layoutYProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
                System.out.println("y = " + arg0.getValue());
            }
        });

        timeline = TimelineBuilder.create().keyFrames(
                new KeyFrame(
                Duration.millis(300),
                new KeyValue(this.vbox_slideview.layoutYProperty(),
                0)))
                .build();
    }
}
于 2013-02-21T15:06:28.667 に答える
0

LayoutX / Y()を使用しないでください... TranslateX / Y()を使用してください

于 2014-12-30T07:04:19.037 に答える