JavaFX LineChart / AreaChart x 轴(CategoryAxis)上的错误排序值

use*_*153 5 java sorting charts javafx linechart

当尝试构建包含可更新的应用程序LineChartAreaChart我认识到奇怪的行为时 - 可能是由于应用程序逻辑中的错误?

目标是在单击“生成”按钮时将数据填充到图表中或更新图表。用户必须输入图表的开始时间和结束时间,此外还必须选择间隔小时/天/周(通过使用 )RadioGroup

初始图表的创建工作没有任何问题。重新生成图表也可以正常工作,但前提是以前的图表中不存在数据点。如果两个图表(旧图表和更新图表)中都包含具有相同 x 值的数据点,则不再按升序排序。

例子:

执行开始日期:01.09.2013 结束日期:25.09.2013 间隔:周

x 轴上的值:

2013年9月1日 / 2013年9月08日 / 2013年9月15日 / 2013年9月22日

单击“天”RadioButton重新生成图表会在 x 轴上生成以下值:

2013年9月1日 / 2013年9月8日 / 2013年9月15日 / 2013年9月22日 / 2013年9月2日 / 2013年9月03日 / 2013年9月04日 / ...

(值应为 01.09.2013 / 02.09.2013 / 03.09.2013 / ...)

已在第一个图表中显示且也在第二个图表中显示的所有值均在新图表的开头排序(而不是按升序排列)

这是实现这一技巧的代码(方法代码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;
 }
}
Run Code Online (Sandbox Code Playgroud)

下面,它DataComparator负责dataPoints根据 x 值按字母顺序排序:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

调试时,程序值在 中正确排序ArrayList dataPoints

任何想法为什么值在图表 x 轴中排序不正确(如果它们已经出现在旧图表中)?

非常感谢对这个“问题”的帮助。

dow*_*own 3

我只是想说,我在折线图上遇到了(几乎)相同的问题!

\n\n

我从数据库加载一些数据以折线图的形式显示。\n这些数据仅表示一个月的总和。

\n\n

当我加载“user1”的数据时,一切看起来都很好:\n图一有清晰的数据。

\n\n

但是当我用第二个用户加载数据时,它看起来像这样:\n图 2 有奇怪的数据。

\n\n

我真的不明白为什么会发生这种情况,因为我在从数据库中选择数据时对数据进行排序,如下所示:

\n\n
...NTING.CUSTOMER = \'"+Customer+"\' GROUP BY MONTH ORDER BY MONTH ASC;\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以\xe2\x80\xa6 这就是我能说的\xe2\x80\xa6 我在从数据库获取数据时订购数据,对于一个用户来说它有效,对于另一个用户则不然!这真的让我吓坏了!

\n\n

我刚刚发现有人建议下载 JRE 和 JDK 8 的“早期访问版本”的帖子 - 但在我看来,对于生产系统,我不会推荐这样做!

\n\n

希望有人能解决这个棘手的问题!

\n\n

就在有人大发雷霆之前,这不是答案——我知道!

\n\n

但我认为收集尽可能多的信息似乎也是解决方案的一部分。

\n\n

而且由于(有时 stackoverflow 的奇怪特权偏好)我无法发表评论,直到我获得更高的声誉值!

\n\n

我不想问新问题,虽然这里已经讨论过这个问题了!

\n\n

希望这没问题\xe2\x80\xa6

\n\n

问候

\n