Java Swing绘制2维3维混合动态散点图

2021-03-16 11:14:10 浏览数 (1)

  • 使用的2D绘图包是jfreechart,3D绘图包是matplotlib for java V2
  • PS:由于和我研究内容相关,如果看到类似SolutionSet的结构体,这是Jmetal中的设置本质我只要其中的double数值。

思路

  1. 一个Jframe
  2. 四个Jpanel,网格布局
  3. 第一个三维,后三个2维

布局和绑定

代码语言:javascript复制
    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

代码语言:javascript复制
    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

代码语言:javascript复制
    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散点图
代码语言:javascript复制
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画三维点阵图
代码语言:javascript复制
 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();
            }

        }

  • 有几点需要注意
  1. JPanel mgrpanel = mgr.getPanel(); mgr的本质是输出一个Jpanel ,如果是直接给到Jframe中会自动适应Frame的大小,但是如果是给到另一个Panel,需要setPreferredSize一下
代码语言:javascript复制
            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包对画动态散点图的套话
代码语言:javascript复制
           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对象,ArrayListaa 的这个集合将这些点组成一个颜色的集合,即在空间中使用一种legend表示,而如果想要表示不同的legend则新建一个集合对象例如bb就好
  1. mgr.addData("Objective value", aa); 添加点和legend
代码语言:javascript复制
            mgr.setScaleX(1);
            mgr.setScaleY(1);
            mgr.setScaleZ(1);
            mgr.setSeeta(0.6);
            mgr.setBeita(1.0);

            mgr.setTitle(name);
            mgr.fitScreem();
  • 控制坐标轴缩放比例和Title
  1. 如果在Jframe中表示用show,如果是在JPanel中使用,不要show
  2. 动态图需要刷新画布,使用以下语句
代码语言:javascript复制
            try {
                mgr.updateView(15);
            } catch (Exception e) {
                e.printStackTrace();
            }

效果演示

  • 注意:我的点是动态更新的,也就是说我的数据源是SolutionSet,这个Set中的OBJ Values 和DCV Values本身都是动态更新的。只是不断刷新我的Jpanel而已。

0 人点赞