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