Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/210.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_Linechart - Fatal编程技术网

单画布上的javaFX多线条图

单画布上的javaFX多线条图,javafx,linechart,Javafx,Linechart,我试图使用折线图显示来自不同通道(即:时间序列)的医疗数据,但这些序列应根据所附图像显示在不同的坐标轴上 我是否需要开发自己的图表组件,或者此场景可以使用折线图 =========================更新。。。 在将yAxis更改为CategoryAxis时,扩展了折线图并添加了额外数据以满足Y值: import java.util.ArrayList; import java.util.Iterator; import java.util.List; import jav

我试图使用折线图显示来自不同通道(即:时间序列)的医疗数据,但这些序列应根据所附图像显示在不同的坐标轴上

  • 我是否需要开发自己的图表组件,或者此场景可以使用折线图

=========================更新。。。 在将yAxis更改为CategoryAxis时,扩展了折线图并添加了额外数据以满足Y值:

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

import javafx.beans.NamedArg;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.chart.Axis;
import javafx.scene.chart.LineChart;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.PathElement;

public class StackedLineChart<X,Y> extends LineChart<X,Y> {

    private double swimlaneHeight = 50;

    private double currentYoffset = 0;

    public static class ExtraData {

        public float channelPower;

        public ExtraData(float channelPower) {
            super();
            this.channelPower = channelPower;
        }
        public float getChannelPower() {
            return channelPower;
        }
        public void setChannelPower(float channelPower) {
            this.channelPower = channelPower;
        }

    }

    public StackedLineChart(@NamedArg("xAxis") Axis<X> xAxis, @NamedArg("yAxis") Axis<Y> yAxis) {
        this(xAxis, yAxis, FXCollections.<Series<X, Y>>observableArrayList());
    }

    public StackedLineChart(@NamedArg("xAxis") Axis<X> xAxis, @NamedArg("yAxis") Axis<Y> yAxis, @NamedArg("data") ObservableList<Series<X,Y>> data) {
        super(xAxis, yAxis);
        setData(data);
    }

    public double getSwimlaneHeight() {
        return swimlaneHeight;
    }

    public void setSwimlaneHeight(double swimlaneHeight) {
        this.swimlaneHeight = swimlaneHeight;
    }

    private static float getChannelPower( Object obj) {
        return ((ExtraData) obj).getChannelPower();
    }

    final int getDataSize() {
        final ObservableList<Series<X,Y>> data = getData();
        return (data!=null) ? data.size() : 0;
    }

     /** @inheritDoc */
    @Override protected void layoutPlotChildren() {

        List<LineTo> constructedPath = new ArrayList<>(getDataSize());
        currentYoffset = 0;
        for (int seriesIndex=0; seriesIndex < getDataSize(); seriesIndex++) {            
            Series<X,Y> series = getData().get(seriesIndex);            
            if(series.getNode() instanceof  Path) {
                final ObservableList<PathElement> seriesLine = ((Path)series.getNode()).getElements();
                seriesLine.clear();
                constructedPath.clear();
                for (Iterator<Data<X, Y>> it = getDisplayedDataIterator(series); it.hasNext(); ) {
                    Data<X, Y> item = it.next();

                    double yCat = getYAxis().getDisplayPosition(item.getYValue());                    
                    double x = getXAxis().getDisplayPosition(item.getXValue());                
                    double y = getChannelPower(item.getExtraValue()) + yCat;

                    if (Double.isNaN(x) || Double.isNaN(y)) {                    
                        continue;                
                    }

                    constructedPath.add(new LineTo(x, y));

                    Node symbol = item.getNode();
                    if (symbol != null) {
                        final double w = symbol.prefWidth(-1);
                        final double h = symbol.prefHeight(-1);
                        symbol.resizeRelocate(x-(w/2), y-(h/2),w,h);
                    }
                }

                if (!constructedPath.isEmpty()) {
                    LineTo first = constructedPath.get(0);
                    seriesLine.add(new MoveTo(first.getX(), first.getY()));
                    seriesLine.addAll(constructedPath);
                }
            }
            currentYoffset+= this.getSwimlaneHeight();
        }
    }      

    @Override protected void updateAxisRange() {
        final Axis<X> xa = getXAxis();
        final Axis<Y> ya = getYAxis();
        List<X> xData = null;
        List<Y> yData = null;
        if(xa.isAutoRanging()) xData = new ArrayList<X>();
        if(ya.isAutoRanging()) yData = new ArrayList<Y>();
        if(xData != null || yData != null) {
            for(Series<X,Y> series : getData()) {
                for(Data<X,Y> data: series.getData()) {
                    if(xData != null) xData.add(data.getXValue());
                    if(yData != null) yData.add(data.getYValue());
                }
            }

            // RT-32838 No need to invalidate range if there is one data item - whose value is zero. 
            if(xData != null) xa.invalidateRange(xData);
            if(yData != null) ya.invalidateRange(yData);


        }
    }

}
import java.util.ArrayList;
导入java.util.Iterator;
导入java.util.List;
导入javafx.beans.NamedArg;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.scene.Node;
导入javafx.scene.chart.Axis;
导入javafx.scene.chart.LineChart;
导入javafx.scene.shape.LineTo;
导入javafx.scene.shape.MoveTo;
导入javafx.scene.shape.Path;
导入javafx.scene.shape.PathElement;
公共类StackedLineChart扩展了LineChart{
私人双泳道高度=50;
专用双电流偏移=0;
公共静态类外部数据{
公共权力;
公共外部数据(浮动信道功率){
超级();
this.channelPower=channelPower;
}
公共权力{
返回通道功率;
}
公共无效设置信道功率(浮动信道功率){
this.channelPower=channelPower;
}
}
公共堆叠线形图(@NamedArg(“xAxis”)轴xAxis,@NamedArg(“yAxis”)轴yAxis){
这是(xAxis、yAxis、FXCollections.observearraylist());
}
公共堆叠线形图(@NamedArg(“xAxis”)轴xAxis、@NamedArg(“yAxis”)轴yAxis、@NamedArg(“数据”)可观测列表数据){
超级(xAxis,yAxis);
setData(数据);
}
公共双getSwimlaneHeight(){
返回泳道高度;
}
公共真空设置泳道高度(双泳道高度){
this.swimlanehight=泳道高度;
}
专用静态浮点getChannelPower(对象obj){
return((ExtraData)obj.getChannelPower();
}
final int getDataSize(){
最终可观察列表数据=getData();
返回(data!=null)?data.size():0;
}
/**@doc*/
@重写受保护的void layoutPlotChildren(){
List constructedPath=newarraylist(getDataSize());
currentYoffset=0;
对于(int seriesIndex=0;seriesIndex
您需要的是一堆图表,而不是单个图表中的各行。因此,是的,你必须开发自己的图表组件。

即:某个时间段的yAxis可以上移/下移吗?所以序列可以绘制在不同的相对坐标轴上…不确定…y轴上没有值。只需在每个系列中的每个点上添加一个量,具体取决于您希望它在图形中的位置。根据您的时间尺度判断,javaFX图表的速度不够快。是的,我会尝试(抵消y值),至于渲染性能,我不确定javaFX如何在内部渲染图表(查看源代码),但是的,基于“画布”的图表应该更快!对吗?画布速度更快,但javaFX画布仍能像直线一样渲染节点,这比直接绘制要慢。相比之下,AWT画布速度非常快。也没有时间轴,但只要显示秒数,就可以为NumberAxis创建一个格式化程序。我会先在FX中尝试,因为它应该很简单。谢谢Brian,问题是医疗数据非常密集,你可能每秒有256个点