这就是我现在在图表中添加一行的方法。这是我要显示的仲裁函数的抽象类:
public abstract class ArbitraryFunction implements
ValueProvider<ArbitraryFunctionData, Double> {
private String field;
public abstract Double f(Double x);
/**
* Constructor
*/
public ArbitraryFunction(String field) {
this.field = field;
}
@Override
public Double getValue(ArbitraryFunctionData object) {
return object.get(field);
}
@Override
public void setValue(ArbitraryFunctionData object, Double value) {
object.put(field, value);
}
@Override
public String getPath() {
return field;
}
}
这是图表的创建方式:
ArbitraryFunction f1 = new ArbitraryFunction("f1") {
@Override
public Double f(Double x) {
return Math.sin(x);
}
};
functionMap.put(f1.getPath(), f1);
// collects the data of the functions and adds them to the store
for (Double x = 0.0; x <= 2 * Math.PI; x = x + 0.1) {
ArbitraryFunctionData d = new ArbitraryFunctionData();
d.setName("" + x);
for (Map.Entry<String, ArbitraryFunction> entry : functionMap.entrySet()) {
ArbitraryFunction tmp = entry.getValue();
d.put(tmp.getPath(), tmp.f(x));
}
store.add(d);
}
chart.setStore(store);
verticalAxis.setPosition(Position.LEFT);
verticalAxis.addField(f1);
verticalAxis.setSteps(2);
verticalAxis.setMinorTickSteps(5);
chart.addAxis(verticalAxis);
这项工作已达到预期目的。图表显示了我应该这样做的线条,垂直轴也是正确的。但是我在绘制水平轴方面遇到了问题,因为我不知道需要给horizontalAxis.addField( ??? )
什么。我尝试了一些东西,但没有任何效果。
有谁知道我需要如何设置水平轴?
答案 0 :(得分:1)
你想要横轴值是多少?它是另一个NumericAxis - 每个数据点都有一个x
值,它应该被绘制吗?你的循环中的每个d
都有一个字符串name
和一些值 - 也许你想要一个CategoryAxis<ArbitraryFunctionData, String>
来绘制那些name
值?
看起来我之前误解了 - 你的Function对象只是在设置中使用,而不是改变你如何绘制数据
我仍然不确定你的目标是什么,但听起来你大多想要绘制一些线条。每个数据点(ArbitraryFunctionData?)似乎都有正在使用的每个函数的Y值和一个标题,但没有X值,因此没有办法将每个点用两个数轴绘制为(X,Y),就像( name,Y)使用CategoryAxis和NumericAxis。这最终会或多或少地像这个样本:http://www.sencha.com/examples/#ExamplePlace:linechart - 沿着底部的字符串,以及沿着侧面的数字。
这里有一个,主要是基于你已经拥有的想法/结构:
public class FunctionPlotter implements EntryPoint {
public static class ArbitraryFunctionData {
private double xValue;
private Map<String, Double> yValues = new HashMap<String, Double>();
public double get(String key) {
return yValues.get(key);
}
public void put(String key, double yValue) {
yValues.put(key, yValue);
}
public double getXValue() {
return xValue;
}
public void setxValue(double xValue) {
this.xValue = xValue;
}
}
public interface AFDProperties extends PropertyAccess<ArbitraryFunctionData> {
//xvalue is unique, key off of that
@Path("xValue")
ModelKeyProvider<ArbitraryFunctionData> key();
//automatic ValueProvider generation for the get/setXValue methods
ValueProvider<ArbitraryFunctionData, Double> xValue();
}
/**
* This is really doing two different jobs at once - wasn't quite was I was trying to suggest in
* that other question. See the second version of this for clarification...
*/
public static abstract class ArbitraryFunction implements ValueProvider<ArbitraryFunctionData, Double> {
private final String field;
public ArbitraryFunction(String field) {
this.field = field;
}
public abstract Double f(Double x);
@Override
public Double getValue(ArbitraryFunctionData object) {
return object.get(field);
}
@Override
public void setValue(ArbitraryFunctionData object, Double value) {
object.put(field, value);
}
@Override
public String getPath() {
return field;
}
}
@Override
public void onModuleLoad() {
Viewport vp = new Viewport();
Set<ArbitraryFunction> functions = new HashSet<ArbitraryFunction>();
ArbitraryFunction f1 = new ArbitraryFunction("f1") {
@Override
public Double f(Double x) {
return Math.sin(x);
}
};
functions.add(f1);
AFDProperties props = GWT.create(AFDProperties.class);
ListStore<ArbitraryFunctionData> store = new ListStore<ArbitraryFunctionData>(props.key());
// collects the data of the functions and adds them to the store
for (Double x = 0.0; x <= 2 * Math.PI; x = x + 0.1) {
// Create one data object, and set the X value, since that is the same for all Y values
ArbitraryFunctionData d = new ArbitraryFunctionData();
d.setxValue(x);
// For each function, set the corresponding Y value
for (ArbitraryFunction func : functions) {
d.put(func.getPath(), func.f(x));
}
store.add(d);
}
Chart<ArbitraryFunctionData> chart = new Chart<ArbitraryFunctionData>();
chart.setStore(store);
//Y-axis
NumericAxis<ArbitraryFunctionData> verticalAxis = new NumericAxis<ArbitraryFunctionData>();
verticalAxis.setPosition(Position.LEFT);
verticalAxis.addField(f1);//needs to know this field to properly set the range of values
//f2, f3, etc
verticalAxis.setSteps(2);
verticalAxis.setMinorTickSteps(5);
chart.addAxis(verticalAxis);
// X-Axis, this time reading from the xValue, not the series of ValueProviders
NumericAxis<ArbitraryFunctionData> horizAxis = new NumericAxis<ArbitraryFunctionData>();
horizAxis.setPosition(Position.BOTTOM);
horizAxis.addField(props.xValue());//same value for all
horizAxis.setSteps(2);
horizAxis.setMinorTickSteps(5);
chart.addAxis(horizAxis);
for (ArbitraryFunction func : functions) {
LineSeries<ArbitraryFunctionData> line = new LineSeries<ArbitraryFunctionData>();
// configure x axis
line.setXAxisPosition(Position.BOTTOM);//where is it
line.setXField(props.xValue());//what value do i use
// configure y axis
line.setYAxisPosition(Position.LEFT);//where is it
line.setYField(func);//what value do i use
//probably want to customized per func
line.setStroke(RGB.GRAY);
line.setStrokeWidth(2);
chart.addSeries(line);
}
vp.setWidget(chart);
RootPanel.get().add(vp);
}
}
这里有两个,这次有更简单的数据,实际上使函数成为自己的ValueProvider,并保持数据简单 - 只需一个双!请注意,ValueProvider 是函数,我们从不调用getValue,我们让轴/系列为我们做!在这里添加了第二个功能,以证明它确实有效。
public class FunctionPlotter implements EntryPoint {
/**
* Where did everything go? We're just making a ValueProvider now that can handle
* each number as a value, and working out the details from there
*
* For fun, added per-function coloring too
*/
public abstract static class Function implements ValueProvider<Double, Double> {
private final String name;
private final Color color;
public Function(String name, Color color) {
this.name = name;
this.color = color;
}
@Override
public abstract Double getValue(Double object);
@Override
public String getPath() {
return name;
}
@Override
public void setValue(Double object, Double value) {
//no-op
}
public Color getColor() {
return color;
}
}
@Override
public void onModuleLoad() {
Viewport vp = new Viewport();
Set<Function> functions = new HashSet<Function>();
Function f1 = new Function("f1", RGB.RED) {
@Override
public Double getValue(Double x) {
return Math.sin(x);
}
};
functions.add(f1);
Function f2 = new Function("f2", RGB.BLACK) {
@Override
public Double getValue(Double x) {
return Math.cos(x);
}
};
functions.add(f2);
//Turns out Stores can hold any objects - should probably factor out this key provider for reuse...
ListStore<Double> store = new ListStore<Double>(new ModelKeyProvider<Double>() {
@Override
public String getKey(Double item) {
return item.toString();
}
});
// collects the data of the functions and adds them to the store
for (Double x = 0.0; x <= 2 * Math.PI; x = x + 0.1) {
store.add(x);
}
Chart<Double> chart = new Chart<Double>();
chart.setStore(store);
//Y-axis
NumericAxis<Double> verticalAxis = new NumericAxis<Double>();
verticalAxis.setPosition(Position.LEFT);
for (Function func : functions) {
verticalAxis.addField(func);//needs to know this field to properly set the range of values
}
verticalAxis.setSteps(2);
verticalAxis.setMinorTickSteps(5);
chart.addAxis(verticalAxis);
// X-Axis, this time reading from the xValue, not the series of ValueProviders
NumericAxis<Double> horizAxis = new NumericAxis<Double>();
horizAxis.setPosition(Position.BOTTOM);
horizAxis.addField(new IdentityValueProvider<Double>());//magic value provider that returns the same string
horizAxis.setSteps(2);
horizAxis.setMinorTickSteps(5);
chart.addAxis(horizAxis);
for (Function func : functions) {
LineSeries<Double> line = new LineSeries<Double>();
// configure x axis
line.setXAxisPosition(Position.BOTTOM);//where is it
line.setXField(new IdentityValueProvider<Double>());//what value do i use
// configure y axis
line.setYAxisPosition(Position.LEFT);//where is it
line.setYField(func);//what value do i use
//probably want to customized per func
line.setStroke(func.getColor());
line.setStrokeWidth(2);
chart.addSeries(line);
}
vp.setWidget(chart);
RootPanel.get().add(vp);
}
}