更新可能なものを含むアプリケーションをビルドしようとしたとき、LineChart
またはAreaChart
奇妙な動作を認識したとき - おそらくアプリケーション ロジックのエラーが原因でしょうか?
目標は、「生成」ボタンがクリックされたときにチャートにデータを入力または更新することです。ユーザーは、グラフの開始時刻と終了時刻を入力する必要があります。さらに、時間/日/週の間隔を ( を使用してRadioGroup
) 選択する必要があります。
初期チャートの作成は問題なく動作します。チャートの再生成も適切に機能しますが、前のチャートにデータ ポイントが存在しない場合に限ります。同じ x 値を持つデータ ポイントが両方のグラフ (古いグラフと更新されたグラフ) に含まれている場合、並べ替えは昇順ではなくなります。
例:
StartDate: 01.09.2013 EndDate: 25.09.2013 間隔: 週で実行
X 軸の値:
01.09.2013 / 08.09.2013 / 15.09.2013 / 22.09.2013
「日」をクリックしRadioButton
てグラフを再生成すると、x 軸に次の値が表示されます。
01.09.2013 / 08.09.2013 / 15.09.2013 / 22.09.2013 / 02.09.2013 / 03.09.2013 / 04.09.2013 / ...
(値は 01.09.2013 / 02.09.2013 / 03.09.2013 / ...)
最初のチャートにすでに表示されていて、2 番目のチャートにもあるすべての値は、新しいチャートの先頭に並べ替えられます (昇順ではありません)。
トリックを行うコードは次のとおりです(メソッドのコードはinitializeTimeline
テスト目的のためだけです(確かに少し最適化可能です;))):
public class ChartDesignController implements Initializable {
@FXML
private AreaChart chartOne;
@FXML
private TextField startDate;
@FXML
private TextField endDate;
@FXML
private RadioButton radioHours;
@FXML
private RadioButton radioDays;
@FXML
private RadioButton radioWeeks;
@FXML
private ToggleGroup timeUnit;
@FXML
private Label msgBox;
@FXML
private void generateGraph(ActionEvent event) {
String timeUnit = getTimeUnit();
Series s = initializeTimeline(startDate.getText(), endDate.getText(), timeUnit);
chartOne.getData().setAll(s);
}
private String getTimeUnit() {
String timeUnitForQuery = "DD";
RadioButton selectedRadio = (RadioButton) timeUnit.getSelectedToggle();
if (selectedRadio == radioHours) {
//System.out.println("RadioHours was selected");
timeUnitForQuery = "HH24";
}
if (selectedRadio == radioDays) {
//System.out.println("RadioDays was selected");
timeUnitForQuery = "DD";
}
if (selectedRadio == radioWeeks) {
//System.out.println("RadioWeeks was selected");
timeUnitForQuery = "IW";
}
//System.out.println("Time unit changed");
return timeUnitForQuery;
}
@Override
public void initialize(URL url, ResourceBundle rb) {
}
private Series initializeTimeline(String startTime, String endTime, String timeUnit) {
msgBox.setText("");
long delta;
int nrOfTicks = 0;
Data<String, Integer> dp;
Series s = new Series();
ArrayList<Data<String, Integer>> dataPoints = new ArrayList();
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
Date startDate = new Date();
Date endDate = new Date();
GregorianCalendar startTimeGC = new GregorianCalendar();
GregorianCalendar endTimeGC = new GregorianCalendar();
if (timeUnit.equalsIgnoreCase("HH24")) {
sdf = new SimpleDateFormat("dd.MM.yyyy HH");
}
try {
startDate = sdf.parse(startTime);
endDate = sdf.parse(endTime);
} catch (ParseException ex) {
msgBox.setText(ex.getMessage() + "\n" + "Format expected: " + sdf.toPattern());
}
startTimeGC.setTimeInMillis(startDate.getTime());
endTimeGC.setTimeInMillis(endDate.getTime());
delta = endTimeGC.getTimeInMillis() - startTimeGC.getTimeInMillis();
if (timeUnit.equalsIgnoreCase("HH24")) {
nrOfTicks = (int) (delta / 1000 / 60 / 60) + 1;
} else if (timeUnit.equalsIgnoreCase("DD")) {
nrOfTicks = (int) (delta / 1000 / 60 / 60 / 24) + 1;
} else if (timeUnit.equalsIgnoreCase("IW")) {
nrOfTicks = (int) (delta / 1000 / 60 / 60 / 24 / 7) + 1;
}
for (int i = 0; i < nrOfTicks; i++) {
dp = new Data(sdf.format(startTimeGC.getTime()), 0);
dataPoints.add(dp);
if (timeUnit.equalsIgnoreCase("HH24")) {
startTimeGC.add(GregorianCalendar.HOUR_OF_DAY, 1);
} else if (timeUnit.equalsIgnoreCase("DD")) {
startTimeGC.add(GregorianCalendar.DAY_OF_MONTH, 1);
} else if (timeUnit.equalsIgnoreCase("IW")) {
startTimeGC.add(GregorianCalendar.WEEK_OF_YEAR, 1);;
}
}
dataPoints.sort(new DataComparator());
s.setData(FXCollections.observableList(dataPoints));
return s;
}
}
以下では、 x 値に従ってアルファベット順にDataComparator
並べ替えを担当します。dataPoints
public class DataComparator implements Comparator<Data> {
@Override
public int compare(Data d1, Data d2) {
String d1Xval = (String) d1.getXValue();
String d2Xval = (String) d2.getXValue();
return d1Xval.compareTo(d2Xval);
}
}
デバッグ時に、プログラムの値は で正しくソートされArrayList
dataPoints
ます。
値が古いチャートに既に表示されている場合に、値がチャートの x 軸で正しくソートされない理由はありますか?
この「問題」の助けをいただければ幸いです。