5

更新可能なものを含むアプリケーションをビルドしようとしたとき、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 軸で正しくソートされない理由はありますか?

この「問題」の助けをいただければ幸いです。

4

6 に答える 6

4

私も同じ問題を抱えていました。プロットをどのようにセットアップしても、新しいデータポイントで再プロットすることにより、順序が常に台無しになります。唯一の修正は、Java 1.8 を使用することでした。

これは、当時の最新の fx である 2.2.51-b13 でした。fx8 アーリー アクセス リリースを使用する必要がありました。

于 2014-02-05T18:31:54.103 に答える
3

言いたかったのは、折れ線グラフで(ほぼ)同じ問題が発生したことです。

データベースからいくつかのデータを読み込んで、折れ線グラフに表示します。データは単に 1 か月の合計を表します。

「user1」のデータをロードすると、すべて問題ないように見えます。 明確なデータを含むチャート 1。

しかし、2 番目のユーザーでデータをロードすると、次のようになります。 奇妙なデータを含むチャート 2。

次のようにデータベースから選択しているときにデータをソートするため、これがなぜ起こっているのか本当にわかりません。

...NTING.CUSTOMER = '"+Customer+"' GROUP BY MONTH ORDER BY MONTH ASC;

だから…私が言えるのはそれだけです…私はデータベースからデータをフェッチしながらデータを注文します。あるユーザーでは機能しますが、他のユーザーでは機能しません! それは本当に私をびっくりさせます!

JRE と JDK 8 の「アーリー アクセス バージョン」をダウンロードすることを誰かが推奨している投稿を見つけました。

誰かがその厄介な問題の解決策を見つけてくれることを願っています!

誰かがそれについて激怒する直前に、これは答えではありません - 私はそれを知っています!

しかし、できるだけ多くの情報を収集することも解決策の一部のように思えます。

そして、(時々スタックオーバーフローの奇妙な特権設定)のために、より高い評判値を得るまでコメントすることはできません!

これはすでにここで議論されていますが、私は新しい質問をしたくありませんでした!

これで問題ないと思います…</p>

あいさつ

于 2013-11-09T18:42:49.923 に答える
0

これについて「一時的な」解決策を見つけました。

series.getData().add(new BarChart.Data<>(rs.getString(1)+" "+i,rs.getDouble(2)));

データとともに増加する変数を追加するiと、データが台無しになるのを防ぎます。

別の解決策は、JDK 8 を使用することです。

于 2014-08-28T08:50:59.767 に答える