本文已参与【新人创作礼】活动,一起开启掘金创作之路
Swing2维3维混合动态散点图
觉得有用的话,欢迎一起讨论相互学习~
- 使用的2D绘图包是jfreechart,3D绘图包是matplotlib for java V2
- PS:由于和我研究内容相关,如果看到类似SolutionSet的结构体,这是
Jmetal中的设置本质我只要其中的double数值。
思路
- 一个Jframe
- 四个Jpanel,网格布局
- 第一个三维,后三个2维
布局和绑定
MatPlot3DMgr mgr1 = new MatPlot3DMgr();//mgr for obj1
MatPlot3DMgr mgr2 = new MatPlot3DMgr();//mgr for obj2
MatPlot3DMgr mgr3 = new MatPlot3DMgr();//mgr for dcv1
MatPlot3DMgr mgr4 = new MatPlot3DMgr();//mgr for dcv2
JFrame jfx = new JFrame(name1 + name2);
JPanel jp1 = new JPanel();
JPanel jp2 = new JPanel();
JPanel jp3 = new JPanel();
JPanel jp4 = new JPanel();
Container contentPaneX;
//控制窗口的大小
int jfxwidth = 900;
int jfxheight = 900;
int subplot_width = 400;
int subplot_height = 400;
int dcv_dim1 = 3;
int dcv_dim2 = 4;
void BindingPanel() {
contentPaneX = jfx.getContentPane();
contentPaneX.setLayout(new GridLayout(0, 2));
jp1.setSize(subplot_width, subplot_height);
jp2.setSize(subplot_width, subplot_height);
jp3.setSize(subplot_width, subplot_height);
jp4.setSize(subplot_width, subplot_height);
contentPaneX.add(jp1);
contentPaneX.add(jp2);
contentPaneX.add(jp3);
contentPaneX.add(jp4);
jfx.setDefaultCloseOperation(jfx.EXIT_ON_CLOSE);
jfx.setSize(jfxwidth, jfxheight);
jfx.setVisible(true);
}
feeding 2Dim data
public double[][] pack2Dplotdata(SolutionSet set, int dim1, int dim2) throws JMException {
double[][] data = new double[2][set.size()];
for (int i = 0; i < set.size(); i++) {
data[0][i] = set.get(i).getDecisionVariables()[dim1].getValue();
data[1][i] = set.get(i).getDecisionVariables()[dim2].getValue();
}
return data;
}
use Jfreechart to return 2dim Jpanel
public ChartPanel plot_2D(double[][] data, String name, String title) {
int chartwidth = subplot_width;
int chartheight = subplot_height;
DefaultXYDataset xydataset = new DefaultXYDataset();
xydataset.addSeries(title, data);//设置点的图标title一般表示这画的是决策变量还是目标函数值
JFreeChart chart = ChartFactory.createScatterPlot(name, "X", "Y", xydataset,
PlotOrientation.VERTICAL, true, true, false);//设置表头,x轴,y轴,name表示问题的类型
//以面板显示
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(chartwidth, chartheight));
return chartPanel;
}
plot 2dim scatter
- 这个好说,可以参考一下JFreechart绘制2D散点图
public void plot_DCV(SolutionSet set, String name, int dim1, int dim2) throws JMException {
double[][] data;
if (set.get(0).getSkillFactor() == 0) {
data = pack2Dplotdata(set, dim1, dim2);
ChartPanel chartPanel = plot_2D(data, name, "dcv");
jp3.removeAll();
jp3.add(chartPanel);
jp3.repaint();
jp3.revalidate();
jp3.updateUI();
contentPaneX.repaint();
contentPaneX.revalidate();
}
if (set.get(1).getSkillFactor() == 1) {
data = pack2Dplotdata(set, dim1, dim2);
ChartPanel chartPanel = plot_2D(data, name, "dcv");
jp4.removeAll();
jp4.add(chartPanel);
jp4.repaint();
jp4.revalidate();
jp4.updateUI();
contentPaneX.repaint();
contentPaneX.revalidate();
}
}
plot 3dim scatter
- 这个需要使用到matplotlib for java , 具体怎么使用可以参考使用Matplotlib 3D for JAVA画三维点阵图
if (set.get(0).getSkillFactor() == 0) {
jp1.removeAll();
JPanel mgrpanel = mgr.getPanel();
mgrpanel.setPreferredSize(new Dimension(subplot_width, subplot_height));
jp1.add(mgrpanel);
} else {
jp2.removeAll();
JPanel mgrpanel = mgr.getPanel();
mgrpanel.setPreferredSize(new Dimension(subplot_width, subplot_height));
jp2.add(mgrpanel);
}
mgr.setDataInputType(MatPlot3DMgr.DATA_TYPE_FUNCTION3D);
mgr.setDataInputType(MatPlot3DMgr.DATA_TYPE_DOTS);
mgr.getProcessor().setCoordinateSysShowType(mgr.getProcessor().COORDINATE_SYS_ALWAYS_FURTHER);
mgr.getProcessor().setCoordinateSysTransformationType(mgr.getProcessor().COORDINATE_RANGE_AUTO_FIT);
Point3D[] pointsarray = new Point3D[set.size()];
ArrayList<Point3D> aa = new ArrayList<>();
mgr.getProcessor().clear();
for (int i = 0; i < set.size(); i++) {
pointsarray[i] = new Point3D(set.get(i).getObjective(0), set.get(i).getObjective(1), set.get(i).getObjective(2));
}
for (int i = 0; i < set.size(); i++) {
aa.add(pointsarray[i]);
}
mgr.addData("Objective value", aa);
mgr.setScaleX(1);
mgr.setScaleY(1);
mgr.setScaleZ(1);
mgr.setSeeta(0.6);
mgr.setBeita(1.0);
mgr.setTitle(name);
mgr.fitScreem();
// mgr.show();//这句话是开始一个新的jframe,而不是一个jpanel
try {
mgr.updateView(15);
} catch (Exception e) {
e.printStackTrace();
}
}
- 有几点需要注意
JPanel mgrpanel = mgr.getPanel();mgr的本质是输出一个Jpanel ,如果是直接给到Jframe中会自动适应Frame的大小,但是如果是给到另一个Panel,需要setPreferredSize一下
mgr.setDataInputType(MatPlot3DMgr.DATA_TYPE_FUNCTION3D);
mgr.setDataInputType(MatPlot3DMgr.DATA_TYPE_DOTS);
mgr.getProcessor().setCoordinateSysShowType(mgr.getProcessor().COORDINATE_SYS_ALWAYS_FURTHER);
mgr.getProcessor().setCoordinateSysTransformationType(mgr.getProcessor().COORDINATE_RANGE_AUTO_FIT);
- mgr包对画动态散点图的套话
Point3D[] pointsarray = new Point3D[set.size()];
ArrayList<Point3D> aa = new ArrayList<>();
mgr.getProcessor().clear();
for (int i = 0; i < set.size(); i++) {
pointsarray[i] = new Point3D(set.get(i).getObjective(0), set.get(i).getObjective(1), set.get(i).getObjective(2));
}
for (int i = 0; i < set.size(); i++) {
aa.add(pointsarray[i]);
}
- 其中每个点都是一个Point3D对象,ArrayList aa 的这个集合将这些点组成一个颜色的集合,即在空间中使用一种legend表示,而如果想要表示不同的legend则新建一个集合对象例如bb就好
mgr.addData("Objective value", aa);添加点和legend
mgr.setScaleX(1);
mgr.setScaleY(1);
mgr.setScaleZ(1);
mgr.setSeeta(0.6);
mgr.setBeita(1.0);
mgr.setTitle(name);
mgr.fitScreem();
- 控制坐标轴缩放比例和Title
- 如果在Jframe中表示用show,如果是在JPanel中使用,不要show
- 动态图需要刷新画布,使用以下语句
try {
mgr.updateView(15);
} catch (Exception e) {
e.printStackTrace();
}
效果演示
- 注意:我的点是动态更新的,也就是说我的数据源是SolutionSet,这个Set中的OBJ Values 和DCV Values本身都是动态更新的。只是不断刷新我的Jpanel而已。