2014-10-22 32 views
0

我很喜欢Java FX BarChart ..我自己的图表实现是一个扩展Java FX GridPane并将BarChart作为成员变量的类。 如果我初始化所有的东西都是完美的,但是如果我动态改变数据(添加一个或删除一个数据),布局将被破坏。 说起在图片,这意味着:(抱歉,我不能在此刻上传图片)Java FX - BarChart动态添加的内容破坏了布局

pic1 - initialization

after adding one element

所以第一次的图片显示initalization后的图表,一个元素后第一直添加和删​​除一个元素后,类别不再显示。 (我Ccan't上传这个图片)

因此,这里是我的代码:

import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.chart.BarChart; 
import javafx.scene.chart.CategoryAxis; 
import javafx.scene.chart.NumberAxis; 
import javafx.scene.chart.XYChart.Data; 
import javafx.scene.chart.XYChart.Series; 
import javafx.scene.control.Tooltip; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.Priority; 
import someCompanyThings.IMyBarChart; 
import someCompanyThings.LocaleService; 
import someCompanyThings.INlsKey; 

/** 
* A Chart with vertical or horizontal bars. It is assumed that the Bars represent positive integer numbers. 
* Data may be added or removed dynamically but on the first intent it should display static. 
*/ 
public class MyBarChart extends GridPane implements IMyBarChart { 

/* 
* Due to data binding problems with a generic bar chart, we hold the two possible bar charts as member variables. 
* Also each of them get's a list of Series<?, ?> 
*/ 
private BarChart<String, Number> _barChartVertical; 

private BarChart<Number, String> _barChartHorizontal; 

private final ObservableList<Series<String, Number>> _dataVertical = FXCollections.observableArrayList(); 

private final ObservableList<Series<Number, String>> _dataHorizontal = FXCollections.observableArrayList(); 

private long _maxValue = 0; 

private boolean _numberAxisInPercent = false; 

private boolean _horizontal = false; 



public MyBarChart(INlsKey pTitle, INlsKey pXLabel, INlsKey pYLabel, boolean pNumberAxisInPercent, boolean pHorizontal) { 
    super(); 
    CategoryAxis categoryAxis = new CategoryAxis(); 
    categoryAxis.setId("bar-chart-category-axis"); 

    NumberAxis numberAxis = new NumberAxis(0.0, 1.0, 1.0); 
    numberAxis.setId("bar-chart-number-axis"); 

    // create bar chart 
    // horizontal means that the x-axis is a number axis and the y-axis is a category axis 
    if (pHorizontal) { 
     categoryAxis.setLabel(LocaleService.getMessage(pYLabel)); 
     numberAxis.setLabel(LocaleService.getMessage(pXLabel)); 
     _barChartHorizontal = new BarChart<Number, String>(numberAxis, categoryAxis); 
     _barChartHorizontal.setData(_dataHorizontal); 
     _barChartHorizontal.setTitle(LocaleService.getMessage(pTitle)); 
     getChildren().add(_barChartHorizontal); 
    } 
    else { 
     categoryAxis.setLabel(LocaleService.getMessage(pXLabel)); 
     numberAxis.setLabel(LocaleService.getMessage(pYLabel)); 
     _barChartVertical = new BarChart<String, Number>(categoryAxis, numberAxis); 
     _barChartVertical.setData(_dataVertical); 
     _barChartVertical.setTitle(LocaleService.getMessage(pTitle)); 
     getChildren().add(_barChartVertical); 
    } 

    _numberAxisInPercent = pNumberAxisInPercent; 
    _horizontal = pHorizontal; 

    /* 
    * layout 
    */ 
    setHgrow(getChildren().get(0), Priority.ALWAYS); 
    setVgrow(getChildren().get(0), Priority.ALWAYS); 

} 



@Override 
public IMyBarChart addSeries(INlsKey pSeriesName, ObservableList<Data<String, Number>> pDataSet) { 
    final Series<String, Number> series = new Series<String, Number>(LocaleService.getMessage(pSeriesName), pDataSet); 
    _dataVertical.add(series); 

    // iterate over the whole data segment and add it to the series 
    for (final Data<String, Number> data : pDataSet) { 
     Tooltip tooltip = new Tooltip(); 
     tooltip.setText(data.getXValue()); 
     Tooltip.install(data.getNode(), tooltip); 

     if (data.getYValue().longValue() > _maxValue) { 
      _maxValue = data.getYValue().longValue(); 
     } 
    } 

    setNumberAxisScale(); 

    return this; 
} 



@Override 
public IMyBarChart addSeriesHorizontal(INlsKey pSeriesName, ObservableList<Data<Number, String>> pDataSet) { 
    final Series<Number, String> series = new Series<Number, String>(LocaleService.getMessage(pSeriesName), pDataSet); 
    _dataHorizontal.add(series); 

    // iterate over the whole data segment and add it to the series 
    for (final Data<Number, String> data : pDataSet) { 
     Tooltip tooltip = new Tooltip(); 
     tooltip.setText(data.getYValue()); 
     Tooltip.install(data.getNode(), tooltip); 

     if (data.getXValue().longValue() > _maxValue) { 
      _maxValue = data.getXValue().longValue(); 
     } 
    } 

    setNumberAxisScale(); 

    return this; 
} 



private void setNumberAxisScale() { 
    NumberAxis numberAxis = getNumberAxis(); 
    // set the number axis as a percent axis 
    if (_numberAxisInPercent) { 
     numberAxis.setUpperBound(100); 
     numberAxis.setTickUnit(10); 
    } 
    else { 
     numberAxis.setUpperBound(_maxValue + 1); 
     numberAxis.setTickUnit(1); 
    } 
} 



@Override 
public void setLegendVisible(boolean pVisible) { 
    if (_barChartHorizontal != null) { 
     _barChartHorizontal.setLegendVisible(pVisible); 
    } 
    else { 
     _barChartVertical.setLegendVisible(pVisible); 
    } 
} 



@Override 
public void setCategories(ObservableList<String> pCategories) { 
    getCategoryAxis().getCategories().setAll(pCategories); 
} 



/** 
* 
* @return the category axis of the used bar chart 
*/ 
private CategoryAxis getCategoryAxis() { 
    if (_horizontal) { 
     return (CategoryAxis)_barChartHorizontal.getYAxis(); 
    } 
    else { 
     return (CategoryAxis)_barChartVertical.getXAxis(); 
    } 
} 



/** 
* 
* @return the number axis of the used bar chart 
*/ 
private NumberAxis getNumberAxis() { 
    if (_horizontal) { 
     return (NumberAxis)_barChartHorizontal.getXAxis(); 
    } 
    else { 
     return (NumberAxis)_barChartVertical.getYAxis(); 
    } 
} 

} 

初始化过程:

final IMyBarChart tablespacesChart = MyFactory.createBarChart(NlsKeys.tablespacesTitle, NlsKeys.tablespacesXAxis, 
      NlsKeys.tablespacesYAxis, true, true); 
// first bool -> numberAxisInPercent, second bool -> horizontal ortientation 
    tablespacesChart.setLegendVisible(false); 
    tablespacesChart.setCategories(model.getListCategories()); 
    tablespacesChart.addSeriesHorizontal(NlsKeys.tablespacesLegendYAxis, model.getListDataUsedMax()); 

的数据变化是由刚刚使用

另一个类实现
model.getCategories().setAll(MyNewCatList); // or 
model.getListDataUsedMax().setAll(MyNewList); 

那么,我也试图用只有一个成员变量实现图表(如BarChart _barChart),但这没有奏效。 现在我有这些布局问题,我不知道他们来自哪里。所以我希望你可以给我一个提示:-)

+0

我通过停用图表动画解决了这个问题(setAnimated(假)) – PJWork 2014-10-28 08:41:40

回答

1

这里是我的解决方案: 首先,创建柱状图的子类访问私有方法updateAxisRange:

class MyBarChart<X, Y> extends BarChart<X, Y> { 

    public MyBarChart(Axis xAxis, Axis yAxis) { 
     super(xAxis, yAxis); 
    } 

    public void relayout() { 
     updateAxisRange(); 
    } 

} 

接下来,实例化条形图作为MyBarChart:

MyBarChart<String, Number> barChart = new MyBarChart<String, Number>(xAxis, yAxis); 

,最后,你要听来调整包含图表上的父事件,以及它们发生时,调用图的重新布局。 例如:

BorderPane pane = new BorderPane(barChart); 
pane.widthProperty().addListener(new ChangeListener<Number>() { 

     @Override 
     public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) { 
      barChart.relayout(); 
     } 
    });