当前位置: 首页 > 知识库问答 >
问题:

JavaFX ListView时间轴滚动动画是跳跃的(choppy)

丁豪
2023-03-14
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.util.ArrayList;
import java.util.List;

public class Jumpy extends Application {

    ListView listView;
    Timeline timeline = new Timeline();
    double speed = 0.0000005;

    @Override
    public void start(Stage stage) throws Exception {
        List list = new ArrayList();
        for (int i = 0; i < 2000; i++) {
            Text text = new Text("Random line of text to show how it is choppy during scroll animation");
            text.setStyle("-fx-font-size: " + 4 + "em");
            list.add(text);
        }
        ObservableList observableList = FXCollections.observableList(list);
        listView = new ListView((observableList));
        listView.setPrefWidth(600);

        AnchorPane root = new AnchorPane();
        root.getChildren().addAll(listView, buttons());

        stage.setScene(new Scene(root));
        stage.show();
    }

    public void scroll() {
        ScrollBar scrollBar = getVerticalScrollBar();
        EventHandler scroll = new EventHandler<ActionEvent>() {
            public void handle(ActionEvent t) {
                scrollBar.setValue(scrollBar.getValue() + speed);
            }
        };

        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.setAutoReverse(false);
        KeyValue kv = new KeyValue(scrollBar.valueProperty(), 1);
        KeyFrame kf = new KeyFrame(Duration.seconds(0.017), scroll);
        timeline.getKeyFrames().add(kf);
        timeline.play();
    }

    public ScrollBar getVerticalScrollBar() {
        ScrollBar scrollBar = null;
        for (Node node : listView.lookupAll(".scroll-bar")) {
            if (node instanceof ScrollBar) {
                scrollBar = (ScrollBar) node;
                if ((scrollBar.getOrientation().compareTo(Orientation.VERTICAL)) == 0) {
                    break;
                }
            }
        }
        return scrollBar;
    }

    public HBox buttons() {
        HBox hBox = new HBox();
        Button start = new Button("start");
        start.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                scroll();
            }
        });
        Button slower = new Button("slower");
        slower.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                ScrollBar scrollBar = getVerticalScrollBar();
                EventHandler scroll = new EventHandler<ActionEvent>() {
                    public void handle(ActionEvent t) {
                        scrollBar.setValue(scrollBar.getValue() - 0.000001);
                    }
                };
                KeyFrame kf = new KeyFrame(Duration.millis(10.0D), scroll);
                timeline.getKeyFrames().add(kf);
            }

        });
        Button faster = new Button("faster");
        faster.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                ScrollBar scrollBar = getVerticalScrollBar();
                EventHandler scroll = new EventHandler<ActionEvent>() {
                    public void handle(ActionEvent t) {
                        scrollBar.setValue(scrollBar.getValue() + 0.000001);
                    }
                };
                KeyFrame kf = new KeyFrame(Duration.millis(10.0D), scroll);
                timeline.getKeyFrames().add(kf);

            }
        });
        hBox.getChildren().addAll(start, slower, faster);
        return hBox;
    }

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

共有1个答案

刘选
2023-03-14

如果只使用2000个节点实例来填充虚拟化控件,那么使用虚拟化控件是没有意义的:首先,您完全破坏了使用虚拟化的几乎所有好处。

用数据(例如,在本例中是字符串s)填充控件,并设置ListView样式或使用单元格工厂来控制值的显示方式。

以下内容对我来说更好:

ListView<String> listView;
Timeline timeline = new Timeline();
double speed = 0.0000005;

@Override
public void start(Stage stage) throws Exception {
    List<String> list = new ArrayList<>();
    for (int i = 0; i < 2000; i++) {
        String text = "Random line of text to show how it is choppy during scroll animation";
        //  text.setStyle("-fx-font-size: " + 4 + "em");
        list.add(text);
    }
    ObservableList<String> observableList = FXCollections.observableList(list);
    listView = new ListView<String>((observableList));
    listView.setPrefWidth(600);

    listView.setStyle("-fx-font-size: 4em; ");

    AnchorPane root = new AnchorPane();
    root.getChildren().addAll(listView, buttons());

    stage.setScene(new Scene(root));
    stage.show();
}
import java.util.ArrayList;
import java.util.List;

