gpt4 book ai didi

JavaFX NumberAxis AutoRange 无限循环

转载 作者:行者123 更新时间:2023-12-01 11:09:44 25 4
gpt4 key购买 nike

我有一个 LineChart,其中 Y 轴设置为自动范围。有时,JavaFx 线程会由于 NumberAxis.autoRange() 陷入无限循环而挂起。新数据由工作线程生成,然后每隔几秒添加到图表(在 JFX 线程上)。无限循环发生在这段代码中(取自 NumberAxis.autoRange()):

for (double major = minRounded; major <= maxRounded; major += tickUnitRounded, count ++)  {
double size = side.isVertical() ? measureTickMarkSize(major, getTickLabelRotation(), formatter).getHeight() :
measureTickMarkSize(major, getTickLabelRotation(), formatter).getWidth();
if (major == minRounded) { // first
last = size/2;
} else {
maxReqTickGap = Math.max(maxReqTickGap, last + 6 + (size/2) );
}
}

从调试中我发现 if (major == minRoundeed) 条件每次都是 true 。因此,major 变量一定不会被更新。

我没有带有局部变量调试信息的 NumberAxis 类的编译版本,因此我看不到局部变量是什么。构建 JavaFX 运行时类似乎需要大量工作,但可能是下一步。

我无法可靠地重现此问题,因此无法提供 Minimal, Complete, and Verifiable example 。我没有在 Oracle 或 OpenJDK bug 数据库中看到任何记录的问题。

JDK版本:8u60

编辑:

我向 Oracle 报告了此错误,目前正在等待他们接受。

最佳答案

问题

意味着循环将依赖于 double 值。因此,如果您尝试为 minValue 和 maxValue 取如此小的 double 值,则会失败。

是否有错误?

对我来说,这不像一个错误。你可以问自己,如果你真的想在你的轴上显示这么大的分数,或者你能更好地放大它们吗?您的应用程序的用户可能更喜欢阅读轴标签上带有底座的 1.5,而不是 0.000000000000000000000000000000000000000015 或 1.5E-33?

整个 Java API 中还有更多事情可能会发生这种情况,因为这是一个简单的数字溢出。

一个简单的例子

这将证明,如果值太小,它将无限循环。

import javafx.geometry.Side;


public class AutoRangeTester {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
AutoRangeTester art = new AutoRangeTester();
art.autoRange(Double.MIN_VALUE, Double.MIN_VALUE + 0.000000000000000000000000000000001, 100, 50);
}

/**
* Called to set the upper and lower bound and anything else that needs to be
* auto-ranged
*
* @param minValue The min data value that needs to be plotted on this axis
* @param maxValue The max data value that needs to be plotted on this axis
* @param length The length of the axis in display coordinates
* @param labelSize The approximate average size a label takes along the axis
*
* @return The calculated range
*/
public Object autoRange(double minValue, double maxValue, double length,
double labelSize) {
final Side side = Side.LEFT;
// check if we need to force zero into range
if (true) {
if (maxValue < 0) {
maxValue = 0;
} else if (minValue > 0) {
minValue = 0;
}
}
final double range = maxValue - minValue;
// pad min and max by 2%, checking if the range is zero
final double paddedRange = (range == 0) ? 2 : Math.abs(range) * 1.02;
final double padding = (paddedRange - range) / 2;
// if min and max are not zero then add padding to them
double paddedMin = minValue - padding;
double paddedMax = maxValue + padding;
// check padding has not pushed min or max over zero line
if ((paddedMin < 0 && minValue >= 0) || (paddedMin > 0 && minValue <= 0)) {
// padding pushed min above or below zero so clamp to 0
paddedMin = 0;
}
if ((paddedMax < 0 && maxValue >= 0) || (paddedMax > 0 && maxValue <= 0)) {
// padding pushed min above or below zero so clamp to 0
paddedMax = 0;
}
// calculate the number of tick-marks we can fit in the given length
int numOfTickMarks = (int) Math.floor(length / labelSize);
// can never have less than 2 tick marks one for each end
numOfTickMarks = Math.max(numOfTickMarks, 2);
// calculate tick unit for the number of ticks can have in the given data range
double tickUnit = paddedRange / (double) numOfTickMarks;
// search for the best tick unit that fits
double tickUnitRounded = 0;
double minRounded = 0;
double maxRounded = 0;
int count = 0;
double reqLength = Double.MAX_VALUE;

// loop till we find a set of ticks that fit length and result in a total of less than 20 tick marks
while (reqLength > length || count > 20) {
int exp = (int) Math.floor(Math.log10(tickUnit));
final double mant = tickUnit / Math.pow(10, exp);
double ratio = mant;
if (mant > 5d) {
exp++;
ratio = 1;
} else if (mant > 1d) {
ratio = mant > 2.5 ? 5 : 2.5;
}

tickUnitRounded = ratio * Math.pow(10, exp);

minRounded = Math.floor(paddedMin / tickUnitRounded) * tickUnitRounded;
maxRounded = Math.ceil(paddedMax / tickUnitRounded) * tickUnitRounded;

count = 0;
for (double major = minRounded; major <= maxRounded; major
+= tickUnitRounded, count++) {
System.out.println("minRounded: " + minRounded);
System.out.println("maxRounded: " + maxRounded);
System.out.println("major: " + major);
System.out.println("tickUnitRounded: " + tickUnitRounded);
System.out.println("-------------------------------------");
}

}
return null;
}

}

更新

错误报告:https://bugs.openjdk.java.net/browse/JDK-8136535计划在版本 9 中进行修复。

关于JavaFX NumberAxis AutoRange 无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32513409/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com