Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaFX时间线与画布文本动画_Javafx_Javafx 8 - Fatal编程技术网

JavaFX时间线与画布文本动画

JavaFX时间线与画布文本动画,javafx,javafx-8,Javafx,Javafx 8,我一直在尝试编写一个高效的“标签”控件,以垂直滚动方式呈现文本(选框/标记)。 我已经编写了两个版本(大致基于我在这里看到的一些模式)来尝试提高性能,但我希望有人能给我指出一个更好的方法,因为这两个版本都使用了大约4-9%的CPU PC规格:(英特尔i7-7660U@2.50GHz)/16GB内存/图形卡:英特尔(R)虹膜(TM)Plus图形640/Win10 虽然这是可以接受的,如果这是我希望我的应用程序所做的一切,它们将用于现有的大型和复杂的应用程序中,并且在任何时候都可以看到30+个细节视

我一直在尝试编写一个高效的“标签”控件,以垂直滚动方式呈现文本(选框/标记)。 我已经编写了两个版本(大致基于我在这里看到的一些模式)来尝试提高性能,但我希望有人能给我指出一个更好的方法,因为这两个版本都使用了大约4-9%的CPU

PC规格:(英特尔i7-7660U@2.50GHz)/16GB内存/图形卡:英特尔(R)虹膜(TM)Plus图形640/Win10

虽然这是可以接受的,如果这是我希望我的应用程序所做的一切,它们将用于现有的大型和复杂的应用程序中,并且在任何时候都可以看到30+个细节视图

