Swing2維3維混合動態散點圖
本文已參與【新人創作禮】活動,一起開啟掘金創作之路
Swing2維3維混合動態散點圖
覺得有用的話,歡迎一起討論相互學習~
* 使用的2D繪圖包是jfreechart,3D繪圖包是matplotlib for java V2
* PS:由於和我研究內容相關,如果看到類似SolutionSet的結構體,這是
Jmetal
中的設定本質我只要其中的double數值。
思路
- 一個Jframe
- 四個Jpanel,網格佈局
- 第一個三維,後三個2維
佈局和繫結
```java 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
```java 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
```java 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散點圖 ```java 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畫三維點陣圖
```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
一下java 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包對畫動態散點圖的套話
java 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- ```java
mgr.setScaleX(1);
mgr.setScaleY(1);
mgr.setScaleZ(1);
mgr.setSeeta(0.6);
mgr.setBeita(1.0);
mgr.setTitle(name); mgr.fitScreem();
* 控制座標軸縮放比例和Title 6. 如果在Jframe中表示用show,如果是在JPanel中使用,不要show 7. 動態圖需要重新整理畫布,使用以下語句
java try { mgr.updateView(15); } catch (Exception e) { e.printStackTrace(); } ```
效果演示
- 注意:我的點是動態更新的,也就是說我的資料來源是SolutionSet,這個Set中的OBJ Values 和DCV Values本身都是動態更新的。只是不斷重新整理我的Jpanel而已。