在RCP应用上使用Jfreechart绘制图表(附源码)
2012-06-28 16:21 飘扬的红领巾 阅读(2504) 评论(0) 收藏 举报下午闲来无事,找出Jfreechart来复习一下,做了个在RCP上使用Jfreechart的小程序。
第一步、创建RCP程序。
在Eclipse中,使用向导创建Eclipse插件程序:
后面就不说了,填写相应项,一路下去,创建好Eclipse插件程序,运行可以看到:
第二步、创建视图
创建视图既可以使用向导创建,也可以手动添加Java类,如添加类似这样的类:
public class ChartCategoryViewPart extends ViewPart
然后在Perspective .java中将创建的视图添加到透视图中:
public class Perspective implements IPerspectiveFactory {
@Override
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.addStandaloneView(
com.cnblogs.leefreeman.views.ChartCategoryViewPart.ID, true,
IPageLayout.LEFT, 0.23f, editorArea);
layout.addStandaloneView(ChartInfoViewPart.ID, true, IPageLayout.RIGHT,
0.77f, editorArea);
layout.setEditorAreaVisible(false);
layout.setFixed(true);
}
}
代码就不详细讲解了,最后会把整个例子的源代码共享出来。
创建了视图,应用程序运行起来就会是这样子:
第三步、在视图中创建树
在创建好的视图类中,添加创建树的代码,代码有点多不贴了,可以到附件中下载。
上图创建了一个树,表示将要在右边视图显示的图表的类别(柱状图、坐标图、饼图)
第四步、创建图表
先添加一个图表类,以饼图为例,如PieChart.java。
public class PieChart {
/**
* 创建提供给图表显示的数据
*
* @return
*/
private static PieDataset createDataset() {
DefaultPieDataset defaultpiedataset = new DefaultPieDataset();
defaultpiedataset.setValue("C", 17.00D);
defaultpiedataset.setValue("Java", 17.00D);
defaultpiedataset.setValue("C++", 9.00D);
defaultpiedataset.setValue("Objective-C", 8.00D);
defaultpiedataset.setValue("C#", 7.00D);
defaultpiedataset.setValue("Other", 42.00D);
return defaultpiedataset;
}
/**
* 创建图表
* @return
*/
@SuppressWarnings("deprecation")
public static JFreeChart createChart() {
PieDataset dataset = createDataset();
JFreeChart chart = ChartFactory.createPieChart3D("", dataset, true,
true, true);
// 设置图片的背景色
chart.setBackgroundPaint(java.awt.Color.white);
// 设置图片标题的字体和大小
TextTitle title = new TextTitle("编程语言排名");
chart.setTitle(title);
PiePlot3D pie = (PiePlot3D) chart.getPlot();
pie.setInsets(new RectangleInsets(5, 5, 5, 5));
// 指定 section 轮廓线的颜色
pie.setOutlinePaint(java.awt.Color.BLACK);
// 指定 section 轮廓线的厚度
pie.setOutlineStroke(new BasicStroke(1));
// 设置第一个 section 的开始位置,默认是12点钟方向,90度,逆时针
pie.setStartAngle(90);
// 指定 section 的色彩
pie.setSectionPaint(1, new Color(0x99, 0x99, 0xFF));
pie.setLabelFont(new Font("黑体", Font.BOLD, 12));
// 指定显示的饼图上圆形还椭圆形。true为圆形,false为椭圆形。默认为false
pie.setCircular(true);
// 指定图片的透明度
pie.setForegroundAlpha(0.5f);
pie.setLabelGap(0.01);// 间距
pie.setNoDataMessage("No data available");
return chart;
}
}
完成图表类之后,想要在视图中显示它,必须完成下面的工作:
@Override
public void createPartControl(Composite parent) {
JFreeChart chart = ChartFactory.createChart(categoryEnum);
if (chart != null) {
final ChartComposite frame = new ChartComposite(parent,
SWT.NONE, chart, true);
if (parent.getChildren().length > 1) {
parent.getChildren()[0].dispose();
}
frame.pack();
parent.layout();
}
}
ChartFactory类是自定义的一个图表工厂,用于创建指定的图表。做完这些事儿,之后。
第五步、实现视图间的通信
简单的来说,就是点击左边的树节点,右边视图中的图表根据点击的节点做相应的更新。实现此功能有很多种方法,常用的方法是在左边视图中,取得右边视图的句柄,然后调用其相关的方法,实现更新。但此方法耦合性较高,不便于扩展,我们不推荐此方法。这里我们使用观察者模式来实现此功能,也就说创建一个被观察者(主题),让视图作为观察者,监听其变化,当监听到主题变化时,做更新图表的操作。而左边视图所做的事情就是在用户点击时,改变主题的内容,触发它的变化。
为此我们这样做:
添加主题:StateModel.java
public class StateModel extends Observable implements IAdaptable {
private ChartCategoryEnum categoryEnum;
/**
* @return the categoryEnum
*/
public ChartCategoryEnum getCategoryEnum() {
return categoryEnum;
}
/**
* @param categoryEnum the categoryEnum to set
*/
public void setCategoryEnum(ChartCategoryEnum categoryEnum) {
this.categoryEnum = categoryEnum;
}
@Override
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
return null;
}
public void fireModelChanged() {
this.setChanged();
notifyObservers();
}
}
在应用程序启动时,放置到系统内存中:
@Override
public void postWindowOpen() {
StateModel stateModel = new StateModel();
try {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
configurer.getWindow().openPage(PERSPECTIVE_ID, stateModel);
} catch (WorkbenchException e) {
e.printStackTrace();
}
super.postWindowOpen();
}
在左边视图类中先从系统内存中取得StateModel(主题):
@Override
public void init(IViewSite site) throws PartInitException {
stateModel = (StateModel) site.getPage().getInput();
super.init(site);
}
然后点击事件中:
Object obj = ((IStructuredSelection) selection)
.getFirstElement();
if (obj.toString().equals("Bar Chart")) {
stateModel.setCategoryEnum(ChartCategoryEnum.BAR);
}
if (obj.toString().equals("Pie Chart")) {
stateModel.setCategoryEnum(ChartCategoryEnum.PIE);
}
if (obj.toString().equals("MultipleAxis Chart")) {
stateModel.setCategoryEnum(ChartCategoryEnum.MULTIPLEAXIS);
}
stateModel.fireModelChanged();
stateModel就会触发变更。
而在右边视图中,同样先从内存中取得stateModel,然后将自己加入到观察者队列中(视图必须实现Observer接口):
@Override
public void init(IViewSite site) throws PartInitException {
stateModel = (StateModel) site.getPage().getInput();
stateModel.addObserver(this);
super.init(site);
}
响应到主题变更后会自动调用update方法:
@Override
public void update(Observable o, Object arg) {
categoryEnum = stateModel.getCategoryEnum();
draw();
}
从而实现左右视图的消息传递。
(柱状图)
(坐标图)
下载







浙公网安备 33010602011771号