文档章节

【分形算法】Jason带你飞之2——java AWT组件的使用

realsa
 realsa
发布于 2014/12/07 17:01
字数 1807
阅读 86
收藏 0

上一篇我们成功的写出了计算LS表达式的两个函数caluStatement1和caluStatement2,接下来需要“创造”一个窗口,并且按照规则进行画图。使用java.awt中的Canvas类来作图可以实现需要的效果。

1、使用Canvas类,在画布上画一个圆圈

import java.awt.*;
import java.awt.event.*;
//画布
class MyCanvas extends Canvas{
	int x,y,r;
	MyCanvas(){
		x=76; y=12; r=38;
		setBackground(Color.cyan);
	}
	public void paint(Graphics g){
		g.drawOval(x, y, 2*r, 2*r);
	}	
}
//窗口
class MyWindow extends Frame {
	MyCanvas canvas= new MyCanvas();
	
    //构造方法
	MyWindow(){
		Panel pn= new Panel();
		add(canvas,BorderLayout.CENTER);
		add(pn,BorderLayout.SOUTH);
		setBounds(100,100,300,200);
		setVisible(true);
	}
	//响应关闭操作
	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);
      }	
}
/**Main method*/
public class sheldon {
	public static void main(String args[]){
		MyWindow instance= new MyWindow();
		instance.setTitle("sheldon and his brain yeah");
	}
}

在这个代码中,我们重写了父类的public void paint(Graphics g)方法。当重写这个方法时,参数g是自动实例化的,这样就可以在子类中使用g的相应方法,比如画直线、画图形等等。同时组件调用repaint方法时,程序会首先清除paint方法以前所画的内容,然后再调用paint方法。

2、给窗口加上菜单、下拉列表和按钮

我们要做一个有菜单,中间是黑底的画布,画笔是绿色,底部加一个panel的窗口。

java中Frame的一个实例就是一个容器(可理解成一个窗口),Frame上可以添加panel,panel上可以添加button和label之类的控件,这些元素组成一个外表凑合的窗口。这么多组件放到一个容器上最好可以空置组件在容器中的位置,java.awt包中提供了FlowLayout、BorderLayout、CardLayout、GridLayout布局类,具体区别就不介绍了,我们将采用BorderLayout布局。

在MyWindow类中定义组件

Panel pSouth= new Panel();

MenuBar menubar= new MenuBar();

Menu menu1= new Menu("文件"); Menu mn_mode= new Menu(); Menu support= new Menu("技术支持");

MenuItem item1= new MenuItem("退出");

MenuItem mn_mode_1= new MenuItem(); MenuItem mn_mode_2= new MenuItem();

Choice choice= new Choice();

Button button_step= new Button("单步迭代");

Label label_step= new Label("     ");

Label info= new Label("LLC LAB");


在构造方法中添加他们

//设置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(support);

menu1.add(item1);

mn_mode.add(mn_mode_1); mn_mode.add(mn_mode_2);

mn_mode.setLabel("生成模式");

mn_mode_1.setLabel("单一规则"); mn_mode_2.setLabel("随机规则");


这样便大功告成了。

3、画图类MyCanvas的中的核心方法

要在画布中画线那必须要有坐标表示方法

//为保存双精度的点而新建一个类

class doublePoint {     

  double x;

  double y;

  doublePoint(double x1,double y1){

    x=x1;y=y1;

  }

}

我们既然已经将指令存储在statement中了那么以此检查字符串数组的每个元素,遇到F就画线,遇到[就将当前状态存储到栈中,遇到]则从栈中取出状态。

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);

       }

       }

4、全部源码和运行结果

package myFenxing.release;
/**
 * @author Jason 
 * @Corp LLC lab
 * @version LS grammar implementation version1; 菜单和按钮无功能
 */
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.Vector;

