-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi 2 all....
I have to add dual axis chart to my project. I have seen examples using jfree chat but don't know how to do the same using zk. I tried googling for the same but haven't found any result for the same. Please help me out...Hope for the reply asap.
Thanks
Piyush Garg
Not Dual Axis, but the way is the same. I do with chart.createBufferedImage create the chart
in memory and added to a zk 'AImage' component.
you can download the whole code here.
code for dual axis charts are here
/** * onClick button Bar Chart. <br> * * @param event * @throws IOException */ public void onClick$button_CustomerChart_BarChart(Event event) throws InterruptedException, IOException { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } div_chartArea.getChildren().clear(); // get the customer ID for which we want show a chart long kunId = getKunde().getKunId(); // get a list of data List<ChartData> kunAmountList = getChartService().getChartDataForCustomer(kunId); if (kunAmountList.size() > 0) { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); for (ChartData chartData : kunAmountList) { Calendar calendar = new GregorianCalendar(); calendar.setTime(chartData.getChartKunInvoiceDate()); int month = calendar.get(Calendar.MONTH) + 1; int year = calendar.get(Calendar.YEAR); String key = String.valueOf(month) + "/" + String.valueOf(year); BigDecimal bd = chartData.getChartKunInvoiceAmount().setScale(15, 3); String amount = String.valueOf(bd.doubleValue()); // fill the data dataset.setValue(new Double(chartData.getChartKunInvoiceAmount().doubleValue()), key + " " + amount, key + " " + amount); } String title = "Monthly amount for year 2009"; PlotOrientation po = PlotOrientation.VERTICAL; JFreeChart chart = ChartFactory.createBarChart(title, "Month", "Amount", dataset, po, true, true, true); CategoryPlot plot = (CategoryPlot) chart.getPlot(); plot.setForegroundAlpha(0.5f); BufferedImage bi = chart.createBufferedImage(750, 400, BufferedImage.TRANSLUCENT, null); byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true); AImage chartImage = new AImage("Bar Chart", bytes); Image img = new Image(); img.setContent(chartImage); img.setParent(div_chartArea); } else { div_chartArea.getChildren().clear(); Label label = new Label(); label.setValue("This customer have no data for showing in a chart!"); label.setParent(div_chartArea); } }
best
Stephan
HI terrytornado/Stephan,
I don't understand your post, where can i find an example of dual or multiple axis with zkoss? Your code is an example of... ??
Thanks in advance,
Carlos David
You can find several codes for dual axis chart here.
In my case all charts are used JFreeChart and at the end of creation of the chart it is copied into a ZKoss Image component. That's all.
Have a look at the sample app codes. Package de.forsthaus.webui.customer.
AImage chartImage = new AImage("Bar Chart", bytes);
Image img = new Image();
img.setContent(chartImage);
img.setParent(div_chartArea);
I have not implemented this case in the sample app because i have not the needed data for this case.
best
Stephan
Thanks Stephan,
I do it, now I have a multiple axis chart with zkoss... but what about the tooltips? I am using a window, a div and a bufferedImage instead a z:chart ...
Best,
Carlos David
Please can you show us the code ?
I will play a little bit with it.
Ok, I have this in my jsp.
<z:page> <z:window id="customChartWindow" use="org.cad.zksample.CustomChartCtrl" border="none" width="1024"> <z:div id="div_chartArea" height="350" width="1024"> The chart. </z:div> </z:window> </z:page>
And i have this in my java class.
public void onCreate$customChartWindow(Event event) throws Exception { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } /* autowire comps and vars */ doOnCreateCommon(customerChartWindow, event); buildGraph(); } public void buildGraph() throws InterruptedException, IOException { div_chartArea.getChildren().clear(); JFreeChart chart = processChart(); if (chart != null) { BufferedImage bi = chart.createBufferedImage(1024, 350, BufferedImage.TRANSLUCENT, null); byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true); AImage chartImage = new AImage(WebUtil.findMessage("pg_custom_graph_reports"), bytes); Image img = new Image(); img.setContent(chartImage); img.setParent(div_chartArea); } else { div_chartArea.getChildren().clear(); Label label = new Label(); label.setValue(WebUtil.findMessage("data_not_found")); label.setParent(div_chartArea); } } private static int[] intArray(double a, double b, double c) { return new int[] {(int) a, (int) b, (int) c}; } private static int[] intArray(double a, double b, double c, double d) { return new int[] {(int) a, (int) b, (int) c, (int) d}; } public Shape[] createStandardSeriesShapes(double shapeSize) { double size = shapeSize; double delta = size / 2.0; int[] xpoints = null; int[] ypoints = null; Shape[] result = new Shape[10]; // square result[0] = new Rectangle2D.Double(-delta, -delta, size, size); // circle result[1] = new Ellipse2D.Double(-delta, -delta, size, size); // up-pointing triangle xpoints = intArray(0.0, delta, -delta); ypoints = intArray(-delta, delta, delta); result[2] = new Polygon(xpoints, ypoints, 3); // diamond xpoints = intArray(0.0, delta, 0.0, -delta); ypoints = intArray(-delta, 0.0, delta, 0.0); result[3] = new Polygon(xpoints, ypoints, 4); // horizontal rectangle result[4] = new Rectangle2D.Double(-delta, -delta / 2, size, size / 2); // down-pointing triangle xpoints = intArray(-delta, +delta, 0.0); ypoints = intArray(-delta, -delta, delta); result[5] = new Polygon(xpoints, ypoints, 3); // horizontal ellipse result[6] = new Ellipse2D.Double(-delta, -delta / 2, size, size / 2); // right-pointing triangle xpoints = intArray(-delta, delta, -delta); ypoints = intArray(-delta, 0.0, delta); result[7] = new Polygon(xpoints, ypoints, 3); // vertical rectangle result[8] = new Rectangle2D.Double(-delta / 2, -delta, size / 2, size); // left-pointing triangle xpoints = intArray(-delta, delta, delta); ypoints = intArray(0.0, -delta, +delta); result[9] = new Polygon(xpoints, ypoints, 3); return result; } public static JFreeChart createTimeSeriesChart(String title, String timeAxisLabel, String valueAxisLabel, XYDataset dataset, boolean legend, boolean tooltips, boolean urls) { ValueAxis timeAxis = new DateAxis(timeAxisLabel); timeAxis.setLowerMargin(0.02); // reduce the default margins timeAxis.setUpperMargin(0.02); NumberAxis valueAxis = new NumberAxis(valueAxisLabel); valueAxis.setAutoRangeIncludesZero(false); // override default XYPlot plot = new XYPlot(dataset, timeAxis, valueAxis, null); XYToolTipGenerator toolTipGenerator = null; if (tooltips) { toolTipGenerator = StandardXYToolTipGenerator.getTimeSeriesInstance(); } XYURLGenerator urlGenerator = null; if (urls) { urlGenerator = new StandardXYURLGenerator(); } XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, false); renderer.setBaseToolTipGenerator(toolTipGenerator); renderer.setURLGenerator(urlGenerator); plot.setRenderer(renderer); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend); return chart; } public JFreeChart processChart() { List<String> seriesNames = (List<String>) getDesktop().getExecution().getAttribute("XYSeriesNames"); List<XYDataset> datasets = (List<XYDataset>)getDesktop().getExecution().getAttribute("XYDatasets"); Map<String,String> params = new HashMap<String,String>(); // Estos parámetros serán pasados usando el request params.put(WebUtil.findMessage("shapeSize"), "3"); params.put(WebUtil.findMessage("type"), "splines"); params.put(WebUtil.findMessage("col.aloc"), "#,###,###,###.0"); params.put(WebUtil.findMessage("col.abr']}"), "##0.0%"); params.put(WebUtil.findMessage("col.attempts']}"), "#,###,###,###"); params.put(WebUtil.findMessage("col.chrgtime']}"), "#,###,###,###"); JFreeChart jfreechart = createTimeSeriesChart(WebUtil.findMessage("pg_custom_graph_reports"),"Time of Day","Primary Range Axis",datasets.get(0),true, true, false); // Si hay más datasets y si tienen 4 o más de ellos if(datasets != null && datasets.size() > 0) { XYPlot xyPlot = (XYPlot) jfreechart.getPlot(); xyPlot.setOrientation(PlotOrientation.VERTICAL); xyPlot.setDomainPannable(true); xyPlot.setRangePannable(true); DateAxis dateAxis = (DateAxis)xyPlot.getDomainAxis(); dateAxis.setDateFormatOverride(new SimpleDateFormat(FormatterUtil.TIME_OF_DAY_OF_MONTH_FORMAT_PATTERN)); xyPlot.getRangeAxis().setFixedDimension(10D); ChartUtilities.applyCurrentTheme(jfreechart); ///// Add other datasets to chart //// for(int i=0; i < datasets.size(); i++) { int datasetIdx = i; String serieName = seriesNames.get(i); NumberAxis numberAxis = new NumberAxis(serieName); if(params.get(serieName) != null) { DecimalFormat formatter = new DecimalFormat(String.valueOf(params.get(serieName))); numberAxis.setNumberFormatOverride(formatter); } xyPlot.setRangeAxis(datasetIdx, numberAxis); xyPlot.setDataset(datasetIdx, datasets.get(i)); xyPlot.mapDatasetToRangeAxis(datasetIdx, datasetIdx); AbstractXYItemRenderer abstractXYItemRenderer = null; String typeOfLines = String.valueOf(params.get("type")); if("lines".equals(typeOfLines)) abstractXYItemRenderer = new XYLineAndShapeRenderer(); else if ("splines".equals(typeOfLines)) abstractXYItemRenderer = new XYSplineRenderer(); else abstractXYItemRenderer = new StandardXYItemRenderer(); xyPlot.setRenderer(datasetIdx, abstractXYItemRenderer); // Los datasets pares van a la izquierda, // el resto van a la derecha if(i % 2 == 0){ xyPlot.setRangeAxisLocation(i,AxisLocation.BOTTOM_OR_LEFT); } } // Aplicamos el template por default a todo el chart (ya tiene todas las series) ChartUtilities.applyCurrentTheme(jfreechart); double shapeSize = 6; if(params.get("shapeSize") != null) { shapeSize = Double.parseDouble(String.valueOf(params.get("shapeSize"))); } DefaultDrawingSupplier drawingSupplier = new DefaultDrawingSupplier( DefaultDrawingSupplier.DEFAULT_PAINT_SEQUENCE, DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE, DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE, createStandardSeriesShapes(shapeSize)); xyPlot.setDrawingSupplier(drawingSupplier,true); // Una vez aplicado el template modificamos los colores for(int i=0; i < datasets.size(); i++) { // El color actual es negro Color currentColor = Color.black; if(i < (MultipleAxis.DEFAULT_COLORS.length - 1)) { currentColor = MultipleAxis.DEFAULT_COLORS<i >; } else { // Si se acabó la paleta de colores genero uno al azar Random generator = new Random(); float h = generator.nextFloat(); float s = generator.nextFloat(); float b = generator.nextFloat(); currentColor = Color.getHSBColor(h, s, b); } xyPlot.getRenderer(i).setSeriesPaint(0,currentColor); NumberAxis numberAxis = (NumberAxis)xyPlot.getRangeAxis(i); numberAxis.setLabelPaint(currentColor); numberAxis.setTickLabelPaint(currentColor); numberAxis.setAutoRangeIncludesZero(true); } } return jfreechart; }
This code was based on your code and cewolf code :) . You gave me some ideas.
Thanks.
CDS
Thanks for sharing it.
This is my updated code, I generate the map for tooltips, but I can't make it to work ... see my comments in the sourcecode.
public void buildGraph() throws InterruptedException, IOException { div_chartArea.getChildren().clear(); JFreeChart chart = processChart(); if (chart != null) { // Get the number of renderers int rendererCount = ((XYPlot)chart.getPlot()).getRendererCount(); // Set a standard tooltip generator for each one for(int i=0; i < rendererCount; i++) ((XYPlot)chart.getPlot()).getRenderer(i).setBaseToolTipGenerator(StandardXYToolTipGenerator.getTimeSeriesInstance()); // Instance a chart info an send it to the createBufferedImage ChartRenderingInfo info = new ChartRenderingInfo(); BufferedImage bi = chart.createBufferedImage(1024, 350, BufferedImage.TRANSLUCENT, info); // Generate the imagemap from the chart info String map = ChartUtilities.getImageMap("testMap", info); byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true); AImage chartImage = new AImage(WebUtil.findMessage("pg_custom_graph_reports"), bytes); // Custom Image xul element, I add the attribute "usemap" org.cad.zksample.Image img = new org.cad.zksample.Image(); img.setContent(chartImage); img.setParent(div_chartArea); img.setUsemap("#testMap"); // Custom Div xul element, I add content to it -- currently doesn't work :'( org.cad.zksample.Div div = new org.cad.zksample.Div(); div.setContent(map); div.setParent(div_chartArea); } else { div_chartArea.getChildren().clear(); Label label = new Label(); label.setValue(WebUtil.findMessage("data_not_found")); label.setParent(div_chartArea); } }
Thanks in advance,
CDS
Finally, i did it...
I don't use my own Div element, because it doesn't work. I replaced it for an Html element.
// Custom Div xul element, I add content to it -- currently doesn't work :'( org.cad.zksample.Div div = new org.cad.zksample.Div(); div.setContent(map); div.setParent(div_chartArea);
I changed the above code with this:
Html html = new Html(); html.setContent(map); html.setParent(div_chartArea);
It's not the best, but it works... I hope that somebody can tell me a better/elegant solution.
Thanks,
CDS
Asked: 2009-07-01 10:49:12 +0800
Seen: 2,370 times
Last updated: Jul 03 '12