首页 > 解决方案 > 如何在节点处于活动状态时停止隐藏节点?

问题描述

我参考的代码:Show / Hide a Node within a stage

按照上一个关于自动隐藏的问题和答案:如何显示/隐藏/自动隐藏节点

感谢 c0der 解决了前面的问题。

它有一个问题,好像它处于活动状态(如移动光标或单击),Vbox 节点仍将自动隐藏。当我移动光标或发生某些事件时,如何使 Vbox 节点保持可见而不隐藏?

当前的行为是,如果我移动光标或单击 VBox 节点上的某些东西,5 秒后它仍然会隐藏。

测试gg.java:

package testinggg;

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Testinggg extends Application {

private TestController controller;
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Test.fxml"));
        Parent root = loader.load();
        controller = loader.getController();
        stage.setScene(new Scene(root));
        stage.setFullScreen(true);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

测试控制器.java:

package testinggg;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.animation.PauseTransition;
import javafx.animation.TranslateTransition;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.VBox;
import javafx.util.Duration;

public class TestController implements Initializable {

    @FXML private VBox statusContainer;
    private TranslateTransition showStatus;
    private TranslateTransition hideStatus;
    private boolean showsStatus = false;
    private static final int AUTO_HIDE_DELAY = 5;  

    public void toggleStatus() {
        if( showsStatus ) {
            hide();
        }
        else {
            show();
        }
    }
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        showStatus = new TranslateTransition(Duration.millis(250), statusContainer);
        showStatus.setByY(-1080.0);
        showStatus.setOnFinished(event -> {
            showsStatus = true;
            autoHide();
        });

        hideStatus = new TranslateTransition(Duration.millis(250), statusContainer);
        hideStatus.setByY(1080.0);
        hideStatus.setOnFinished(new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent event) {
                showsStatus = false;
            }
        });
    }  

    private void show(){
        hideStatus.stop();
        showStatus.play();
    }

    private void hide(){
        showStatus.stop();
        hideStatus.play();
    }

    private void autoHide(){
        Duration duration = Duration.seconds(AUTO_HIDE_DELAY);
        PauseTransition transition = new PauseTransition(duration);
        transition.setOnFinished(evt ->{
            if( showsStatus ) {
                hide();
            }
        });
        transition.play();
    }
}

测试.fxml:

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

<?import javafx.scene.text.*?>
<?import javafx.scene.image.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="testinggg.TestController">
   <children>
      <AnchorPane id="AnchorPane" maxHeight="-Infinity" prefHeight="1080.0" prefWidth="1920.0" StackPane.alignment="TOP_LEFT">
         <children>
            <Button mnemonicParsing="false" onAction="#toggleStatus" prefHeight="1080.0" prefWidth="1920.0" text="Button" />
         </children>
      </AnchorPane>
      <VBox fx:id="statusContainer" maxHeight="1080.0" prefHeight="1080.0" translateY="1080.0" StackPane.alignment="BOTTOM_LEFT">
         <children>
            <AnchorPane prefHeight="668.0" prefWidth="1266.0">
               <VBox.margin>
                  <Insets bottom="50.0" left="50.0" right="50.0" top="50.0" />
               </VBox.margin>
               <children>
                  <ImageView fitHeight="540.0" fitWidth="1820.0" layoutY="43.0" pickOnBounds="true">
                     <image>
                        <Image url="@../Rainbow%20Poro.png" />
                     </image>
                  </ImageView>
                  <ImageView fitHeight="44.0" fitWidth="153.0" layoutX="857.0" pickOnBounds="true" preserveRatio="true">
                     <image>
                        <Image url="@../logo.png" />
                     </image>
                  </ImageView>
                  <ScrollPane layoutY="582.0" prefHeight="391.0" prefViewportHeight="208.0" prefViewportWidth="1266.0" prefWidth="1820.0">
                     <content>
                        <TextArea editable="false" layoutY="460.0" prefHeight="515.0" prefWidth="1804.0" text="Sometexthere SometexthereSometexthereSometexthereSometexthereSometexthereSometexthereSometexthereSometexthereSometexthere&#10;Some&#10;Text&#10;Here&#10;Some&#10;Text &#10;Here&#10;Some&#10;Text &#10;Here&#10;Some&#10;Text &#10;Here&#10;Some&#10;Text &#10;Here&#10;Some&#10;Text &#10;HereSome&#10;Text &#10;HereSome&#10;Text &#10;HereSome&#10;Text &#10;HereSome&#10;Text &#10;HereSome&#10;Text &#10;HereSome&#10;Text &#10;Here&#10;Some&#10;Text &#10;Here" />
                     </content>
                  </ScrollPane>
                  <Button layoutX="1775.0" mnemonicParsing="false" onAction="#toggleStatus" text="Close" />
               </children>
            </AnchorPane>
         </children>
      </VBox>
   </children>
   <stylesheets>
    <URL value="@test1.css" />
  </stylesheets>
</StackPane>

标签: javafxfxml

解决方案


您可以向控制器添加一个控制布尔值:

private boolean isStatusContainerBusy = false;

让感兴趣的事件切换它。例如鼠标进入时设置为真,鼠标退出时设置为假:

statusContainer.setOnMouseEntered(e-> isStatusContainerBusy = true);
statusContainer.setOnMouseExited(e-> isStatusContainerBusy = false);

并用它来控制自动隐藏:

transition.setOnFinished(evt ->{
    if( showsStatus ) {
        if(isStatusContainerBusy) {
            transition.play(); //start auto hide transition again
        }else{
            hide();
        }
    }
});

把它们放在一起:

public class TestController {

    @FXML private VBox statusContainer;

    private TranslateTransition showStatus;
    private TranslateTransition hideStatus;
    private boolean showsStatus = false;
    private static final int AUTO_HIDE_DEALY = 5;
    private boolean isStatusContainerBusy = false;

    @FXML void initialize() {

        showStatus = new TranslateTransition(Duration.millis(250), statusContainer);
        showStatus.setByY(-100.0);
        showStatus.setOnFinished(event -> {
            showsStatus = true;
            autoHide();
        });
        hideStatus = new TranslateTransition(Duration.millis(250), statusContainer);
        hideStatus.setByY(100.0);
        hideStatus.setOnFinished(event -> showsStatus = false);
        statusContainer.setOnMouseEntered(e-> isStatusContainerBusy = true);
        statusContainer.setOnMouseExited(e-> isStatusContainerBusy = false);
    }

    public void toggleStatus() {
        if( showsStatus ) {
            hide();
        }
        else {
            show();
        }
    }

    private void show(){
        hideStatus.stop();
        showStatus.play();
    }

    private void hide(){
        showStatus.stop();
        hideStatus.play();
    }

    private void autoHide() {
        Duration duration = Duration.seconds(AUTO_HIDE_DEALY);
        PauseTransition transition = new PauseTransition(duration);
        transition.setOnFinished(evt ->{
            if( showsStatus ) {
                if(isStatusContainerBusy) {
                    transition.play(); //start auto hide transition again
                }else{
                    hide();
                }
            }
        });
        transition.play();
    }
} 

推荐阅读