로드 된 처음 몇 초가 지난 후에도 잘 작동하는 내 자신의 Marquee 클래스/컨트롤을 만들었습니다. 그러나, 일단 응용 프로그램이 첫 번째로 부하를 걸면 부하는 maxWidth : 0.0 minWidth : 2.0이라고 가정합니다. 아래는 Marquee 클래스 코드 및 테스트 응용 프로그램에서로드하는 데 사용하는 코드입니다.JavaFX 컨트롤에서 초기화 즉시 localBounds를 인식하도록하려면 어떻게합니까?
움직이는 등급 :
public class Marquee extends HBox {
/**
* Add a node to the Marquee control
* @param node - a node to add
*/
public void add(Node node) {
getChildren().add(node);
}
/**
* Add a list of nodes to the Marquee control
* @param observable list - an observable list to add
*/
public void addAll(ObservableList<Node> list) {
getChildren().addAll(list);
}
/**
* Default Constructor: Initializes the Marquee Object with default settings:
* Empty Array List of Nodes, initial delay, Direction.LEFT, Duration.seconds(10), Interpolator.LINEAR, 10)
*/
public Marquee()
{
this(FXCollections.observableArrayList(new ArrayList<Node>()), Duration.seconds(3), Direction.LEFT, Duration.seconds(10), Interpolator.LINEAR, 10.0);
}
/**
* Constructor: Initializes the Marquee Object with default settings
* @param observable list
*/
public Marquee(ObservableList<Node> nodes)
{
this(nodes, Duration.seconds(3), Direction.LEFT, Duration.seconds(10), Interpolator.LINEAR, 10.0);
}
/**
* Constructor: Initializes the Marquee Object with default settings
* @param observable list
* @param duration - usually in seconds i.e. Duration.seconds(10)
*/
public Marquee(ObservableList<Node> nodes, Duration duration) {
this(nodes, Duration.seconds(3), Direction.LEFT, duration, Interpolator.LINEAR, 10.0);
}
/**
* Constructor: Initializes the Marquee Object with default settings
* @param observable list
* @param direction - an enum, i.e Direction.LEFT or Direction.RIGHT
* @param duration - usually in seconds i.e. Duration.seconds(10)
*/
public Marquee(ObservableList<Node> nodes, Direction direction, Duration duration) {
this(nodes, Duration.seconds(3), direction, duration, Interpolator.LINEAR, 10.0);
}
/**
* Constructor: Initializes the Marquee Object with default settings
* @param observable list
* @param duration - usually in seconds i.e. Duration.seconds(10)
* @param interpolator - effects the translation behavior, i.e
* Interpolator.EASE_BOTH, or EASE_LINEAR
*/
public Marquee(ObservableList<Node> nodes, Duration duration, Interpolator interpolator)
{
this(nodes, Duration.seconds(3), Direction.LEFT, duration, interpolator, 10.0);
}
/**
* Constructor: Initializes the Marquee Object with default settings:
* @param observable list
* @param initialDelay - the amount of time before the marquee will begin scrolling
* after the application has loaded
* @param direction - an enum, i.e Direction.LEFT or Direction.RIGHT
* @param duration - usually in seconds i.e. Duration.seconds(10)
* @param interpolator - effects the translation behavior, i.e
* Interpolator.EASE_BOTH, or EASE_LINEAR
*/
public Marquee(ObservableList<Node> list, Duration initialDelay, Direction direction, Duration duration, Interpolator interpolator) {
this(list, initialDelay, direction, duration, interpolator, 10.0);
}
/**
* Preferred Constructor: Initializes the Marquee Object with your preferred settings
*
* @param observable list
* @param initialDelay - the amount of time before the marquee will begin scrolling
* after the application has loaded
* @param direction - an enum, i.e Direction.LEFT or Direction.RIGHT
* @param duration - usually in seconds i.e. Duration.seconds(10)
* @param interpolator - effects the translation behavior, i.e
* Interpolator.EASE_BOTH, or EASE_LINEAR
* @param nodeSpacing - a double value that determines how far apart
* each element in the marquee will be placed from one another
*/
public Marquee(ObservableList<Node> list, Duration initialDelay, Direction direction, Duration duration, Interpolator interpolator, double nodeSpacing) {
super();
getChildren().addAll(list);
setSpacing(nodeSpacing);
delay = initialDelay;
this.direction = direction;
this.duration = duration;
this.interpolator = interpolator;
}
public enum Direction {
LEFT, RIGHT
};
private Direction direction;
private TranslateTransition animation;
private Duration duration;
/**
* This begins the animation of the Marquee. By default this method
* calculates the width of the Marquee's parent and uses that as its
* start point. When the nodes inside the Marquee have reached the outer
* bounds of its parent the Marquee will stop and reset. Note: If the
* application is resized, the animation will need to be stopped and
* restarted. The Marquee will recalculate its translation requirements each
* cycle so if the user resizes it's parent, the Marquee will conform.
*
* @param duration
* the amount of time the translation should take
*/
public void animate() {
animation = new TranslateTransition(duration, this);
double maxWidth = getBoundsInLocal().getMaxX();
double minWidth = getBoundsInLocal().getMinX() - getContentsWidth();
switch (direction) {
case LEFT:
animation.setToX(minWidth);
animation.setFromX(maxWidth);
break;
case RIGHT:
animation.setToX(maxWidth);
animation.setFromX(minWidth);
break;
default:
animation.setToX(minWidth);
animation.setFromX(maxWidth);
break;
}
animation.setCycleCount(1);
animation.setInterpolator(getInterpolator());
animation.setDelay(delay);
animation.playFromStart();
animation.setOnFinished(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event)
{
stopAnimation();
recycleAnimation();
}
});
}
private Duration delay;
public Duration getDelay() {
return delay;
}
public void setDelay(Duration delay) {
this.delay = delay;
}
private Interpolator interpolator;
/**
* How the Marquee transitions its content into and out of FOV.
* Options are:
* DISCRETE (DO NOT USE), EASE_IN, EASE_OUT, EASE_BOTH, and LINEAR (DEFAULT).
* Any change to the Interpolator will take affect after the current cycle
* ends.
* Suggested Usage: setInterpolator(Interpolator.LINEAR)
*/
public void setInterpolator(Interpolator interpolator)
{
this.interpolator = interpolator;
}
/**
* The Interpolator of the Marquee.
* @return Interpolator
*/
public Interpolator getInterpolator()
{
return interpolator;
}
public void recycleAnimation()
{
setDelay(Duration.ZERO);
animate();
}
/**
* Stop animation of Marquee
*/
public void stopAnimation() {
animation.stop();
}
/**
* Set the default spacing between nodes in the Marquee Default is set to
* 5.0
*/
public void setNodeSpacing(double value) {
setSpacing(value);
}
/**
* Get the current spacing between nodes in the Marquee
*
* @return double
*/
public double getNodeSpacing() {
return getSpacing();
}
private int getContentsWidth()
{
int width = 0;
for(Node node : getChildrenUnmodifiable())
{
width += node.boundsInLocalProperty().get().getWidth();
}
return width;
}
}
내 메인 클래스
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
ObservableList<Node> labels = FXCollections.observableArrayList();
labels.add(new Label("Test Label 1"));
labels.add(new Label("Test Label 2"));
Marquee marqueeLeft = new Marquee(labels, Duration.ZERO, Direction.LEFT, Duration.seconds(10), Interpolator.EASE_BOTH, 10.0);
root.setTop(marqueeLeft);
final ObservableList<Node> labels2 = FXCollections.observableArrayList();
labels2.add(new Label("Test Label 3"));
labels2.add(new Label("Test Label 4"));
final Marquee marqueeRight = new Marquee(labels2, Duration.ZERO, Direction.RIGHT, Duration.seconds(10), Interpolator.EASE_BOTH, 10.0);
root.setBottom(marqueeRight);
marqueeLeft.animate();
marqueeRight.animate();
Button button = new Button();
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Workin");
marqueeRight.add(new Label("Test Add Label"));
}
});
root.setCenter(button);
Scene scene = new Scene(root,600,300);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
나는 무대를 보여주고 parentBounds이 localBounds, 당신은 그것을 이름을 얻으려고 때까지 천막을로드 기다리고 노력했다. 0.0, 2.0부터 항상 시작하고 싶습니다.
모든 조언을 주시면 감사하겠습니다. 당신의 Marquee
클래스에서
감사합니다! 스테이지를 보여준 후에로드하려고했을 때 나는 거기에서 모든 인스턴스화도하고 있었다고 생각합니다. – JeramyRR
나는 왜 그것이 효과가 없었고 유효한 해결책인지에 대한 적절한 설명으로 나의 대답을 편집했다. –
다시 한번 감사드립니다! 이것은 진정한 도움이되었습니다. 이제 레이블을 초과하는 것을 방지하는 방법을 알아낼 수 있다면 ... – JeramyRR