import javafx.animation.AnimationTimer;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Jumpy extends Application {

    ListView<String> listView;
    Timeline timeline = new Timeline();
    double increment = 2e-5 ;
    double speed = 5*increment ;

    AnimationTimer timer = new AnimationTimer() {

        private long lastUpdate = -1 ;
        private ScrollBar scrollbar ;

        @Override
        public void start() {
            scrollbar = getVerticalScrollBar();
            super.start();
        }

        @Override
        public void handle(long now) {
            if (lastUpdate < 0) {
                lastUpdate = now ;
                return ;
            }

            long elapsedNanos = now - lastUpdate ;
            double delta = speed * elapsedNanos / 1_000_000_000 ;
            scrollbar.setValue(scrollbar.getValue() + delta);

            lastUpdate = now ;
        }
    };

    @Override
    public void start(Stage stage) throws Exception {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 2000; i++) {
            String text = "Random line of text to show how it is choppy during scroll animation";
            list.add(text);
        }
        ObservableList<String> observableList = FXCollections.observableList(list);
        listView = new ListView<String>((observableList));
        listView.setPrefWidth(600);

        listView.setStyle("-fx-font-size: 4em; ");

        AnchorPane root = new AnchorPane();
        root.getChildren().addAll(listView, buttons());

        stage.setScene(new Scene(root));
        stage.show();
    }

    private ScrollBar getVerticalScrollBar() {
        ScrollBar scrollBar = null;
        for (Node node : listView.lookupAll(".scroll-bar")) {
            if (node instanceof ScrollBar) {
                scrollBar = (ScrollBar) node;
                if (scrollBar.getOrientation() == Orientation.VERTICAL) {
                    break;
                }
            }
        }
        return scrollBar;
    }

    private HBox buttons() {
        HBox hBox = new HBox();
        Button start = new Button("start");
        start.setOnAction(event -> timer.start());
        Button slower = new Button("slower");
        slower.setOnAction(event -> speed -= increment);
        Button faster = new Button("faster");
        faster.setOnAction(event -> speed += increment);
        hBox.getChildren().addAll(start, slower, faster);
        return hBox;
    }

    public static void main(String[] args) {
        launch(args);
    }
}
 类似资料:
  • 我想知道为什么我的图表每次移动后屏幕都不清晰。这是我的代码: MainClass,我想删除其中的“时间”,并将其放在绘图方法updateScene中的lambda表达式中,但还不知道如何做到这一点:/ Axes类描述如何绘制轴: 缩放和绘制图表中我需要的一切。 绘图课负责制作动画,精确绘制我想要的图形。 屏幕显示我编译后得到的内容。就像我自上而下的问题一样,不知道是什么原因导致在每个时间线阶段后不

  • 我一直试图在我的UI中添加一个动画到我的气泡图中,但遇到了一些问题。我试图在不同的阶段增加气泡的大小,以显示渐变,但它只是画出它的全部大小,而不是在每个阶段。 体育推特计数是泡沫的最终值,我将其除以不同的数量,以显示最终值的建立。 有人有什么想法为什么这不像我期望的那样工作吗?

  • 在一个区域表面上有很多图像。我把它们分成小组。它们应该水平滚动成链。在这里输入图像描述 我写了一些方法来工作。例如。在左边切换位置。(rects-rectangles。早先是rectangles)。 例如。将元素从中心移到左边。 等等。

  • 我目前正在创建一个非常简单的JavaFX程序,模拟城市之间运送乘客的飞机和船只。到目前为止,我已经能够让飞机在几个城市进行短途飞行,但问题是,当我添加超过3或4架飞机时,动画速度非常慢。 我正在做的是使用Timeline类作为我的主游戏循环,清除并重新绘制画布上每帧60帧的平面图像。以下是时间表部分: 以下是我如何为平面创建新线程: 这是Plane类中定义的run()方法: 我知道代码非常混乱,但

  • 我想使用chartjs折线图来可视化我的数据点。默认情况下,Chartjs似乎会为图形设置动画,但不会为x轴上的值设置动画。x轴仅以离散步骤移动。 是否有任何方法也可以启用轴上的动画? 谢谢

  • 我是JavaFX新手,我确信我在这里遗漏了一些明显的东西。我试图制作一个汽车的动画,它从左到右穿过一扇窗户,到达那里时绕着右边。用户应该能够点击up/down来调整动画的速度。当我使用一个对象时,动画开始运行,但发现你无法调整的,所以我在一个中重新编辑了它。 然而,随着时间的推移,我被卡住了。当我启动应用程序时,汽车不会显示在屏幕上。以下是我希望的一段简洁的代码片段: 还有消旋果烷: 编辑:根据@