Using ZKGrails I wanted to use its built-in chart tags. However, since the last time I used ZK (3 years ago) they no longer provide charts in their free version.
FYI, ZKGrails no longer supports having zscript code in the .zul pages, so the process of trying to get a dynamically rendered image embedded into a .zul page was that much more difficult. All the code must be the ZKGrails composer class, so rapid prototyping is out.
The difficulty was compounded by an optional ZKGrails Groovy Builder code supported inside the ZKGrails composers. The builder creates a JQuery like syntax for selecting ZK components from the .zul view. Since it provides a "Groovyer" syntax I wanted to use it, but it did add some mental overhead.
So using jFreeChart I created a Grails service, which just statically returns a jFreeChart. The chart is just a static chart I found in one of the jFreechart demos.
package com.lcr.audit import org.jfree.chart.ChartFactory import org.jfree.chart.ChartPanel import org.jfree.chart.JFreeChart import org.jfree.chart.plot.PlotOrientation import org.jfree.chart.plot.XYPlot import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer import org.jfree.ui.ApplicationFrame import org.jfree.ui.RefineryUtilities import org.jfree.data.category.DefaultCategoryDataset class ChartService { static transactional = false def getChart() { def dataset = createDataset() def chart = createChart(dataset) return chart } def createDataset(){ DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(212, "Classes", "JDK 1.0"); dataset.addValue(504, "Classes", "JDK 1.1"); dataset.addValue(1520, "Classes", "SDK 1.2"); dataset.addValue(1842, "Classes", "SDK 1.3"); dataset.addValue(2991, "Classes", "SDK 1.4"); return dataset } def createChart(dataset){ JFreeChart chart = ChartFactory.createLineChart( "Java Standard Class Library", // chart title "Release", // domain axis label "Class Count", // range axis label dataset, // data PlotOrientation.VERTICAL, // orientation false, // include legend true, // tooltips false // urls ) return chart } }
This returns a chart that looks like this:
This image is a jFreechart "chart" object, which provides a method that converts it to a buffered image class. After a great deal of trial and error and searching the web, I found a ZK example that I partially got to work, proving I could render a dynamic image, and the code only needed a buffered image as input.
ZK Demo Dynamic Images
Here is a basic .zul page which will work to render the single dynamic chart from the above chart service:
The important line is:![]()
The "id" of "img" is what we will use to select this image component and set its content to our chart buffered image.
Now, let's look at the ZKGrails Composer:
package com.lcr.audit import org.zkoss.zk.grails.composer.* import org.zkoss.zk.ui.select.annotation.Wire import org.zkoss.zk.ui.select.annotation.Listen class DomBillAuditToolComposer extends GrailsComposer { def chartService def img def afterCompose = { window -> // initialize components here def chart = chartService.getChart() def bufferImg = chart.createBufferedImage(700, 200) img.setContent(bufferImg) } }This composer is not coded using the ZKGrails Builder JQuery syntax. This was the how I first got it to work. Later, I got help from to get the ZKGrails Builder code to work.
Google Groups: ZKGrails User Group
Lines 10 and 16 are important. "def img" is how we select the ZK Image component from the .zul page. Now, the variable img can be used as it is in line 16 to call the "setContent()" method, so we can pass in our buffered image.
Using the ZKGrails builder code we could do something like this:
$('#img').append{ def chart = chartService.getChart() def bufferImg = chart.createBufferedImage(700, 200) def img = $('#chart01') // Or: def img = $('#chart01')[0] img.setContent(bufferImg) }
This is how the ZK image component is selected:
$('#img')
Because we are not appending anything to the "img" ZK Image component, maybe we don't need to select the component like this:
$('#img').append{}
Because notice we are "selecting" the component again in this line.
def img = $('#chart01')This is similar to what we did in the first composer code above, which uses the older style.
Note: if you have no JQuery background, you may find the JQuery style of having a dollar sign and parentheses $(blah), strange, and very non-Groovy. When I first saw it I had no idea what it was. It is optional, as you can always use the first composer syntax.
0 comments:
Post a Comment