//为保存双精度的点而新建一个类
class doublePoint {     
  double x;
  double y;
  doublePoint(double x1,double y1){
    x=x1;y=y1;
  }
}
//画布
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;
	        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;");
		}
}
//窗口
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 support= new Menu("技术支持");
	MenuItem item1= new MenuItem("退出");
	MenuItem mn_mode_1= new MenuItem(); MenuItem mn_mode_2= new MenuItem();
	
	Choice choice= new Choice();		
	Button button_step= new Button("单步迭代");
	Label label_step= new Label("     ");
	Label info= new Label("LLC LAB");
	//LS文法需要的变量
	String statement,replacement;
    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(support);
		menu1.add(item1);
		mn_mode.add(mn_mode_1); mn_mode.add(mn_mode_2);
		mn_mode.setLabel("生成模式");
		mn_mode_1.setLabel("单一规则"); mn_mode_2.setLabel("随机规则");
	}
	//响应关闭操作
	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);
      }
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub		
	}
	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);  
	}
	/**计算LS表达式*/	//1、直接替换
    public String caluStatement1(int depth){    	
        for(;depth > 0; depth--){
        	String newStatement="";
        	for(int i=0;i< statement.length();i++){
        		if(statement.charAt(i)== 'F') newStatement += replacement;
        		else newStatement += statement.charAt(i);
        		//防止字符串数组爆了,其最大长度取决于字符串在常量池中的存储大小 
        		if(newStatement.length() >= 65534){//2^16-1=65535
        			return newStatement;
        		}	        			
        	}
        	statement = newStatement;
        }
        return statement;
    }
    //2、随机替换
    public String caluStatement2(int depth){
    	//三条规则随机选择	 
    	sRule[0][0]="F";
	    sRule[0][1]="F[+F]F[-F]F" ;
	    sRule[1][0]="F";
	    sRule[1][1]="F[+F[+F]]F[-F]";
	    sRule[2][0]="F";
	    sRule[2][1]="F+F-[-F+F-F][+F-F+F]";
        for(;depth > 0; depth--){
        	String newStatement="";
        	for(int i=0;i< statement.length();i++){
        		replacement= sRule[(int)(Math.random()*3)][1];
        		if(statement.charAt(i)== 'F') newStatement += replacement;
        		else newStatement += statement.charAt(i);
        		//防止字符串数组爆了
        		if(newStatement.length() >= 65534){//2^16-1=65535
        			return newStatement;
        		}
        	}
        	statement = newStatement;
        }
        return statement;
    }

}
/**Main method*/
public class randomLS_V1 {
	public static void main(String args[]){
		MyWindow instance= new MyWindow();
		instance.setTitle("牛逼的树");
		instance.statement= instance.caluStatement2(5);
		instance.init();
	}
}

© 著作权归作者所有

realsa

realsa

粉丝 33
博文 84
码字总数 107087
作品 0
广州
程序员
私信 提问
Google网页工具包 GWT 2.1.1 发布

Google 网页工具包——GWT 提供了一组基于Java语言的开发包,这个开发包的设计参考Java AWT包设计,类命名规则、接口设计、事件监听等都和AWT非常类似。熟悉Java AWT的开发者不需要花费多大的...

绿悠悠
2010/12/20
1K
1
java swing 组件技术(上)

第一次写自己的博客,明知道写得很水,还是努力去写了,希望踏出第一步之后,能有着更好的发展。这几天看了一些资料,总结了一下自己所学的关于java swing的知识。 一、 java swing 组件技术...

静心天涯
2013/06/14
7.4K
6
GWT 2.1 RC1 发布,Google网页工具包

Google 网页工具包——GWT 提供了一组基于Java语言的开发包,这个开发包的设计参考Java AWT包设计,类命名规则、接口设计、事件监听等都和AWT非常类似。熟悉Java AWT的开发者不需要花费多大的...

红薯
2010/10/13
801
0
Google 网页工具包的网友评论

Google 网页工具包——GWT 提供了一组基于Java语言的开发包,这个开发包的设计参考Java AWT包设计,类命名规则、接口设计、事件监听等都和AWT非常类似。熟悉Java AWT的开发者不需要花费多大的...

红薯
2009/12/11
582
2
细说Java GUI:AWT,SWT,Swing

历史 Internet上有许多围绕这一争论的故事。你可能已经听说过它们中的大多数了,其中之一有助于让你理清头绪,让我们就从这里开始,Amy Fowler是Swing阵营的一个倡导者。 回到上个世纪90年代...

javasql
2014/02/05
5.4K
3

没有更多内容

加载失败,请刷新页面

加载更多

Activity启动模式二

上篇文章Activity启动模式一主要介绍了Activity的四种启动模式,这些启动模式都是在AndroidManifest中进行配置的。除此之外,Android系统还通过Intent类提供了一些标志位,同样可以指定Activ...

ltlovezh
32分钟前
4
0
三原色还原

1、Color Filter Array — CFA 随着数码相机、手机的普及,CCD/CMOS 图像传感器近年来得到广泛的关注和应用。 图像传感器一般都采用一定的模式来采集图像数据,常用的有 BGR 模式和 CFA 模式...

天王盖地虎626
43分钟前
3
0
kubernetes pod exec接口调用

正文 一般生产环境上由于网络安全策略,大多数端口是不能为集群外部访问的。多个集群之间一般都是通过k8s的ApiServer组件提供的接口通信,如https://192.168.1.101:6443。所以在做云平台时,...

码农实战
今天
8
0
3_数组

3_数组

行者终成事
今天
8
0
经典系统设计面试题解析:如何设计TinyURL(二)

原文链接:https://www.educative.io/courses/grokking-the-system-design-interview/m2ygV4E81AR 编者注:本文以一道经典的系统设计面试题:《如何设计TinyURL》的参考答案和解析为例,帮助...

APEMESH
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部