分形画板和分形图有什么不同呢?区别还是很大的。分形图可以说只是分形画板的基础。分形图只是加个鼠标监听器或者按钮监听器然后在画布上画出图形而已。学会了这个知识之后,才能开始设计一个分形画板。分形画板的难度在于,有一个菜单,还有两个面板,大概的形式是这样。
这只是一个初步的界面,菜单只有一个迭代实现分形,但事实上分形有很多很多种。界面做好了,可以看出来这个画板由两个面板和一个菜单组成。接下来就是麻烦的事了,西面画板的画布需要在多个类中存在,这样才能画出图形,同时西面画板的对象也要同样多个类中存在,要保证可以使用paintComponent来刷新西面面板。所以传参可以说是这个程序最麻烦的事情。
首先从最简单的开始,这是西面面板的代码。
publicclass JPanel1 extends JPanel {
public JPanel1() {
this.setPreferredSize(new Dimension(850, 600));
}
//重绘方法
publicvoid paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
}
}
接下来上东面板的代码:
publicclass JPanel2 extends JPanel {
private Graphics g12;
private Actionlis2 js2;
private JPanel1 jpanel1;
private JSlider js1;
private JsListener jslis;
public JPanel2(){
this.setPreferredSize(new Dimension(450, 600));
this.setLayout(null);
js1 = new JSlider(0, 50, 0);
js1.setBounds(100, 100, 200, 100);
}
publicvoid JPanel2(Graphics g12,JPanel1 jpanel1) {
this.g12 = g12;//传入西面面板的画布
this.jpanel1 = jpanel1;//传入西面面板
jslis = new JsListener(g12, jpanel1);
js1.addChangeListener(jslis);
this.add(js1);
JButton jb1 = new JButton("减少");
JButton jb2 = new JButton("增加");
jb1.setBounds(40, 140, 60, 60);
jb2.setBounds(340, 140, 60, 60);
jb1.setActionCommand("减少");
jb2.setActionCommand("增加");
js2 = new Actionlis2(js1);
jb1.addActionListener(js2);
jb2.addActionListener(js2);
this.add(jb1);
this.add(jb2);
}
//重绘方法
publicvoid paintComponent(Graphics g) {
super.paintComponent(g);
}
//调用此方法可以给第二个按钮监听器传入西面面板和画布
publicvoid JPanel21(Graphics g12, JPanel1 jpanel1) {
js2.setGraphics(g12);
js2.setJPanel1(jpanel1);
}
}
有人可能会问,为什么不在构造方法直接传入画板和画布呢?为什么要搞一个和类名一样的方法传入呢?这可以说是我专研过很久很久迫不得已的选择,也是我认为对的选择。在主函数里面,创建了东面面板之后才写出this.setVisible(true);,然后才能获取西面面板的画布,这三个顺序的步骤是不能更改的,所以在创建东面面板之后才有画布,所以只能采取这样的方法传入面板和画布。最后的JPanel21方法的作用是为按钮监听器传入画布和面板。
上拉杆监听器的代码:
publicclass JsListener implements ChangeListener {
private Graphics g;
private JPanel1 jp1;
privateintv;
public JsListener(Graphics g, JPanel1 jp1) {
this.g = g;
this.jp1 = jp1;
}
publicvoid stateChanged(ChangeEvent e) {
Object obj = e.getSource();
JSlider js = (JSlider) obj;
v = js.getValue();
if (test.string.equals("圆环")) {
jp1.paintComponent(g);
double a = 1.4, b = 1.56, c = 1.4, d = -6.56, x1 = 200, y1 = 200, x2 = 0, y2 = 0, x3, y3, x4, y4;
int f = 0;
for (int y = 0; y < 1000; y++) {
if (f == 0) {
x2 = d * Math.sin(a * x1) - Math.sin(b * y1);
y2 = c * Math.cos(a * x1) + Math.cos(b * y1);
f += 1;
} elseif (f == 1) {
for (int i = 0; i < v; i++) {
x3 = x2;
y3 = y2;
x2 = d * Math.sin(a * x3) - Math.sin(b * y3);
y2 = c * Math.cos(a * x3) + Math.cos(b * y3);
x4 = x2 * 50 + 400;
y4 = y2 * 50 + 350;
int red = (int) x4 - 250;
int green = (int) y4 - 250;
int blue = 180;
red = red < 0 ? 0 : red;
green = green < 0 ? 0 : green;
blue = blue < 0 ? 0 : blue;
red = red > 255 ? 255 : red;
green = green > 255 ? 255 : green;
blue = blue > 255 ? 255 : blue;
Color color = new Color(red, green, blue);
g.setColor(color);
g.drawLine((int) x4, (int) y4 - 80, (int) x4,
(int) y4 - 80);
}
}
}
} elseif (test.string.equals("号角")) {
jp1.paintComponent(g);
double a = -2, b = -2, c = -1.2, d = 2, x1 = 200, y1 = 200, x2 = 0, y2 = 0, x3, y3, x4, y4;
int f = 0;
for (int y = 0; y < 1000; y++) {
if (f == 0) {
x2 = Math.sin(a * y1) - Math.cos(b * x1);
y2 = Math.sin(c * x1) - Math.cos(d * y1);
f += 1;
} elseif (f == 1) {
for (int i = 0; i < v; i++) {
x3 = x2;
y3 = y2;
x2 = Math.sin(a * y3) - Math.cos(b * x3);
y2 = Math.sin(c * x3) - Math.cos(d * y3);
x4 = x2 * 100 + 350;
y4 = y2 * 100 + 350;
int red = (int) x4 - 250;
int green = (int) y4 - 250;
int blue = 180;
red = red < 0 ? 0 : red;
green = green < 0 ? 0 : green;
blue = blue < 0 ? 0 : blue;
red = red > 255 ? 255 : red;
green = green > 255 ? 255 : green;
blue = blue > 255 ? 255 : blue;
Color color = new Color(red, green, blue);
g.setColor(color);
g.drawLine((int) x4, (int) y4 - 80, (int) x4,
(int) y4 - 80);
}
}
}
}
}
}
拉杆监听器不难,传入西面面板和画布后自然就如鱼得水了。说一下这个类里面的test.string。这个东西是test类里面的一个全局属性,全部类都可以调用。上test类代码:
publicclass test {
publicstatic String string = " ";
}
很简单,3行。这个的作用是设置这个属性保存客户要求的分形图,比如点击菜单的某一个图形后,这个string就会有一个值,然后按钮监听器,拉杆监听器就会根据这个值画出对应的图形,所以需要这个值为全局变量。
上第一个按钮监听器代码:
publicclass Actionlis1 implements ActionListener {
private Graphics g;
private JPanel1 jpanel1;
private JPanel2 jp2;
public Actionlis1(JPanel1 jpanel1, Graphics g) {
this.jpanel1 = jpanel1;
this.g = g;
jp2 = new JPanel2();
}
publicvoid actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("圆环")) {
test.string = "圆环";
jpanel1.paintComponent(g);
double a = 1.4, b = 1.56, c = 1.4, d = -6.56, x1 = 200, y1 = 200, x2 = 0, y2 = 0, x3, y3, x4, y4;
;
int f = 0;
for (int y = 0; y < 1000; y++) {
if (f == 0) {
x2 = d * Math.sin(a * x1) - Math.sin(b * y1);
y2 = c * Math.cos(a * x1) + Math.cos(b * y1);
f += 1;
} elseif (f == 1) {
for (int i = 0; i < 1; i++) {
x3 = x2;
y3 = y2;
x2 = d * Math.sin(a * x3) - Math.sin(b * y3);
y2 = c * Math.cos(a * x3) + Math.cos(b * y3);
x4 = x2 * 50 + 400;
y4 = y2 * 50 + 350;
int red = (int) x4 - 250;
int green = (int) y4 - 250;
int blue = 180;
red = red < 0 ? 0 : red;
green = green < 0 ? 0 : green;
blue = blue < 0 ? 0 : blue;
red = red > 255 ? 255 : red;
green = green > 255 ? 255 : green;
blue = blue > 255 ? 255 : blue;
Color color = new Color(red, green, blue);
g.setColor(color);
g.drawLine((int) x4, (int) y4 - 80, (int) x4,
(int) y4 - 80);
}
}
}
} elseif (e.getActionCommand().equals("号角")) {
test.string = "号角";
jpanel1.paintComponent(g);
double a = -2, b = -2, c = -1.2, d = 2, x1 = 200, y1 = 200, x2 = 0, y2 = 0, x3, y3, x4, y4;
int f = 0;
for (int y = 0; y < 1000; y++) {
if (f == 0) {
x2 = Math.sin(a * y1) - Math.cos(b * x1);
y2 = Math.sin(c * x1) - Math.cos(d * y1);
f += 1;
} elseif (f == 1) {
for (int i = 0; i < 1; i++) {
x3 = x2;
y3 = y2;
x2 = Math.sin(a * y3) - Math.cos(b * x3);
y2 = Math.sin(c * x3) - Math.cos(d * y3);
x4 = x2 * 100 + 350;
y4 = y2 * 100 + 350;
int red = (int) x4 - 250;
int green = (int) y4 - 250;
int blue = 180;
red = red < 0 ? 0 : red;
green = green < 0 ? 0 : green;
blue = blue < 0 ? 0 : blue;
red = red > 255 ? 255 : red;
green = green > 255 ? 255 : green;
blue = blue > 255 ? 255 : blue;
Color color = new Color(red, green, blue);
g.setColor(color);
g.drawLine((int) x4, (int) y4 - 80, (int) x4,
(int) y4 - 80);
}
}
}
}
}
}
这个类很简单,只用于菜单按钮。作用就是当按钮选择了一个分形图形时,画出只有一层循环的图案,并且设置全局变量test.string为对应的值。
上第二个按钮监听器的代码:
publicclass Actionlis2 implements ActionListener {
private JSlider js;
intv;
private Graphics g1;
private JPanel1 jp1;
public Actionlis2(JSlider js){
this.js = js;
}
publicvoid actionPerformed(ActionEvent e) {
v = js.getValue();
if (test.string.equals("圆环")) {
if (e.getActionCommand().equals("减少")) {
js.setValue(v - 1);
jp1.paintComponent(g1);
double a = 1.4, b = 1.56, c = 1.4, d = -6.56, x1 = 200, y1 = 200, x2 = 0, y2 = 0, x3, y3, x4, y4;
int f = 0;
for (int y = 0; y < 1000; y++) {
if (f == 0) {
x2 = d * Math.sin(a * x1) - Math.sin(b * y1);
y2 = c * Math.cos(a * x1) + Math.cos(b * y1);
f += 1;
} elseif (f == 1) {
for (int i = 0; i <js.getValue(); i++) {
x3 = x2;
y3 = y2;
x2 = d * Math.sin(a * x3) - Math.sin(b * y3);
y2 = c * Math.cos(a * x3) + Math.cos(b * y3);
x4 = x2 * 50 + 400;
y4 = y2 * 50 + 350;
int red = (int) x4 - 250;
int green = (int) y4 - 250;
int blue = 180;
red = red < 0 ? 0 : red;
green = green < 0 ? 0 : green;
blue = blue < 0 ? 0 : blue;
red = red > 255 ? 255 : red;
green = green > 255 ? 255 : green;
blue = blue > 255 ? 255 : blue;
Color color = new Color(red, green, blue);
g1.setColor(color);
g1.drawLine((int) x4, (int) y4 - 80, (int) x4,
(int) y4 - 80);
}
}
}
} elseif (e.getActionCommand().equals("增加")) {
jp1.paintComponent(g1);
js.setValue(v + 1);
double a = 1.4, b = 1.56, c = 1.4, d = -6.56, x1 = 200, y1 = 200, x2 = 0, y2 = 0, x3, y3, x4, y4;
;
int f = 0;
for (int y = 0; y < 1000; y++) {
if (f == 0) {
x2 = d * Math.sin(a * x1) - Math.sin(b * y1);
y2 = c * Math.cos(a * x1) + Math.cos(b * y1);
f += 1;
} elseif (f == 1) {
for (int i = 0; i < js.getValue(); i++) {
x3 = x2;
y3 = y2;
x2 = d * Math.sin(a * x3) - Math.sin(b * y3);
y2 = c * Math.cos(a * x3) + Math.cos(b * y3);
x4 = x2 * 50 + 400;
y4 = y2 * 50 + 350;
int red = (int) x4 - 250;
int green = (int) y4 - 250;
int blue = 180;
red = red < 0 ? 0 : red;
green = green < 0 ? 0 : green;
blue = blue < 0 ? 0 : blue;
red = red > 255 ? 255 : red;
green = green > 255 ? 255 : green;
blue = blue > 255 ? 255 : blue;
Color color = new Color(red, green, blue);
g1.setColor(color);
g1.drawLine((int) x4, (int) y4 - 80, (int) x4,
(int) y4 - 80);
}
}
}
}
} elseif (test.string.equals("号角")) {
if (e.getActionCommand().equals("减少")) {
js.setValue(v - 1);
jp1.paintComponent(g1);
double a = -2, b = -2, c = -1.2, d = 2, x1 = 200, y1 = 200, x2 = 0, y2 = 0, x3, y3, x4, y4;
int f = 0;
for (int y = 0; y < 1000; y++) {
if (f == 0) {
x2 = Math.sin(a * y1) - Math.cos(b * x1);
y2 = Math.sin(c * x1) - Math.cos(d * y1);
f += 1;
} elseif (f == 1) {
for (int i = 0; i < js.getValue(); i++) {
x3 = x2;
y3 = y2;
x2 = Math.sin(a * y3) - Math.cos(b * x3);
y2 = Math.sin(c * x3) - Math.cos(d * y3);
x4 = x2 * 100 + 350;
y4 = y2 * 100 + 350;
int red = (int) x4 - 250;
int green = (int) y4 - 250;
int blue = 180;
red = red < 0 ? 0 : red;
green = green < 0 ? 0 : green;
blue = blue < 0 ? 0 : blue;
red = red > 255 ? 255 : red;
green = green > 255 ? 255 : green;
blue = blue > 255 ? 255 : blue;
Color color = new Color(red, green, blue);
g1.setColor(color);
g1.drawLine((int) x4, (int) y4 - 80, (int) x4,
(int) y4 - 80);
}
}
}
} elseif (e.getActionCommand().equals("增加")) {
js.setValue(v + 1);
jp1.paintComponent(g1);
double a = -2, b = -2, c = -1.2, d = 2, x1 = 200, y1 = 200, x2 = 0, y2 = 0, x3, y3, x4, y4;
int f = 0;
for (int y = 0; y < 1000; y++) {
if (f == 0) {
x2 = Math.sin(a * y1) - Math.cos(b * x1);
y2 = Math.sin(c * x1) - Math.cos(d * y1);
f += 1;
} elseif (f == 1) {
for (int i = 0; i <js.getValue(); i++) {
x3 = x2;
y3 = y2;
x2 = Math.sin(a * y3) - Math.cos(b * x3);
y2 = Math.sin(c * x3) - Math.cos(d * y3);
x4 = x2 * 100 + 350;
y4 = y2 * 100 + 350;
int red = (int) x4 - 250;
int green = (int) y4 - 250;
int blue = 180;
red = red < 0 ? 0 : red;
green = green < 0 ? 0 : green;
blue = blue < 0 ? 0 : blue;
red = red > 255 ? 255 : red;
green = green > 255 ? 255 : green;
blue = blue > 255 ? 255 : blue;
Color color = new Color(red, green, blue);
g1.setColor(color);
g1.drawLine((int) x4, (int) y4 - 80, (int) x4,
(int) y4 - 80);
}
}
}
}
}
}
publicvoid setGraphics(Graphics g1) {
this.g1 = g1;
}
publicvoid setJPanel1(JPanel1 jp1) {
this.jp1 = jp1;
}
}
也没有太大的难度,只是要注意要传入拉杆,并且点击按钮的时候改变value的值即可。
最后上main:
publicclass main extends JFrame {
publicstaticvoid main(String[] args) {
main jf = new main();
jf.unite();
}
privatevoid unite() {
this.setTitle("聪明蛋的项目");
this.setSize(new Dimension(1300, 600));
this.setResizable(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
// 创建网格布局
this.setLayout(new BorderLayout());
// 创建菜单栏
JMenuBar jmen = new JMenuBar();
// 创建菜单
JMenu jm = new JMenu("迭代实现分形");
// 创建菜单项
JMenuItem[] jmit = { new JMenuItem("圆环"), new JMenuItem("号角"),
new JMenuItem("树叶") };
// 创建西边画板
JPanel1 jpanel1 = new JPanel1();
this.add(jpanel1, BorderLayout.WEST);
jmen.add(jm);
this.setJMenuBar(jmen);
//创建东边画板
JPanel2 jpanel2 = new JPanel2();
this.add(jpanel2,BorderLayout.EAST);
this.setVisible(true);
Graphics g = jpanel1.getGraphics();
//将西边画板画布传给东边画板
jpanel2.JPanel2(g,jpanel1);
jpanel2.JPanel21(g,jpanel1);
// 实例化按钮监听器对象
Actionlis1 actionlis1 = new Actionlis1(jpanel1, g);
// 整合菜单栏
for (int i = 0; i < 3; i++) {
jmit[i].addActionListener(actionlis1);
jm.add(jmit[i]);
}
}
}