编程语言
首页 > 编程语言> > JavaFX LineChart / AreaChart在x轴上的分类值错误(CategoryAxis)

JavaFX LineChart / AreaChart在x轴上的分类值错误(CategoryAxis)

作者:互联网

当尝试构建包含可更新的LineChart或AreaChart的应用程序时,我发现了奇怪的行为 – 可能是由于应用程序逻辑中的错误?

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

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

例:

执行用
StartDate:01.09.2013
EndDate:25.09.2013
间隔:周

x轴上的值:

2013年9月1日/ 08.09.2013 / 15.09.2013 / 22.09.2013

单击“Days”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 / …)

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

这是执行技巧的代码(方法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;
 }
}

下面是DataComparator,负责根据x值按字母顺序对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轴,如果它们已经出现在旧图表中?

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

解决方法:

我有同样的问题.无论我如何设置绘图,通过使用新的数据点重新绘制,排序总是会搞砸.唯一的解决方法是使用java 1.8.

这是当时最新的fx,2.2.51-b13.不得不与fx8早期访问版本一起使用.

标签:linechart,java,sorting,javafx,charts
来源: https://codeday.me/bug/20190723/1508420.html