PDA

View Full Version : [CLOSED] Display errors in AreaChart's XAxis



dscholl
10 Mar 2011, 1:57 AM
Hi guys!

Here is my use case: I try to make a continuous displaying of time dependent monitoring data in an area chart. I set the time X as zero and add my dots as relative values.
For example:
dot1: y=5, x=0
dot2: y=6, x=5000
dot3: y=4, x=10000
and so on.

Every update cycle, I redefine the values of the x-axis labels by defining ten steps in the specific time range. I do this with the following code snippet:


XAxis axis = chart.getChartModel().getXAxis();

long timeStamp = p_measurementData.getKey();
long relativeTimeStamp = roundTimeStamp(timeStamp - m_displayRangeBegin);

Long steps = relativeTimeStamp / monitoringChartXAxisStepCount;
axis.setRange(0, relativeTimeStamp,steps);
axis.setLabels(redefineLabels(monitoringChartXAxisStepCount)); // returns List<String>
axis.getLabels().setSteps(steps.intValue());


The problem:
Every label is add is rendered on the same position, this looks like that:
http://img7.imageshack.us/img7/3668/testjz.jpg (http://img7.imageshack.us/i/testjz.jpg/)
Uploaded with ImageShack.us (http://imageshack.us)

It happens both in web mode and hosted mode, using GWT 2.0.3 and GXT 2.2.0. Tested with latest Firefox (3.6) and Chrome 9 and 10 on Windows XP.

Here is some standalone sample code:


import com.extjs.gxt.charts.client.Chart;
import com.extjs.gxt.charts.client.ChartManager;
import com.extjs.gxt.charts.client.model.ChartModel;
import com.extjs.gxt.charts.client.model.Legend;
import com.extjs.gxt.charts.client.model.axis.XAxis;
import com.extjs.gxt.charts.client.model.axis.YAxis;
import com.extjs.gxt.charts.client.model.charts.AreaChart;
import com.extjs.gxt.charts.client.model.charts.ChartConfig;
import com.extjs.gxt.charts.client.model.charts.dots.BaseDot;
import com.extjs.gxt.charts.client.model.charts.dots.Dot;
import com.extjs.gxt.ui.client.Style;
import com.extjs.gxt.ui.client.data.BaseModelData;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.Composite;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.form.TextArea;
import com.extjs.gxt.ui.client.widget.layout.LayoutData;
import com.extjs.gxt.ui.client.widget.layout.RowData;
import com.extjs.gxt.ui.client.widget.layout.RowLayout;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.resources.client.*;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class Sample implements EntryPoint {

private static final long monitoringChartXAxisStepCount = 10;

@Override
public void onModuleLoad() {
HandlerManager manager = new HandlerManager(this);
MonitoringWidget widget = new MonitoringWidget("chart", new String[]{"test"},manager);
RootPanel.get("content").add(widget);
widget.setSize(500,500);
}

private void continueExample() {
m_displayRangeBegin = System.currentTimeMillis() - 100000;

for(int i_count = 0; i_count < 10; i_count++) {
performUpdateChartData("chart", new ValuePair<Long, Integer>(m_displayRangeBegin + i_count * 1000, 5));
}
}

//########## View

private class MonitoringWidget extends Composite {

private static final String CHART_URL_POSTFIX = "gxt/chart/open-flash-chart.swf";
private boolean isReady = false;

private Chart m_chart;

private transient String m_chartUrl;
private String m_chartId;
private String[] m_chartNames;
private ContentPanel m_mainContainer;

public MonitoringWidget(String p_chartid, String[] p_chartNames, HandlerManager p_eventBus) {
m_chartId = p_chartid;
m_chartNames = p_chartNames;

m_chartUrl = GWT.getModuleBaseURL() + CHART_URL_POSTFIX;

ContentPanel horizental = new ContentPanel();
horizental.setLayout(new RowLayout(Style.Orientation.HORIZONTAL));
horizental.setHeaderVisible(false);
horizental.setCollapsible(false);

m_mainContainer = horizental;

if(isReady) {
createChart();
}
else {
try {
loadScript();
}
catch(ResourceException e) {
GWT.getUncaughtExceptionHandler().onUncaughtException(e);
}
}
setUp();

initComponent(m_mainContainer);
}

private void loadScript() throws ResourceException {
Script script = GWT.create(Script.class);
script.chartScript().getText(new ResourceCallback<TextResource>() {
@Override
public void onError(ResourceException e) {
GWT.getUncaughtExceptionHandler().onUncaughtException(e);
}
@Override
public void onSuccess(TextResource resource) {
if(isReady) {
m_mainContainer.removeAll();
createChart();
setUp();
m_mainContainer.layout(true);

return;
}

Element elem = DOM.createElement("script");

elem.setAttribute("type", "text/javascript");
elem.setAttribute("language","javascript");
// elem.setAttribute("src", "gxt/flash/swfobject.js");

elem.setInnerText(resource.getText());

DOM.appendChild(RootPanel.getBodyElement(), elem);

isReady = true;

m_mainContainer.removeAll();
createChart();
setUp();
m_mainContainer.layout(true);

continueExample();
}
});
}

private ChartModel getChartModel(String p_name, String[] p_chartNames) {
ChartModel cm = new ChartModel(p_name);
cm.setBackgroundColour("#ffffff");
XAxis xa = new XAxis();
// xa.setRange(0,Resources.getSettings().monitoringChartXAxisStepCount(),Resources.getSettings().monitoringChartXAxisStepCount());
YAxis ya = new YAxis();
cm.setXAxis(xa);
cm.setYAxis(ya);

Legend legend = new Legend(Legend.Position.TOP);
legend.setVisible(true);
cm.setLegend(legend);
cm.setThousandSeparatorDisabled(true);

// cm.setXLegend(new Text(Resources.getResourceBundle().time()));
// cm.setYLegend(new Text(Resources.getResourceBundle().count()));

for(ChartConfig config : getChartConfigs(p_chartNames)) {
cm.addChartConfig(config);
}

return cm;
}

private Iterable<ChartConfig> getChartConfigs(String[] p_chartNames) {
List<ChartConfig> list = new ArrayList<ChartConfig>();

for(int i_count = 0; i_count < p_chartNames.length; i_count++) {
AreaChart area = new AreaChart();
area.setFillAlpha(0.3f);

String color;

switch(i_count) {
default:
case 0:
color = "#ff0000";
break;
case 1:
color = "#00fa00";
break;
case 2:
color = "#0000ff";
break;
}
area.setColour(color);
area.setFillColour(color);
area.setText(p_chartNames[i_count]);

list.add(area);
}

return list;
}

@Override
public void onAttach() {
if(!isAttached()) {
super.onAttach();
}

m_mainContainer.removeAll();
// createChart();
setUp();
m_mainContainer.layout(true);
}

@Override
public void onDetach() {
super.onDetach();
// ChartManager.get().unregisterChart(m_chart);
}

private void createChart() {
createChart(getChartModel(m_chartId, m_chartNames));
}

private void createChart(ChartModel model) {
m_chart = new Chart(m_chartUrl);
m_chart.setSwfId(m_chartId);
m_chart.setHeight(250);
m_chart.setBorders(true);
m_chart.setChartModel(model);

ChartManager.get().registerChart(m_chart);
}

/*
Remember:
The height and width of each component can be specified with a RowData instance. There are 3 types of values:

Values less than or equal to 1 are treated as percentages, with 1 = 100%.
Values greater than 1 are treated as pixels.
Values equal to Style.DEFAULT (-1) will use the component's computed height.
*/
private void setUp() {
LayoutData vChartData = new RowData(0.7d, 1, new Margins(4));
if(m_chart != null) {
m_mainContainer.add(m_chart, vChartData);
}
else {
m_mainContainer.add(getChartNotAvailable(), vChartData);
}
}

private Widget getChartNotAvailable() {
TextArea area = new TextArea();

area.setEnabled(false);
area.setValue("errortext");
area.setStyleAttribute("color", "#000");
area.setStyleAttribute("font-weight", "bold");

return area;
}
}


//############ Presentation

private long m_displayRangeBegin;

private void performUpdateChartData(String p_chartId, ValuePair<Long, Integer> p_measurementData) {
Chart chart = ChartManager.get().getChart(p_chartId);
if(chart == null) {
return;
}

XAxis axis = chart.getChartModel().getXAxis();

long timeStamp = p_measurementData.getKey();
long relativeTimeStamp = roundTimeStamp(timeStamp - m_displayRangeBegin);

Long steps = relativeTimeStamp / monitoringChartXAxisStepCount;
axis.setRange(0, relativeTimeStamp,steps);
axis.setLabels(redefineLabels(monitoringChartXAxisStepCount));
axis.getLabels().setSteps(steps.intValue());

for(ChartConfig config : chart.getChartModel().getChartConfigs()) {
BaseDot dot = new Dot();
Number value = p_measurementData.getValue();

if(value == null) {
continue;
}

dot.setValue(value);
dot.setXY(relativeTimeStamp, dot.getY());

config.getValues().add(dot);
//checkYScale(chart.getChartModel().getYAxis(), value);
}

chart.refresh();
}

private List<String> redefineLabels(long p_stepCount) {
List<String> list = new ArrayList<String>();
long relativeTimeStamp = System.currentTimeMillis() - m_displayRangeBegin;

long step = relativeTimeStamp / p_stepCount;

for(int i_count = 0; i_count < p_stepCount; i_count++) {
long time = m_displayRangeBegin + (i_count * step);
String timeString = formatTime(time);
list.add(timeString);
}

return list;
}

private String formatTime(long p_timestamp) {
DateTimeFormat format = DateTimeFormat.getShortTimeFormat();
return format.format(new Date(p_timestamp));
}


private long roundTimeStamp(long p_time) {
return p_time -= (p_time % 1000);
}

//######## Datamodel

private static class ValuePair<T,U> extends BaseModelData implements IsSerializable, Serializable {

private static final String[] columnIDs = new String[] {
"name", "value"
};

private static final long serialVersionUID = 1792818929025668978L;

public ValuePair() {}


public ValuePair(T key, U value) {
set(columnIDs[0], key);
set(columnIDs[1], value);
}

@SuppressWarnings("unchecked")
public T getKey() {
Object tmp = get(columnIDs[0]);

try{
return (T) tmp;
}
catch(ClassCastException e) {
return null;
}
}

public void setKey(T p_key) {
set(columnIDs[0], p_key);
}

@SuppressWarnings("unchecked")
public U getValue() {
Object tmp = get(columnIDs[1]);

try{
return (U) tmp;
}
catch(ClassCastException e) {
return null;
}
}

public void setValue(U p_value) {
set(columnIDs[1], p_value);
}
}

//######### Resources
public interface Script extends ClientBundleWithLookup {
@Source("swfobject.js")
ExternalTextResource chartScript();
}

}



The only dependencies: Have swfobject.js available as resource and open-flash-chart.swf in the following path relative to the compiled code: "gxt/chart/open-flash-chart.swf"

Thank you for help.

sven
13 Mar 2011, 5:37 AM
I do not understany much of your code, but there are logical issue, thats why it fails.

You only define labels for x values from 0 to 9. But your dots are positioned at xvalues of 1000, 2000, etc. What is the reason for this?


private void performUpdateChartData(String p_chartId, ValuePair<Long, Integer> p_measurementData) {
Chart chart = ChartManager.get().getChart(p_chartId);
if (chart == null) {
return;
}

XAxis axis = chart.getChartModel().getXAxis();
axis.setLabels(redefineLabels(monitoringChartXAxisStepCount));

for (ChartConfig config : chart.getChartModel().getChartConfigs()) {
BaseDot dot = new Dot();
Number value = p_measurementData.getValue();

if (value == null) {
continue;
}

dot.setValue(value);

config.getValues().add(dot);
// checkYScale(chart.getChartModel().getYAxis(), value);
}

chart.refresh();
}

This is the corrected code.