在这篇博客里提到我想要实现一个分形软件,晚上用Java写了一个简单的绘图框架来方便我实现各种分形算法,有了这个框架我就可以很容易的将实现的各种分形绘图算法集成进这个软件。
这个框架主要包含以下几个类:
- FractalMain类继承自JFrame,用于整个Frame的布局,这里通过用户选择的不同的MenuItem来执行不同的绘图功能,使用FractalPanel类提供的setPaintStype方法来控制调用不同的绘图算法;
- FractalPanel类继承自JPanel,用于调用不同的绘图算法,这里主要通过用户从FractalMain类设置过来的ShapeStyle来调用不同的绘图算法,绘图主要由paintComponent方法实现,此方法继承自JComponent,当用户从FractalMain选择不同的绘图算法时通过调用repaint方法实现;
- ShapeStyle是一个枚举,主要用于表示用户当前选择的绘图算法,通过这个枚举最终判断该调用那个类提供的draw方法;
- Cantor类是一个Cantor三分集的绘图算法实现;
当前这个框架已经基本满足现阶段的需求,只需要向这个框架中添加各种不同的绘图算法即可,每个绘图算法以一个新的类的形式出现,后续需要在这个框架中加入分形动画,还可能会加入自己制作分形图案的功能。
这个框架还需要完善的功能包括:
- 添加设置绘图颜色;
- 添加设置绘图的size;
- 增加用户配置文件保存;
- 增加分形图案保存功能;
FractalMain.java
package com.elvalad; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class FractalMain extends JFrame implements ActionListener { private JMenuBar menuBar; private JMenu fractalMenu; private JMenuItem blankItem; private JMenuItem cantorItem; private ShapeStyle style; private FractalPanel fractalPanel = new FractalPanel(); /** * FractalMain类的构造函数 */ public FractalMain() { /* JFrame继承自awt Frame类的方法,设置窗体标题 */ this.setTitle("Fractal"); /* 设置JFrame的初始大小 */ this.setSize(1000, 1000); /* 设置用户在此窗体上发起 "close" 时默认执行的操作 */ this.setDefaultCloseOperation(EXIT_ON_CLOSE); /* 设置窗口相对于指定组件的位置,当为null时在正中央 */ this.setLocationRelativeTo(null); /* 建立menu */ this.buildMenuBar(); /* 设置此窗体的菜单栏 */ this.setJMenuBar(this.menuBar); /* 添加fractalPanel到JFrame中央 */ this.add(this.fractalPanel, "Center"); /* 继承自Window类,根据参数显示或隐藏组件 */ this.setVisible(true); } /** * 创建MenuBar * MenuBar: menuBar * Menu: fractalMenu * MenuItem: blankItem * MenuItem: cantorItem */ private void buildMenuBar() { this.menuBar = new JMenuBar(); this.fractalMenu = new JMenu("Fractal"); this.blankItem = new JMenuItem("Blank"); this.blankItem.addActionListener(this); this.cantorItem = new JMenuItem("Cantor"); this.cantorItem.addActionListener(this); this.menuBar.add(this.fractalMenu); this.fractalMenu.add(this.blankItem); this.fractalMenu.add(this.cantorItem); } /** * 通过设置PaintStyle来绘制不同的图案 * 清空Panel上的图案 */ private void drawBlankOnPanel() { this.style = ShapeStyle.BLANK; this.fractalPanel.setPaintStype(this.style); this.repaint(); } /** * 通过设置PaintStyle来绘制不同的图案 * 绘制Cantor三分集 */ private void drawCantorOnPanel() { this.style = ShapeStyle.CANTOR; this.fractalPanel.setPaintStype(this.style); this.repaint(); } /** * * @param e awt事件接口,用于判断此时是哪种事件来选择执行不同的方法 */ public void actionPerformed(ActionEvent e) { if (e.getSource() == this.blankItem) { this.drawBlankOnPanel(); } else if (e.getSource() == this.cantorItem) { this.drawCantorOnPanel(); } } public static void main(String[] args) { new FractalMain(); } }
FractalPanel.java
package com.elvalad; import javax.swing.*; import java.awt.*; /** * Created by elvalad on 2014/12/27. */ public class FractalPanel extends JPanel { private Cantor cantor = new Cantor(100, 100, 800, 100, new Color(108, 187, 219)); private ShapeStyle style; public FractalPanel() { this.style = ShapeStyle.BLANK; } public void setPaintStype(ShapeStyle s) { this.style = s; } public void paintComponent(Graphics g) { super.paintComponent(g); switch (this.style) { case CANTOR: { this.drawCantor(g); break; } case BLANK: { break; } } } private void drawCantor(Graphics g) { this.cantor.draw(g); } }
ShapeStyle.java
package com.elvalad; /** * Created by elvalad on 2014/12/27. */ public enum ShapeStyle { BLANK, CANTOR }
Cantor.java
package com.elvalad; import java.awt.*; /** * Created by elvalad on 2014/12/27. */ public class Cantor { private double x1; private double y1; private double x2; private double y2; private Color color = new Color(108, 187, 219); /** * Cantor的构造函数 * @param x1 Cantor起始点的横坐标 * @param y1 Cantor起始点的纵坐标 * @param x2 Cantor终止点的横坐标 * @param y2 Cantor终止点的纵坐标 */ public Cantor(int x1, int y1, int x2, int y2, Color color) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.color = color; } /** * * @param */ public void draw(Graphics g) { g.setColor(this.color); this.drawShape(g, this.x1, this.y1, this.x2, this.y2); } /** * * @param g * @param x1 * @param y1 * @param x2 * @param y2 */ private void drawShape(Graphics g, double x1, double y1, double x2, double y2) { g.setColor(this.color); double c = 1.0; if ((x2 - x1) < c) { g.drawLine((int)x1, (int)y1, (int)x2, (int)y2); } else { double x3 = 0; double y3 = 0; double x4 = 0; double y4 = 0; g.drawLine((int)x1, (int)y1, (int)x2, (int)y2); x3 = x1 + (x2 - x1) / 3; y3 = y1 + 50; x4 = x2 - (x2 - x1) / 3; y4 = y2 + 50; y1 = y1 + 50; y2 = y2 + 50; drawShape(g, x1, y1, x3, y3); drawShape(g, x4, y4, x2, y2); } } }