首先来看看最终效果,如果是你需要的那就继续来看代码的实现过程吧:
(上传的图片有点大个,看在我专门去转了gif大家就凑活看吧)
在这项程序中,主要创建了三个类,分别是:
定义替换规则和绘图的类:Koch;
监听器(拉杆监听器):Listener
界面:UI
在Koch中主要涉及两个方法:方法defineString实现字符替换,方法drawF实现根据绘图规则绘图,代码如下(这里是有关实现上述内容用到的所有代码,所以有需要的小伙伴可以直接复制看一下效果,应该改一下包名就可以。):
package LSystem;
import java.awt.Graphics;
public class Koch {
String str = "F";
public void defineString(int n,String newstr) {
//计步
int number = 0;
for(int i=0;i<str.length();i++) {
//将字符串中的F用新的字符串替换
str=str.replaceAll("F", newstr);
System.out.println(str);
number++;
if(number>=n) {
break;
}
}
}
public void drawF(Graphics g,double startx,double starty,double len,double angle) {
double theta = 0;
System.out.println(str);
int Fnum = 0;
//遍历第一遍确定F个数进而确定此时的len
for(int i = 0;i<str.length();i++) {
if((str.charAt(i)=='F')) {
Fnum++;
}
}
//确定len长度
if(Fnum==1) {
len = len;
}else {
len = len/(3*(Fnum/4));
}
//遍历第二遍根据指令绘图
for(int i = 0;i<str.length();i++) {
if(str.charAt(i)=='+') {
theta+=Math.PI/angle;
}else if((str.charAt(i)=='-')) {
theta-=Math.PI/angle;
}else if((str.charAt(i)=='F')) {
double endx = startx+len*Math.cos(theta);
double endy = starty-len*Math.sin(theta);
g.drawLine((int)startx, (int)starty, (int)(endx), (int)(endy));
//端点变起点
startx = endx;
starty = endy;
}
}
}
}
监听器的代码如下:
package LSystem;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Listener implements ChangeListener{
Graphics g;
Color color = Color.GREEN;
JSlider sliderd;
JSlider slidern;
JSlider slidertheta;
JTextField ruleIn;
public void stateChanged(ChangeEvent e) {
//更新画布,并在最后设置画笔颜色
Color curColor = g.getColor();
g.setColor(Color.black);
g.fillRect(0,0,1000,1000);
//得到滑杆d、n、θ的值
double len = sliderd.getValue();
int n = slidern.getValue();
int theta = slidertheta.getValue();
String f = ruleIn.getText();
g.setColor(color);
Koch koch = new Koch();
koch.defineString(n,f);
koch.drawF(g, 100, 200, len,theta);
System.out.println(len);
}
}
UI代码如下:
package LSystem;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
public class UI {
public void showUI() {
//创建窗体
JFrame uiframe = new JFrame();
uiframe.setSize(600,500);
uiframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
uiframe.setTitle("L-System");
//创建东侧面板,放置输入框、滑杆等
JPanel eastpanel = new JPanel();
eastpanel.setBackground(new Color(200,200,200));
Dimension dimension = new Dimension(150,500);
eastpanel.setPreferredSize(dimension);
uiframe.add(eastpanel,BorderLayout.EAST);
//创建一个绘图面板
JPanel centerpanel = new JPanel();
centerpanel.setBackground(Color.black);
uiframe.add(centerpanel,BorderLayout.CENTER);
//对象化监听器
Listener lis = new Listener();
//在东侧面板添加输入框、滑杆等部件
eastpanel.setLayout(new GridLayout(13,1));
eastpanel.add(new JLabel(" "));
eastpanel.add(new JLabel(" "));
eastpanel.add(new JLabel(" 输入演变规则"));
//创建文本框对象
JTextField rule = new JTextField();
eastpanel.add(rule);
eastpanel.add(new JLabel(" n"));
//创建滑杆n
JSlider n = new JSlider(0,10);
// 设置主刻度间隔
n.setMajorTickSpacing(5);
n.setPaintTicks(true);
n.setPaintLabels(true);
eastpanel.add(n);
eastpanel.add(new JLabel(" θ"));
//创建滑杆theta
JSlider theta = new JSlider(1,9);
eastpanel.add(theta);
eastpanel.add(new JLabel(" d"));
//创建滑杆d
JSlider d = new JSlider(0,3000);
// 设置主刻度间隔
d.setMajorTickSpacing(1500);
// 绘制 刻度 和 标签
d.setPaintTicks(true);
d.setPaintLabels(true);
eastpanel.add(d);
//设置界面可见
uiframe.setVisible(true);
//创建窗体的graphics
Graphics g = centerpanel.getGraphics();
//让窗体的graphics等于监听器的
lis.g = g;
//为滑杆n创建监听器
n.addChangeListener(lis);
lis.slidern = n;
//为滑杆d创建监听器
d.addChangeListener(lis);
lis.sliderd = d;
//为滑杆theta创建监听器
theta.addChangeListener(lis);
lis.slidertheta = theta;
//获取输入规则里的内容
lis.ruleIn = rule;
}
public static void main(String[] args) {
UI ui = new UI();
ui.showUI();
}
}
这样就可以实现依据输入 的绘图规则,如“F+F–F+F”,调整角度和迭代次数或者长度来绘图啦。
当然这个小程序还有很多需要改进的地方,例如可以加入更多的绘图指令,如添加对[]的定义,还有就是每次绘图的起始位置起始可以做的更加智能化 ,设计图形界面时有些代码可能可以进行进一步优化,而不这么机械化,等等等等
继续改进继续加油,希望可以帮助到有需要的小伙伴,小苗要更加努力呀!!