使用translateX()和translateY()时,窗格布局中的JavaFX文本与其他元素重叠

下图是正在发生的事情的描述:

使用translateX()和translateY()时,窗格布局中的JavaFX文本与其他元素重叠

我有一个包含Text的窗格,并且我正在使用下面的代码来制作类似于Text的字幕效果.因此,当窗格没有足够的空间来显示文本时,就会启动动画,并且文本必须来回移动,以便用户可以完整地看到它.

问题是我期望使用setTranslateX()转到左侧时文本消失并且不与其他元素重叠.例如,此处与左侧的StackPane重叠.

该代码来自-> JavaFX Marquee Animation问题.

>为什么会发生?
>我需要一个解决方案和简短说明:)

下面是代码:

Marquee.java [class]:

import java.io.IOException;

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.InvalidationListener;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import javafx.util.Duration;

/**
 * When the screen element is not big enough to show the text then an animation
 * will start automatically
 * 
 *
 */
public class Marquee extends Pane{

    @FXML
    private Text text;

    // minimum distance to Pane bounds
    private static final double OFFSET = 5;

    private Timeline timeline = new Timeline();

    /**
     * Constructor
     */
    public Marquee() {

        // FXMLLOADER
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Marquee.fxml"));
            loader.setController(this);
            loader.setRoot(this);
            loader.load();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }


    /**
     * Called when FXML is loaded
     */
    @FXML
    public void initialize() {

        startAnimation();
    }

    /**
     * This method changes the text of the Marquee
     * 
     * @param value
     * @return this
     */
    public Marquee setText(String value) {

        // text
        text.setText(value);

        return this;
    }

    /**
     * This method starts the Animation of the marquee
     */
    private final void startAnimation() {

        // KeyFrame
        KeyFrame updateFrame = new KeyFrame(Duration.millis(35), new EventHandler<ActionEvent>() {

            private boolean rightMovement;

              @Override
                public void handle(ActionEvent event) {
                    double textWidth = text.getLayoutBounds().getWidth();
                    double paneWidth = getWidth();
                    double layoutX = text.getLayoutX();

                    if (2 * OFFSET + textWidth <= paneWidth && layoutX >= OFFSET) {
                        // stop, if the pane is large enough and the position is correct
                        text.setLayoutX(OFFSET);
                        timeline.stop();
                    } else {
                        if ((rightMovement && layoutX >= OFFSET) || (!rightMovement && layoutX + textWidth + OFFSET <= paneWidth)) {
                            // invert movement, if bounds are reached
                            rightMovement = !rightMovement;
                        }

                        // update position
                        if (rightMovement) {
                            layoutX += 1;
                        } else {
                            layoutX -= 1;
                        }
                        text.setLayoutX(layoutX);
                    }
                }
        });
        timeline.getKeyFrames().add(updateFrame);
        timeline.setCycleCount(Animation.INDEFINITE);

        // listen to bound changes of the elements to start/stop the
        // animation
        InvalidationListener listener = o -> {
            double textWidth = text.getLayoutBounds().getWidth();
            double paneWidth = getWidth();
            if (textWidth + 2 * OFFSET > paneWidth && timeline.getStatus() != Animation.Status.RUNNING)
                timeline.play();
        };

        text.layoutBoundsProperty().addListener(listener);
        widthProperty().addListener(listener);

    }

}

Marquee.fxml:

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

<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Text?>

<fx:root maxHeight="25.0" minHeight="25.0" prefHeight="25.0" prefWidth="100.0" style="-fx-border-color: orange;" type="Pane" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <Text fx:id="text" layoutX="5.0" layoutY="17.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" />
   </children>
</fx:root>

最后是Main.java [class]:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {

        Scene scene = new Scene(new Marquee().setText("Extra Biiggggggg Textttt"), 300, 300);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

在F*s回答后编辑:

.fxml现在是:

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

<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.shape.Rectangle?>

<fx:root fx:id="root" maxHeight="25.0" minHeight="25.0" prefHeight="25.0" prefWidth="100.0" style="-fx-border-color: orange; -fx-background-color: white;" type="Pane" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
  <children>
     <Text fx:id="text" layoutX="5.0" layoutY="17.0" strokeType="OUTSIDE" strokeWidth="0.0" style="-fx-text-fill: black; -fx-font-weight: bold;" text="Stopped" />
  </children>
  <clip>
     <Rectangle width="${root.width}" height="${root.height}"/>
  </clip>
</fx:root>

解决方法:

Why does it do that?

默认情况下,JavaFX还在子节点边界之外绘制子代.

How to fix that?

使用父级的clip属性可将内容裁剪到窗格的边界:

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

<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.shape.Rectangle?>

<fx:root xmlns:fx="http://javafx.com/fxml/1" fx:id="root" maxHeight="25.0" minHeight="25.0" prefHeight="25.0" prefWidth="100.0" style="-fx-border-color: orange;" type="Pane" xmlns="http://javafx.com/javafx/8.0.60">
    <children>
        <Text fx:id="text" layoutX="5.0" layoutY="17.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Text"/>
    </children>
    <clip>
        <Rectangle width="${root.width}" height="${root.height}" />
    </clip>
</fx:root>
上一篇:JavaFX:禁用TableView多列排序


下一篇:http协议详解-经典篇