使用translateX()和translateY()时,窗格布局中的JavaFX文本与其他元素重叠 [英] JavaFX Text inside Pane Layout is overlapping other Elements when using translateX() and translateY()

查看:270
本文介绍了使用translateX()和translateY()时,窗格布局中的JavaFX文本与其他元素重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下图是对所发生情况的描述:

The image below is the description of what is happening:

我有 Pane ,其中包含文字我正在使用下面的代码制作文本的效果的字幕。因此,当 Pane 没有足够的空间来显示文本时,动画正在启动,文本必须来回传递,以便用户可以完整地看到它。

I have a Pane which contains a Text and i am using the code below to make a marquee like effect of the Text . So when the Pane has not enough space to display the text , an animation is starting and the text has to go back and forth so the user can see it whole.

问题是我在使用 setTranslateX()向左转时期待文本消失,而不是重叠其他元素。例如,这里重叠左边的 StackPane

The problem is that i was expecting the text when going to the left using setTranslateX() to disappear and not overlape the other elements.For example here is overlapping the StackPane at the left.

代码来自 - > JavaFX Marquee Animation 问题。

The code comes from -> JavaFX Marquee Animation question.


  • 为什么会这样?

  • 我需要一个解决方案和简要说明:)

以下是代码:

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);
    }
}









Fabians之后编辑回答:

.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也会在节点边界之外绘制子节点。

JavaFX by default also draws children outside of a nodes bounds.

如何修复?

使用剪辑父级的属性,用于在 Pane 的范围内剪辑内容:

Use the clip property of the parent to clip the content at the bounds of the Pane:

<?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>

这篇关于使用translateX()和translateY()时,窗格布局中的JavaFX文本与其他元素重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