我尝试的第一个版本使用了TimeLine,最接近我想要的外观。它仍然需要改进,以便文本按需要显示/消失,但它足够接近基准测试

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

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.CacheHint;
import javafx.scene.Scene;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class TickerLabelTester extends Application {



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

    @Override
    public void start(Stage stage) {
        List<String> list1 = new ArrayList<String>(
                Arrays.asList("Name 1",
                        "Name 2"));
        List<String> list2 = new ArrayList<String>(
                Arrays.asList("Name 3",
                        "Name 4"));

        VBox root = new VBox(2.0);
        root.setStyle("-fx-background-color:orange;");
        for (int i = 0; i < 30; i++) {
            TickerLabel tickerLabel = new TickerLabel();
            if (i % 2 == 0) {
                tickerLabel.setStrings(list1);
            } else {
                tickerLabel.setStrings(list2);
            }
            HBox hBox = new HBox(tickerLabel);
            hBox.setBorder(new Border(new BorderStroke(Color.BLACK,
                    BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
            root.getChildren().add(hBox);
        }
        root.setPrefSize(250, 700);
        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.setTitle("Scrolling Strings");
        stage.show();


    }

    class TickerLabel extends Pane {
        private Timeline timeline;
        private Text text;
        private List<String> strings = new ArrayList<String>();

        public TickerLabel() {
            Rectangle clip = new Rectangle();
            this.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> {
                clip.setWidth(newValue.getWidth());
                clip.setHeight(newValue.getHeight());
            });
            this.setClip(clip);
            text = new Text();
            this.getChildren().add(text);
            text.setCache(true);
            text.setCacheHint(CacheHint.SPEED);
            timeline = new Timeline();
            timeline.setCycleCount(Timeline.INDEFINITE);
        }

        public void setStrings(List<String> strings) {
            this.strings = strings;
            rerunTransition();
        }

        private void rerunTransition() {
            timeline.stop();
            if (strings.size() > 0) {
                recalculateTranslateTransition();
                timeline.playFromStart();
            }
        }

        private void recalculateTranslateTransition() {
            Duration duration = Duration.ZERO;
            double startPos = text.getLayoutBounds().getHeight() + 8;
            for (String string : strings) {
                KeyValue initKeyValue = new KeyValue(text.translateYProperty(), startPos);
                KeyValue initTextKeyValue = new KeyValue(text.textProperty(), string);
                KeyFrame initFrame = new KeyFrame(duration, initKeyValue, initTextKeyValue);
                timeline.getKeyFrames().add(initFrame);
                duration = Duration.seconds(duration.toSeconds() + 2);
                KeyValue endKeyValue = new KeyValue(text.translateYProperty(), 0);
                KeyFrame endFrame = new KeyFrame(duration, endKeyValue);
                timeline.getKeyFrames().add(endFrame);
            }
        }

    }

}
import java.util.ArrayList;
导入java.util.array;
导入java.util.List;
导入javafx.animation.KeyFrame;
导入javafx.animation.KeyValue;
导入javafx.animation.Timeline;
导入javafx.application.application;
导入javafx.scene.CacheHint;
导入javafx.scene.scene;
导入javafx.scene.layout.Border;
导入javafx.scene.layout.BorderStroke;
导入javafx.scene.layout.BorderStrokeStyle;
导入javafx.scene.layout.BorderWidths;
导入javafx.scene.layout.CornerRadii;
导入javafx.scene.layout.HBox;
导入javafx.scene.layout.Pane;
导入javafx.scene.layout.VBox;
导入javafx.scene.paint.Color;
导入javafx.scene.shape.Rectangle;
导入javafx.scene.text.text;
导入javafx.stage.stage;
导入javafx.util.Duration;
公共类TickerLabelTester扩展应用程序{
公共静态void main(字符串[]args){
应用程序启动(args);
}
@凌驾
公众假期开始(阶段){
List list1=新阵列列表(
Arrays.asList(“名称1”,
“名称2”);
List list2=新的阵列列表(
Arrays.asList(“名称3”,
"姓名(4);;
VBox根=新的VBox(2.0);
root.setStyle(“-fx背景色:橙色;”);
对于(int i=0;i<30;i++){
TickerLabel TickerLabel=新的TickerLabel();
如果(i%2==0){
股票标签设置字符串(列表1);
}否则{
股票标签设置字符串(列表2);
}
HBox HBox=新的HBox(标签);
hBox.setOrder(新边框)(新边框笔划)(颜色为黑色,
BorderStrokeStyle.SOLID,CornerRadii.EMPTY,BorderWidths.DEFAULT));
root.getChildren().add(hBox);
}
root.setPrefSize(250700);
场景=新场景(根);
舞台场景;
stage.setTitle(“滚动字符串”);
stage.show();
}
类TickerLabel扩展窗格{
私人时间表;
私人文本;
私有列表字符串=新的ArrayList();
公共股票标签(){
矩形剪辑=新矩形();
this.layoutBoundsProperty().addListener((可观察、旧值、新值)->{
clip.setWidth(newValue.getWidth());
setHeight(newValue.getHeight());
});
这个.setClip(clip);
text=新文本();
this.getChildren().add(文本);
text.setCache(true);
setCacheHint(CacheHint.SPEED);
时间线=新时间线();
timeline.setCycleCount(timeline.unfinite);
}
公共无效设置字符串(列表字符串){
this.strings=字符串;
重新翻译();
}
私有无效重新转换(){
timeline.stop();
if(strings.size()>0){
重新计算TranslateTransition();
timeline.playFromStart();
}
}
私有void重新计算TranslateTransition(){
持续时间=持续时间0;
double startPos=text.getLayoutBounds().getHeight()+8;
for(字符串:字符串){
KeyValue initKeyValue=新的KeyValue(text.translateYProperty(),startPos);
KeyValue initTextKeyValue=新的KeyValue(text.textProperty(),字符串);
KeyFrame initFrame=新关键帧(持续时间、initKeyValue、initTextKeyValue);
timeline.getKeyFrames().add(initFrame);
持续时间=持续时间.s(持续时间.toSeconds()+2);
KeyValue endKeyValue=新的KeyValue(text.translateYProperty(),0);
关键帧endFrame=新关键帧(持续时间,endKeyValue);
timeline.getKeyFrames().add(endFrame);
}
}
}
}
第二个版本使用画布和GraphicsContext。我以前没有使用过JavaFXCanvas,我希望它可能像Swing/AWT一样,我可以使用一些屏幕外缓冲来提高性能,不幸的是,这个版本的性能不如时间表。在切换到下面显示的AnimationTimer之前,我曾尝试使用自己的任务/服务类来执行渲染,但性能较差。希望我遗漏了一些关于如何使用GraphicsContext的内容

在实际应用程序中,每个标签的字符串列表将不时单独更新,因此时间线或AnimationTimer需要选择列表更改

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

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.CacheHint;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class TickerCanvasLabelTester extends Application {



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

    @Override
    public void start(Stage stage) {

        List<String> list1 = new ArrayList<String>(
                Arrays.asList("Name 1",
                        "Name 2"));
        List<String> list2 = new ArrayList<String>(
                Arrays.asList("Name 3",
                        "Name 4"));

        VBox root = new VBox(2.0);
        root.setStyle("-fx-background-color:orange;");
        for (int i = 0; i < 30; i++) {
            TickerLabel tickerLabel = new TickerLabel();
            if (i % 2 == 0) {
                tickerLabel.setStrings(list1);
            } else {
                tickerLabel.setStrings(list2);
            }
            HBox hBox = new HBox(tickerLabel);
            hBox.setBorder(new Border(new BorderStroke(Color.BLACK,
                    BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
            root.getChildren().add(hBox);
        }
        root.setPrefSize(250, 700);
        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.setTitle("Scrolling Strings");
        stage.show();


    }

    class TickerLabel extends Pane {
        private List<String> strings = new ArrayList<String>();
        private int stringPointer = 0;
        private Canvas canvas;
        private GraphicsContext gc;
        private AnimationTimer at;
        private String string;

        public TickerLabel() {
            Rectangle clip = new Rectangle();
            this.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> {
                clip.setWidth(newValue.getWidth());
                clip.setHeight(newValue.getHeight());
            });
            this.setClip(clip);
            canvas = new Canvas();
            canvas.setCache(true);
            canvas.setCacheHint(CacheHint.SPEED);
            canvas.setWidth(100);
            canvas.setHeight(20);
            gc = canvas.getGraphicsContext2D();
            string = "";

            at = new AnimationTimer() {
                private long lastUpdate = 0;
                private double i = canvas.getHeight() + 2;

                @Override
                public void handle(long now) {
                    // limit how often this is called
                    if (now - lastUpdate >= 200_000_000) {
                        if (i >= -2) {
                            gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
                            gc.strokeText(string, 0, i);
                            i--;

                        } else {
                            i = canvas.getHeight();
                            selectNextString();
                        }
                        lastUpdate = now;
                    }
                }
            };
            this.getChildren().add(canvas);

        }

        public void setStrings(List<String> strings) {
            this.strings = strings;
            at.stop();
            selectNextString();
            at.start();
        }

        private void selectNextString() {
            if (strings.size() > 0) {
                string = strings.get(stringPointer);
                if (stringPointer >= strings.size() - 1) {
                    stringPointer = 0;
                } else {
                    stringPointer++;
                }
            }
        }
    }

}
import java.util.ArrayList;
导入java.util.array;
导入java.util.List;
导入javafx.animation.AnimationTimer;
导入javafx.application.application;
导入javafx.scene.CacheHint;
导入javafx.scene.scene;
导入javafx.scene.canvas.canvas;
导入javafx.scene.canvas.GraphicsContext;
导入javafx.scene.layout.Border;
导入javafx.scene.layout.BorderStroke;
导入javafx.scene.layout.BorderStrokeStyle;
导入javafx.scene.layout.BorderWidths;
导入javafx.scene.layout.CornerRadii;
导入javafx.scene.layout。