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