我正在使用StackedBarChart开发应用程序,但我发现了我认为是一个小错误,如果图表的动画属性设置为false,则不会呈现负值。尝试下面的代码进行测试,任何人都知道如何解决它?
提前致谢。
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* Created by fabiofrumento on 28/04/15.
*/
public class Scratch extends Application {
private static final SimpleDateFormat ONESECOND_CHART_DATE_FORMAT = new SimpleDateFormat("HH:mm:ss",
Locale.ENGLISH);
private boolean stopThreads;
CategoryAxis xAxisActive = new CategoryAxis();
CategoryAxis xAxisReactive = new CategoryAxis();
NumberAxis yAxisActive = new NumberAxis();
NumberAxis yAxisReactive = new NumberAxis();
{
xAxisActive.setLabel("Time");
xAxisReactive.setLabel("Time");
yAxisActive.setLabel("animated = false");
yAxisReactive.setLabel("animated = true");
}
private StackedBarChart<String, Number> onesecondActiveBarChart = new StackedBarChart<String, Number>(xAxisActive,
yAxisActive);
private StackedBarChart<String, Number> onesecondReactiveBarChart = new StackedBarChart<String, Number>(xAxisReactive,
yAxisReactive);
private XYChart.Series<String, Number> onesecondActiveConsumedSerie = new XYChart.Series<>();
private XYChart.Series<String, Number> onesecondActiveGeneratedSerie = new XYChart.Series<>();
private XYChart.Series<String, Number> onesecondReactiveConsumedSerie = new XYChart.Series<>();
private XYChart.Series<String, Number> onesecondReactiveGeneratedSerie = new XYChart.Series<>();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws
Exception {
VBox root = new VBox();
initCharts();
root.getChildren()
.addAll(onesecondActiveBarChart,
onesecondReactiveBarChart);
Scene scene = new Scene(root,
1024,
768);
primaryStage.setTitle("JecomoduleUI");
primaryStage.setScene(scene);
primaryStage.setFullScreen(true);
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent event) {
stopThreads = true;
}
});
primaryStage.show();
new Thread(new Runnable() {
@Override
public void run() {
while (!stopThreads) {
try {
Thread.sleep(1000);
Platform.runLater(new Runnable() {
@Override
public void run() {
updateActiveData();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
private void initCharts() {
onesecondActiveConsumedSerie.setName("Cons. W");
onesecondActiveGeneratedSerie.setName("Gen. W");
onesecondReactiveConsumedSerie.setName("Cons. VAR");
onesecondReactiveGeneratedSerie.setName("Gen.. VAR");
onesecondActiveBarChart.getData()
.addAll(onesecondActiveConsumedSerie,
onesecondActiveGeneratedSerie);
onesecondActiveBarChart.setAnimated(false);
onesecondReactiveBarChart.getData()
.addAll(onesecondReactiveConsumedSerie,
onesecondReactiveGeneratedSerie);
}
void updateActiveData() {
Date format = new Date();
Integer oneSecondActiveConsumedValue;
Integer oneSecondActiveGeneratedValue;
Double rand = Math.random();
Integer rnd = new Double(1000l + rand * 9000l).intValue();
if (rnd % 2 == 0) {
oneSecondActiveConsumedValue = rnd;
oneSecondActiveGeneratedValue = 0;
} else {
oneSecondActiveConsumedValue = 0;
oneSecondActiveGeneratedValue = 0 - rnd;
}
onesecondActiveConsumedSerie.getData()
.add(new XYChart.Data<String, Number>(ONESECOND_CHART_DATE_FORMAT.format(format),
oneSecondActiveConsumedValue));
if (onesecondActiveConsumedSerie.getData()
.size() > 10)
onesecondActiveConsumedSerie.getData()
.remove(0);
onesecondActiveGeneratedSerie.getData()
.add(new XYChart.Data<String, Number>(ONESECOND_CHART_DATE_FORMAT.format(format),
oneSecondActiveGeneratedValue));
if (onesecondActiveGeneratedSerie.getData()
.size() > 10)
onesecondActiveGeneratedSerie.getData()
.remove(0);
onesecondReactiveConsumedSerie.getData()
.add(new XYChart.Data<String, Number>(ONESECOND_CHART_DATE_FORMAT.format(format),
oneSecondActiveConsumedValue));
if (onesecondReactiveConsumedSerie.getData()
.size() > 10)
onesecondReactiveConsumedSerie.getData()
.remove(0);
onesecondReactiveGeneratedSerie.getData()
.add(new XYChart.Data<String, Number>(ONESECOND_CHART_DATE_FORMAT.format(format),
oneSecondActiveGeneratedValue));
if (onesecondReactiveGeneratedSerie.getData()
.size() > 10)
onesecondReactiveGeneratedSerie.getData()
.remove(0);
}
}
答案 0 :(得分:3)
是的,这似乎是一个JavaFX错误(Java 8u60)。
查看StackedBarChart
的源代码,只有在项目节点的样式类中找到“否定”时才能正确绘制具有负值的项目(请参阅StackedBarChart#layoutPlotChildren
)。
“负面”样式应由StackedBarChart#dataItemAdded
设置。对于动画图表StackedBarChart#animateData
被调用,如果项目的值为负,则将“否定”样式添加到节点。
对于非动画数据,该节点会添加到聊天的绘图子节点而不更新样式类。
作为解决方法,覆盖onesecondActiveBarChart的dataItemAdded
:
private StackedBarChart<String, Number> onesecondActiveBarChart = new StackedBarChart<String, Number>(xAxisActive, yAxisActive) {
@Override
protected void dataItemAdded(XYChart.Series<String,Number> series, int itemIndex, XYChart.Data<String,Number> item) {
super.dataItemAdded(series, itemIndex, item);
Node bar = item.getNode();
double barVal = item.getYValue().doubleValue();
if (barVal < 0) {
bar.getStyleClass().add("negative");
}
}
};