现在只剩下了最后10%的工作——添加菜单和按钮的功能。菜单栏可以选择两种模式:单一规则和随机规则模式;点击按钮实现单步迭代。
答曰:我也不懂,但你一看下面的这个代码就懂了……{!参考http://blog.csdn.net/selena1122/article/details/37810579}
package myFenxing.release; import java.awt.CheckboxMenuItem; import java.awt.Frame; import java.awt.Menu; import java.awt.MenuBar; import java.awt.MenuItem; import java.awt.MenuShortcut; import java.awt.TextArea; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; /** * 简单的菜单项例子 * 菜单条-----菜单-----菜单项 * 其中,菜单中可以包含菜单,组成二级菜单 * @author elena * @date 2014-7-15上午09:51:29 * @version 1.0 */ public class SimpleMenu { private Frame f = new Frame("菜单测试"); private MenuBar mb = new MenuBar(); Menu file = new Menu("文件"); Menu edit = new Menu("编辑"); MenuItem newItem = new MenuItem("新建"); MenuItem saveItem = new MenuItem("保存"); // 创建exititem菜单项,指定使用ctrl+x快捷键 MenuItem exitItem = new MenuItem("退出", new MenuShortcut(KeyEvent.VK_X)); CheckboxMenuItem autoWrap = new CheckboxMenuItem("自动换行"); MenuItem copyiItem = new MenuItem("复制"); MenuItem pasteItem = new MenuItem("粘贴"); Menu format = new Menu("格式"); // 创建commentem菜单项,指定使用ctrl+shift+/快捷键 MenuItem commentItem = new MenuItem("注释", new MenuShortcut( KeyEvent.VK_SLASH, true)); MenuItem cancelItem = new MenuItem("取消注释"); private TextArea ta = new TextArea(6, 40); public void init() { // 以匿名内部类的形式创建菜单监听器 ActionListener menuListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub String cmd = e.getActionCommand(); ta.append("单击" + cmd + "菜单" + "\n"); if (cmd.equals("退出")) { System.exit(0); } } }; commentItem.addActionListener(menuListener); exitItem.addActionListener(menuListener); // 为file菜单添加菜单项 file.add(newItem); file.add(saveItem); file.add(exitItem); // 为edit菜单添加菜单项 edit.add(autoWrap);// 自动换行 // 使用addseparator方法来添加菜单分割线 edit.addSeparator(); edit.add(copyiItem); edit.add(pasteItem); // 为format菜单添加菜单项 format.add(commentItem); format.add(cancelItem); // 使用添加new menuitem(”-“)的方式添加菜单分割线 edit.add(new MenuItem("-")); // 将format菜单组合到edit菜单中,从而形成二级菜单 edit.add(format); // 将file edit菜单添加到mb菜单条中 mb.add(file); mb.add(edit); // 为窗体f设置菜单条 f.setMenuBar(mb); // 以匿名内部类的形式创建事件监听器对象 f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { ta.append("用户试图关闭窗口\n"); System.exit(0); } }); f.add(ta); f.pack(); f.setVisible(true); } public static void main(String[] args) { new SimpleMenu().init(); } }
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String cmd = e.getActionCommand();
if (cmd.equals("退出")) {
System.exit(0);
}else if(cmd.equals("单一规则")){
//System.out.print("单一规则");
this.statement= "F"; mode=1; itemChange=true;
this.statement= this.caluStatement1(4);
this.reinit();
}else if(cmd.equals("随机规则")){
this.statement= "F"; mode=2; itemChange=true;
this.statement= this.caluStatement2(5);
this.reinit();
}else if(cmd.equals("技术支持")){
try { Process process = Runtime.getRuntime().exec("explorer http://my.oschina.net/SnifferApache/blog/353418");
} catch (IOException IOe) {
IOe.printStackTrace();
}
}else if(cmd.equals("About 牛逼的树")){
JOptionPane.showMessageDialog(this, "LLC实验室制作\nhttp:gdauto.gdut.edu.cn/");
}
}
注意:选中某个模式之后,需要重新计算statement,并重新画图。同时还要改变按钮显示文字,所以要在reinit方法中添加
canvas.setStatement(statement);
canvas.repaint();
if(this.itemChange){
this.itemChange= false;
this.step= 1;//重置步骤数
button_step.setLabel("单步迭代");
label_step.setText(" ");
}
而Canvas的repaint方法是在当前参数基础上重新画图,不满足需要,所以我们也要覆写repaint,添加
//清除旧的图像
repaint(0, 0, 0, getWidth(), getHeight());
//重置画图参数
pStartX =320; //原始起始点340,20
pStartY =20;
direction_init =90; // 作画时的初始方向
direction =direction_init;
lengthF =4.5; //步长
rotation =30; //给定转角
根据当前的模式来决定单步实现哪个规则,计算新的statement,再次画图即可
//button的响应事件 public boolean action(Event ev, Object arg){ if ( ev.target instanceof Button) { String button = (String) arg; if (button.equals("单步迭代")) { button_step.setLabel("迭代一步"); label_step.setText("第"+step+"步"); this.statement= "F"; if(mode== 1){ this.caluStatement1(1); }else{ this.caluStatement2(1); } this.reinit(); } if (button.equals("迭代一步")){ step++; label_step.setText("第"+step+"步"); this.statement= "F"; if(mode== 1){ this.caluStatement1(step); }else{ this.caluStatement2(step); } this.reinit(); } return true; }else return false; }
package myFenxing.UI; /** * @author Jason * @Corp LLC lab * @version LS grammar implementation */ import java.awt.*; import java.awt.event.*; import java.applet.*; import java.io.IOException; import java.util.Vector; import javax.swing.JOptionPane; //画布 class MyCanvas extends Canvas{ String statement; //LS文法表达式 int pStartX =320; //起始点340,20 int pStartY =20; double direction_init =90; // 作画时的初始方向 double direction =direction_init; double lengthF =4.5; double rotation =30; int StartDepth =7; //画图深度 doublePoint a, b; // 画线段所需的两点 MyCanvas(){ setBackground(Color.black); } public void setStatement(String s){ this.statement= s; } //改变窗口大小的时候会调用此方法重新绘图 public void paint(Graphics g){ //System.out.print("\n"+this.statement); a = new doublePoint(pStartX,pStartY); // 起始点 g.setColor(new Color(110,170,60)); // 定义画笔的颜色绿色 draw(g,this.statement); } //核心方法 public void draw(Graphics g, String statement){ Vector aPoint = new Vector();//用堆栈记录[]中的内容 Vector aDirection = new Vector(); String sDirection; int i; int j; char c; //System.out.print("\ndraw length "+statement.length()); for (i=0;i<statement.length();i++) { //获取公理中第i个字符,即解释instruction c = statement.charAt(i); if (c=='F') { double rad = 2*Math.PI*direction/360 ; // 角度转换 double p = lengthF * Math.cos(rad); double q = lengthF * Math.sin(rad); b = new doublePoint(a.x+p, a.y+q); //g=this.getGraphics(); g.drawLine((int)(a.x), (int)(400-a.y), (int)(b.x) ,(int)(400-b.y)); a = b; // 前一线段的终点为后一线段的起始点 } else if (c=='+') direction += rotation; //逆时针转角度 else if (c=='-') direction -= rotation; //顺时针转角度 else if (c=='[') { //入栈 aPoint.addElement(a); sDirection = String.valueOf(direction); aDirection.addElement(sDirection); } else if (c==']') { //出栈 a=(doublePoint)(aPoint.elementAt(aPoint.size()-1)); sDirection=(String)(aDirection.elementAt(aDirection.size()-1)); direction=Double.valueOf(sDirection).doubleValue(); aPoint.removeElementAt(aPoint.size()-1); aDirection.removeElementAt(aDirection.size()-1); } }//System.out.print("\ndraw over;"); } @Override public void repaint(){ //清除旧的图像 repaint(0, 0, 0, getWidth(), getHeight()); //重置画图参数 pStartX =320; //起始点340,20 pStartY =20; direction_init =90; // 作画时的初始方向 direction =direction_init; lengthF =4.5; rotation =30; this.paint(getGraphics()); } } //窗口 class MyWindow extends Frame implements ActionListener{ MyCanvas canvas= new MyCanvas(); //在画布中绘图的起始点340,20 int pStartX =320; int pStartY =20; Panel pSouth= new Panel(); MenuBar menubar= new MenuBar(); Menu menu1= new Menu("文件"); Menu mn_mode= new Menu(); Menu help= new Menu("帮助"); MenuItem item1= new MenuItem("退出"); MenuItem mn_mode_1= new MenuItem(); MenuItem mn_mode_2= new MenuItem(); MenuItem help_1= new MenuItem("技术支持"); MenuItem help_2= new MenuItem("About 牛逼的树"); Choice choice= new Choice(); Button button_step= new Button("单步迭代"); Label label_step= new Label(" "); Label info= new Label("LLC LAB"); //LS文法需要的变量 String statement,replacement; int step=1;//单步迭代的步骤 int mode=2;//模式1:单一规则,模式2:随机规则 boolean itemChange= false;//false表示item没有改变 String sStart; //公理;起始字符串 String sRule[][]; //存储规则 //构造方法 MyWindow(){ //默认状态下的公理 sStart = "F";//给公理赋值 statement= sStart; replacement= "F[+F]F[-F]F" ; //用来随机抽取,绘制随机植物 sRule = new String [10][2]; //设置UI setBackground(Color.lightGray); choice.addItem("牛逼的树"); pSouth.add(choice); pSouth.add(button_step); pSouth.add(label_step); pSouth.add(info); add(canvas,BorderLayout.CENTER); add(pSouth,BorderLayout.SOUTH); //设置menu this.setMenuBar(menubar); menubar.add(menu1); menubar.add(mn_mode); menubar.add(help); menu1.add(item1); mn_mode.add(mn_mode_1); mn_mode.add(mn_mode_2); help.add(help_1); help.add(help_2); mn_mode.setLabel("生成模式"); mn_mode_1.setLabel("单一规则"); mn_mode_2.setLabel("随机规则"); item1.addActionListener(this); mn_mode_1.addActionListener(this); mn_mode_2.addActionListener(this); help_1.addActionListener(this); help_2.addActionListener(this); } @Override public void actionPerformed(ActionEvent e) { //略 } //button的响应事件 public boolean action(Event ev, Object arg){ if ( ev.target instanceof Button) { String button = (String) arg; //略 }else return false; } //响应关闭操作 protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } } //窗口名称 public synchronized void setTitle(String title) { super.setTitle(title); enableEvents(AWTEvent.WINDOW_EVENT_MASK); } public void init() { //将计算出的statement传递给画布 canvas.setStatement(statement); this.setSize(pStartX*2,550); //获得屏幕长和宽,dimension类在一个单一对象中封装组建的宽和高 Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation((d.width - this.getSize().width) / 2, (d.height - this.getSize().height) / 2); this.setVisible(true); } //操作之后刷新 public void reinit(){ //将计算出的statement传递给画布 canvas.setStatement(statement); canvas.repaint(); if(this.itemChange){ this.itemChange= false; this.step= 1;//重置步骤数 button_step.setLabel("单步迭代"); label_step.setText(" "); } } /**计算LS表达式*/ //略 /**Main method*/ public class randomLS { public static void main(String args[]){ MyWindow instance= new MyWindow(); instance.setTitle("牛逼的树"); instance.statement= instance.caluStatement2(5); instance.init(); } }
效果图