`

Java 2D高级绘图

    博客分类:
  • Java
阅读更多
知识要点:

第一节  Java 2D的增强功能

概述、AWT图形能力的不足、Java 2D API

第二节  图形绘制的基本方法

转换Graphics2D对象、Graphics 类特性、绘图的属性和基本编程方法

第三节  曲线问题的高级应用开发

直线问题深入研究、贝塞尔(Bezier)曲线、自定义样条曲线编程、

用户数据的曲线显示、曲线用Applet显示的数据来源问题

第四节  字符串的高级处理

TextLayout类、LineMetrics类

第五节  构造几何形状

2D几何形状的设计、构造型区域几何形状、变换、缓冲的图像

第六节  三维图形处理的设计技术

透视投影、透视图形的显示、隐蔽面消除问题

第七节  同环境交互

GraphicsEnvironment类、GraphicsDevice类、GraphicsConfiguration类













































第一节  Java 2D的增强功能



一、概述:



由Sun公司与Adobe系统公司合作推出的Java 2D API,提供了一个功能强大而且非常灵活的二维图形框架。Java 2D API扩展了java.awt包中定义的Graphics类和Image类,提供了高性能的二维图形、图像和文字,同时又维持了对现有AWT应用的兼容。



二、AWT图形能力的不足:



在 AWT 的初始实现中,图形能力并不十分完善。因为开发 JDK 是打算将其作为平台中立的实现平台,所以其原始的功能被限制于“最少公共功能”上,所有被支持的操作系统上保证提供这些公共功能;

在 Java 2D 出现之前,对绘制能力、字体操作和图像控制的支持非常少。而对诸如用图案进行着色、形状操作以及图形变换之类的重要操作的支持则完全没有。

Java 2D 满足了跨平台实现中对这些功能以及其它功能的需求。



三、Java 2D API:



它是JFC (Java Fundation Classes)的一员,加强了传统AWT( Abstract Windowing Toolkit )的描绘功能。在 JDK1.2中已经支援 Java 2D 的使用。透过Java 2D API ,程序员可以轻松地描绘出任意的几何图形、运用不同的填色效果、对图形做旋转( rotate)、缩放( scale)、扭曲( shear)等。如图所示,程序员透过2D API所提供的功能,简单地利用不同类型的线或是填色效果绘出统计图,以区分出不同的资料。

它们是基于Graphics2D类的绘图功能,是对AWT中的Graphics类的进一步的扩展和增强。主要体现在:



1。对渲染质量的控制:消除锯齿以平滑绘制对象的边缘

2.裁剪、合成和透明度:它们允许使用任意形状来限定绘制操作的边界。它们还提供对图形进行分层以及控制透明度和不透明度的能力。

3.控制和填充简单及复杂的形状:这种功能提供了一个 Stroke 代理和一个 Paint 代理,前者定义用来绘制形状轮廓的笔(定义绘制的笔的宽度和样式),后者允许用纯色、渐变色和图案来填充形状。

4。图像处理和变换:Java 2D 同 Java 高级图像 API(Java Advanced Imaging API (JAI))协作,支持用大量图形格式处理复杂的图像。Java 2D 还为您提供了修改图像、形状和字体字符的变换能力。

5。特殊的填充方式,如梯度或者图案

6.高级字体处理和字符串格式化:允许象操作任何其它图形形状一样操作字体字符。除此以外,可以象文字处理程序一样,通过为 String 中的字符应用属性和样式信息来创建格式化文本。




java.awt.geom 包中的Areas类支援联集( union)、交集( intersection)、差集(subtraction )、Exclusive OR (XOR)等布尔运算。最後, AffineTransform 类别则提供图形物件做Scale(比例)、Shear(剪裁) 、Rotate(旋转)等座标上的转换。










第二节  图形绘制的基本方法



一、转换Graphics2D对象

  

绘制图形时,可以在Graphics对象或者Graphics2D对象上进行,它们都代表了需要绘图的区域,选择那个取决于是否要使用所增加的Java2D的图形功能。但要注意的是,所有的Java2D图形操作都必须在Graphics2D对象上调用。Graphics2D是Graphics的子类,同样包含在java.awt包中。

public void paintComponent(Graphics comp)

{     Graphics2D comp2D=(Graphics2D)comp;

}

或者

public void paint (Graphics comp)

{     Graphics2D comp2D=(Graphics2D)comp;

}





二、Graphics 类特性



Graphics 类支持几种确定图形环境状态的特性。以下列出了部分特性:

1)Color:当前绘制颜色,它属于 java.awt.Color 类型。所有的绘制、着色和纯文本输出都将以指定的颜色显示。

2)Font:当前字体,它属于 java.awt.Font 类型。它是将用于所有纯文本输出的字体。

3)Clip:java.awt.Shape 类型的对象,它充当用来定义几何形状的接口。该特性包含的形状定义了图形环境的区域,绘制将作用于该区域。通常情况下,这一形状与整个图形环境相同,但也并不一定如此。

4)ClipBounds:java.awt.Rectangle 对象,它表示将包围由 Clip 特性定义的 Shape 的最小矩形。它是只读特性。

5)FontMetrics:java.awt.FontMetrics 类型的只读特性。该对象含有关于图形环境中当前起作用的 Font 的信息。如同我们将看到的那样,获取此信息的这种机制已被 LineMetrics 类所取代

6)Paint Mode:该特性控制环境使用当前颜色的方式。如果调用了 setPaintMode() 方法,那么所有绘制操作都将使用当前颜色。如果调用了 setXORMode() 方法(该方法获取一个 Color 类型的参数),那么就用指定的颜色对像素做“XOR”操作。XOR 具有在重新绘制时恢复初始位模式的特性,因此它被用作橡皮擦除和动画操作。



三、绘图的属性和基本编程方法



1)颜色Color类:没有变化。

2)填充方式:



Paint(油漆桶) 接口有几个具体的实现,它们允许用纯色、渐变色或图案来填充形状。



1,纯色填充(Color类):对 java.awt.Color 类做了一些调整以实现 Paint,并且可以用于纯色填充。

2,渐变色来填充(梯度填充GradientPaint类):java.awt.GradientPaint 类允许用线性颜色渐变色来填充形状,线性颜色渐变色允许在两个指定的 Color 对象之间创建过渡。可以将渐变色设置成“周期性的”,这将导致渐变色图案重复出现。

3,图案填充(纹理TexturePaint类):提供了 java.awt.TexturePaint 类,它可以用由 BufferedImage 描述的图案填充形状

编程方法:

使用Graphics2D类中的setPaint()方法并使用Paint对象作为其参数,但由于任何可以作为填充的类如GradientPaint、TexturePaint和Color都实现了Paint接口(该接口注意定义了在Graphics2D下的颜色填充方式),因此可以将它们作为参数。如:

public void paintComponent(Graphics comp)

{     Graphics2D comp2D=(Graphics2D)comp;

GradientPaint pat=new GradientPaint(0f,0f,Color.white,100f,45f,Color.blue);

comp2D.setPaint(pat);

}



3)设置笔的形状:



Stroke 接口由 java.awt.BasicStroke 类实现。该类允许进行大量的选择以修改线的绘制细节。可以编程指定 BasicStroke 宽度,也可以指定对名为柱头和交点的路径上端点和交点的“装饰”。现在也可以绘制点划线了,只须设置 BasicStroke 的破折号属性即可。

在Graphics类中线条是一个点宽,而在Graphics2D中可以通过BasicStoke类中的setStroke()方法来设置。其构造函数是BasicStroke(float width, int cap, int join)

其中width指示线宽(缺省时为1.0)

cap指示线的末端(包头,在BasicStroke类中定义出三个static 类型的常量如CAP_BUTT没有包头( )、CAP_ROUND圆包头( )、CAP_SQUARE方包头( )的样式



join指示线段之间的拐角(在BasicStroke类中定义出三个static 类型的常量如JOIN_BEVEL( )、JOIN_MITER( )、   JOIN_ROUND( )样式。



4)编程方法:



public void paintComponent(Graphics comp)

{     Graphics2D comp2D=(Graphics2D)comp;



BasicStroke pen

=new BasicStroke(2.0f, BasicStroke .CAP_BUTT, BasicStroke .JOIN_ROUND);

comp2D.setStroke (pen);

}



代码示例:



       float thick = 0.5f;         //设置画刷的粗细为 0.5

BufferedImage bi = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB);

Graphics2D g = (Graphics2D)bi.getGraphics();

Stroke stroke = g.getStroke();             //得到当前的画刷

g.setStroke(new BasicStroke(thick, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));

g.draw(new Line2D.Float(x1, y1, x2, y2)); 画线

g.setStroke( stroke ); //将画刷复原





5)创建要绘制的形状对象

  

在Java2D中进行绘图时,不是采用对应的方法来实现,而是为要实现某中形状创建出相应的形状对象。这可以通过使用java.awt.geom包中的类来定义所要创建的形状。如线条Line2D.Float类、距形Rectangle2D.Float或者Rectangle2D.Double类、椭圆Ellipes2D.Float、圆弧Arc2D.Float类等。



6)绘制对象:



1,可以使用Graphics2D类中的方法draw()用于绘制轮廓,而fill()方法用于填充。它们都以前面所创建的图形对象作为参数。

2,Java2D中的字符串的绘制仍然采用drawString()方法,但有drawString(String s, float x, float y)和drawString(String str, int x, int y)。

3,绘制轮廓:draw(Shape s)其中的Shape接口在Graphics2D中被定义

新的 Java 2D Shape 类都有“2D”后缀。这些新的形状使用浮点值(而不是整数)来描述其几何形状。

Polygon类(int[] xpoints, int[] ypoints, int npoints)

RectangularShape(抽象类,其子类有Arc2D, Ellipse2D, Rectangle2D, RoundRectangle2D), Rectangle(距形)

QuadCurve2D(二次贝塞尔样条曲线,贝塞尔曲线由两个端点以及一个或两个控制点指定。贝塞尔曲线创建了适合于大多数表示的曲线。)

CubicCurve2D(三次贝塞尔样条曲线)

Area(区域)

GeneralPath(由直线、二次样条曲线、三次样条曲线所构成)

Line2D



8)基本步骤



绘图的第一个步骤是产生 Graphics2D 对象。 然后设定所要的状态属性。例如你想要对一物件做渐层式的填色,可以设定属性 Paint为 GradientPaint。最後再调用Graphics2D所提供的方法fill或是draw,完成整个绘图的程序。


9)程序实例



例一:

这是一个最简单的例子,也可以认为是绘图的一个最简单的框架。



import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.awt.geom.*;

public class Map extends JFrame

{   public Map()

       {  super("Map");

         setSize(350,350);

         MapPane map=new MapPane();

         getContentPane().add(map);

       }

       public static void main(String [] arg)

       {  Map frame=new Map();

          frame.show();

       }

}

class MapPane extends JPanel

{   public void paintComponent(Graphics comp)

    {     Graphics2D comp2D=(Graphics2D)comp;

       comp2D.drawString("sbcd",200,200);

              Line2D.Float line=new Line2D.Float(1.0f,2.0f,200.0f,200.0f);

       comp2D.draw(line);

    }

}







例二:

下面是在Graphics2D模式下的基本绘图框架。我们可以看到,利用:

         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

                          RenderingHints.VALUE_ANTIALIAS_ON);

通过该方法的设置,使图形去除锯齿状,可以得到多么细腻的图形。



样例:



import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;



public class DrawDemo extends JFrame {



  public DrawDemo(){

    //设置窗口的大小、标题

    this.setSize(new Dimension(600, 400));

   

    //创建绘制各种形状的容器

    ShapesPanel shapesPanel = new ShapesPanel();

    //将该容器加入窗口

    getContentPane().add(shapesPanel, BorderLayout.CENTER);

  }



  public static void main(String[] args) {

    DrawDemo frame = new DrawDemo();

    frame.setVisible(true);

    //当窗口关闭时清空内存

    frame.addWindowListener(new WindowAdapter() {

        public void windowClosing(WindowEvent e) {

            System.exit(0);

        }

    });

  }

}



//创建各种容器的类

class ShapesPanel extends JPanel {

    final int maxCharHeight = 15;

    final Color bg = Color.white; //声明背景颜色为灰色

    final Color fg = Color.blue;      //声明前景颜色为蓝色



    public ShapesPanel() {

        setBackground(bg);            //设置背景颜色

        setForeground(fg);            //设置前景颜色

        //创建组合边框

        setBorder(BorderFactory.createCompoundBorder(

                BorderFactory.createRaisedBevelBorder(),

                BorderFactory.createLoweredBevelBorder()));

    }





    public void paintComponent(Graphics g1) {

        super.paintComponent(g1);      //清空背景颜色





         float thick = 0.5f;               //设置画刷的粗细为 0.5

         Graphics2D g = (Graphics2D)g1;

         Stroke stroke = g.getStroke();            //得到当前的画刷

         g.setStroke(new BasicStroke(thick, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));

        

         //通过该方法使图形去除锯齿状

         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

                          RenderingHints.VALUE_ANTIALIAS_ON);

       

        

         String txt= "我的文章";

        

         int style=2;//0普通1粗体2斜体3粗斜

         g.setFont(new Font("宋体", 2, 15)); //15为字大小

         //设置笔刷为黑色

         g.setPaint(Color.black);

        

         g.drawString(txt,200,150);

        

         g.setPaint(Color.red);

         g.draw(new Line2D.Float(0,0,200,150)); //画线

        

         g.setPaint(Color.blue);

        

         g.draw(new Rectangle2D.Float(200,150,100,100));

        

         g.setStroke(stroke); //将画刷复原

        

    }

}







    例三:图形灵活的显示

   

在上面的例子中,是使用一个继承于JPanel的类,覆盖它的void paintComponent(Graphics g1)事件方法,实现绘图的,这样虽然方便,但显得灵活性不高。

实际上,通过JPanel对象直接赋值给Graphics2D对象,往往可以使程序具有很大的灵活性。程序可以这样来写。



JPanel contentPane= (JPanel) this.getContentPane();

public Graphics2D comp2D=(Graphics2D)contentPane .getGraphics();



样例:



package myDrawDemo;



import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.awt.geom.*;



public class DrawDemo1 extends JFrame

{

  public JPanel contentPane; //绘图窗口

  public Graphics2D comp2D;    //绘图对象

  JPanel jPanel1 = new JPanel();//控件容器

  JButton jButton1 = new JButton();

  JButton jButton2 = new JButton();





  //构造函数

  public DrawDemo1() {

    enableEvents(AWTEvent.WINDOW_EVENT_MASK);

    try {

      jbInit();

    }

    catch(Exception e) {

      e.printStackTrace();

    }

  }



  //控件的初始化



  private void jbInit() throws Exception  {

    contentPane = (JPanel) this.getContentPane();

    contentPane.setLayout(new BorderLayout());

    this.setSize(new Dimension(400, 300));

    this.setTitle("Frame Title");

    //contentPane.setSize(400,240);

    jPanel1.setLayout(null);

    jButton1.setBounds(new Rectangle(30, 235, 100, 31));

    jButton1.setText("画线保留");



    jButton1.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton1_actionPerformed(e);

      }

    });



    jButton2.setBounds(new Rectangle(150, 235, 100, 30));

    jButton2.setText("画线删除");

  

    jButton2.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton2_actionPerformed(e);

      }

    });



     contentPane.add(jPanel1, BorderLayout.CENTER);

    jPanel1.add(jButton1, null);

    jPanel1.add(jButton2, null);

  }



   public static void main(String[] args) {

   

    DrawDemo1 frame=new DrawDemo1();

    frame.show();

    frame.comp2D=(Graphics2D)frame.contentPane .getGraphics();

    frame.comp2D.setBackground(Color.white);

    frame.comp2D.clearRect(0,0,401,221);

}



  //Overridden so we can exit when window is closed

  protected void processWindowEvent(WindowEvent e) {

    super.processWindowEvent(e);

    if (e.getID() == WindowEvent.WINDOW_CLOSING) {

      System.exit(0);

    }

  }



  void jButton1_actionPerformed(ActionEvent e){



       comp2D.setPaint(Color.red);

       Line2D.Float line=new Line2D.Float(1.0f,2.0f,200.0f,220.0f);

       comp2D.draw(line);



  }



  void jButton2_actionPerformed(ActionEvent e) {

     

    comp2D.clearRect(0,0,401,221);

    comp2D.setPaint(Color.blue);

    Line2D.Float line=new Line2D.Float(1.0f,100.0f,300.0f,220.0f);

    comp2D.draw(line);

  }

}







例四:剪裁



图形处理问题中,剪裁由的时候是非常难处理的,所谓剪裁是指超过绘图取得内容不显示,看起来这是个简单问题,但由于所有的线条必须计算与边界的交点,而且边界有四个方向,这就使问题变得很复杂。java 2D很好的解决了这个问题,请看下面的例子。



package myDrawDemo;



import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.awt.geom.*;



public class DrawDemo2 extends JFrame

{

  public JPanel contentPane; //绘图窗口

  public Graphics2D comp2D;    //绘图对象

  JPanel jPanel1 = new JPanel();//控件容器

  JButton jButton1 = new JButton();

  JButton jButton2 = new JButton();





  //构造函数

  public DrawDemo2() {

    enableEvents(AWTEvent.WINDOW_EVENT_MASK);

    try {

      jbInit();

    }

    catch(Exception e) {

      e.printStackTrace();

    }

  }



  //控件初始化



    private void jbInit() throws Exception  {

    contentPane = (JPanel) this.getContentPane();

    contentPane.setLayout(new BorderLayout());

    this.setSize(new Dimension(400, 300));

    this.setTitle("Frame Title");

    //contentPane.setSize(400,240);

    jPanel1.setLayout(null);

    jButton1.setBounds(new Rectangle(30, 235, 100, 31));

    jButton1.setText("画线保留");



    jButton1.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton1_actionPerformed(e);

      }

    });



    jButton2.setBounds(new Rectangle(150, 235, 100, 30));

    jButton2.setText("画线删除");

  

    jButton2.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton2_actionPerformed(e);

      }

    });

  

     contentPane.add(jPanel1, BorderLayout.CENTER);

    jPanel1.add(jButton1, null);

    jPanel1.add(jButton2, null);



  }



   public static void main(String[] args) {

   

    DrawDemo2 frame=new DrawDemo2();

    frame.show();

    frame.comp2D=(Graphics2D)frame.contentPane .getGraphics();

    frame.comp2D.setBackground(Color.white);

    frame.comp2D.clearRect(0,0,401,221);

   }



  //Overridden so we can exit when window is closed

  protected void processWindowEvent(WindowEvent e) {

    super.processWindowEvent(e);

    if (e.getID() == WindowEvent.WINDOW_CLOSING) {

      System.exit(0);

    }

  }



  void jButton1_actionPerformed(ActionEvent e){



       comp2D.setPaint(Color.red);

       Line2D.Float line=new Line2D.Float(1.0f,2.0f,200.0f,220.0f);





        comp2D.draw(line);

  }



  void jButton2_actionPerformed(ActionEvent e) {

     

    comp2D.clearRect(0,0,401,221);

    //剪裁

    comp2D.setClip(50,50,300,150);

    comp2D.setPaint(Color.blue);

    Line2D.Float line=new Line2D.Float(1.0f,100.0f,300.0f,220.0f);

    comp2D.draw(line);

  }

}



 





第三节  曲线问题的高级应用开发



在jdk尚未支援 2D图形之前,只可以画出直的、相同粗细的线条。现在可以通过2D API绘出不同粗细的线条及圆滑的曲线。在java.awt.geom包中提供了Line2D、 QuadCurve2D(二次贝塞尔曲线)及 CubicCurve2D(三次贝塞尔曲线)等相关的类,让程序员能够轻松地绘出想要的线条。

其实绘图的核心是画线,下面通过一些实例对一些问题进行深入的讨论。



    一、直线问题深入研究



样例:

我们通过一个例子,深入的研究一下绘制直线和折线需要掌握哪些内容。



package myDrawDemo;



import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.awt.geom.*;



public class DrawDemo1 extends JFrame

{

  public JPanel contentPane; //绘图窗口

  public Graphics2D comp2D;    //绘图对象

  JPanel jPanel1 = new JPanel();//控件容器

  JButton jButton1 = new JButton();

  JButton jButton2 = new JButton();

  JButton jButton3 = new JButton();



  //构造函数

  public DrawDemo1() {

    enableEvents(AWTEvent.WINDOW_EVENT_MASK);

    try {

      jbInit();

    }

    catch(Exception e) {

      e.printStackTrace();

    }

  }



  //控件初始化

  private void jbInit() throws Exception  {

    contentPane = (JPanel) this.getContentPane();

    contentPane.setLayout(new BorderLayout());

    this.setSize(new Dimension(400, 300));

    this.setTitle("Frame Title");

    //contentPane.setSize(400,240);

    jPanel1.setLayout(null);

    jButton1.setBounds(new Rectangle(30, 235, 100, 31));

    jButton1.setText("园头");



    jButton1.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton1_actionPerformed(e);

      }

    });



    jButton2.setBounds(new Rectangle(150, 235, 100, 30));

    jButton2.setText("方头");

  

    jButton2.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton2_actionPerformed(e);

      }

    });



   jButton3.setBounds(new Rectangle(270, 235, 100, 30));

    jButton3.setText("封闭");

  

    jButton3.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton3_actionPerformed(e);

      }

    });



     contentPane.add(jPanel1, BorderLayout.CENTER);

    jPanel1.add(jButton1, null);

    jPanel1.add(jButton2, null);

    jPanel1.add(jButton3, null);

  }



   public static void main(String[] args) {

   

    DrawDemo1 frame=new DrawDemo1();

    frame.show();

    frame.comp2D=(Graphics2D)frame.contentPane .getGraphics();

    frame.comp2D.setBackground(Color.white);

    frame.comp2D.clearRect(0,0,401,221);

   }



  //Overridden so we can exit when window is closed

  protected void processWindowEvent(WindowEvent e) {

    super.processWindowEvent(e);

    if (e.getID() == WindowEvent.WINDOW_CLOSING) {

      System.exit(0);

    }

  }



  int Xs1[]={10,60,120,200,260,340};

  int Ys1[]={10,200,120,180,60,130};



  void jButton1_actionPerformed(ActionEvent e){



      comp2D.clearRect(0,0,401,221);

       //笔宽度     

      float thick = 10f;

      //设置笔刷

      //园头园连接

comp2D.setStroke(new BasicStroke(thick,

BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

      comp2D.setPaint(Color.red);

     

       //通过该方法使图形去除锯齿状

      comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

                          RenderingHints.VALUE_ANTIALIAS_ON);

          comp2D.drawPolyline(Xs1,Ys1,Xs1.length);  

  }



  void jButton2_actionPerformed(ActionEvent e) {

     

      comp2D.clearRect(0,0,401,221);

       //笔宽度     

      float thick = 10f;

     

      //设置笔刷

      //方头方连接

comp2D.setStroke(new BasicStroke(thick,

BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE));

      comp2D.setPaint(Color.blue);

     

       //通过该方法使图形去除锯齿状

      //comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

        //                  RenderingHints.VALUE_ANTIALIAS_ON);

       comp2D.drawPolyline(Xs1,Ys1,Xs1.length);  

  }



void jButton3_actionPerformed(ActionEvent e) {

     

      comp2D.clearRect(0,0,401,221);

       //笔宽度     

      float thick = 1f;

     

      //设置笔刷

      //方头方连接

comp2D.setStroke(new BasicStroke(thick,

BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE));

     

      comp2D.setPaint(Color.blue);

     

       //通过该方法使图形去除锯齿状

      //comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

        //                  RenderingHints.VALUE_ANTIALIAS_ON);

   

      //画封闭线

      comp2D.drawPolygon(Xs1,Ys1,Xs1.length);  

  }

}







二、贝塞尔(Bezier)曲线



java 2D提供的QuadCurve2D(二次贝塞尔曲线)及 CubicCurve2D(三次贝塞尔曲线)等相关的类,可以很容易的画出贝赛尔曲线。

QuadCurve2D为三个数据,中间一个为控制点。

CubicCurve2D为四个数据,中间两个为控制点。



样例:



package myDrawDemo;



import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.awt.geom.*;



public class DrawDemo1 extends JFrame

{

  public JPanel contentPane; //绘图窗口

  public Graphics2D comp2D;    //绘图对象

  JPanel jPanel1 = new JPanel();//控件容器

  JButton jButton1 = new JButton();

  JButton jButton2 = new JButton();



  //构造函数

  public DrawDemo1() {

    enableEvents(AWTEvent.WINDOW_EVENT_MASK);

    try {

      jbInit();

    }

    catch(Exception e) {

      e.printStackTrace();

    }

  }



  //控件初始化

  private void jbInit() throws Exception  {

    contentPane = (JPanel) this.getContentPane();

    contentPane.setLayout(new BorderLayout());

    this.setSize(new Dimension(400, 300));

    this.setTitle("Frame Title");

    //contentPane.setSize(400,240);

    jPanel1.setLayout(null);

    jButton1.setBounds(new Rectangle(30, 235, 150, 31));

    jButton1.setText("二阶贝塞尔");



    jButton1.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton1_actionPerformed(e);

      }

    });



    jButton2.setBounds(new Rectangle(200, 235, 150, 30));

    jButton2.setText("三阶贝塞尔");

  

    jButton2.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton2_actionPerformed(e);

      }

    });



     contentPane.add(jPanel1, BorderLayout.CENTER);

    jPanel1.add(jButton1, null);

    jPanel1.add(jButton2, null);

  

  }



   public static void main(String[] args) {

   

    DrawDemo1 frame=new DrawDemo1();

    frame.show();

    frame.comp2D=(Graphics2D)frame.contentPane .getGraphics();

    frame.comp2D.setBackground(Color.white);

    frame.comp2D.clearRect(0,0,401,221);

   }



  //Overridden so we can exit when window is closed

  protected void processWindowEvent(WindowEvent e) {

    super.processWindowEvent(e);

    if (e.getID() == WindowEvent.WINDOW_CLOSING) {

      System.exit(0);

    }

  }



 

  void jButton1_actionPerformed(ActionEvent e){



     double[] x1={50,180,300};

     double[] y1={100,190,100};



      comp2D.clearRect(0,0,401,221);

       //笔宽度     

      float thick = 1f;

     

      comp2D.setPaint(Color.red);

     

      QuadCurve2D.Double qc=new QuadCurve2D.Double();

      qc.setCurve(x1[0],y1[0],x1[1],y1[1],x1[2],y1[2]);

      

      comp2D.draw(qc);

     

      comp2D.drawLine((int)x1[1]-5,(int)y1[1],(int)x1[1]+5,(int)y1[1]);

      comp2D.drawLine((int)x1[1],(int)y1[1]-5,(int)x1[1],(int)y1[1]+5);

     

      comp2D.setPaint(Color.blue);

     

      x1[1]=180;

      y1[1]=30;

     

      qc.setCurve(x1[0],y1[0],x1[1],y1[1],x1[2],y1[2]);

      

      comp2D.draw(qc);

     

      comp2D.drawLine((int)x1[1]-5,(int)y1[1],(int)x1[1]+5,(int)y1[1]);

      comp2D.drawLine((int)x1[1],(int)y1[1]-5,(int)x1[1],(int)y1[1]+5);

     

  }



  void jButton2_actionPerformed(ActionEvent e) {

     

     double[] x1={50,80,200,300};

     double[] y1={100,70,190,100};

     

      comp2D.clearRect(0,0,401,221);

       //笔宽度     

      float thick = 1f;

     

      comp2D.setPaint(Color.red);

     

      CubicCurve2D.Double qc=new CubicCurve2D.Double();

      qc.setCurve(x1[0],y1[0],x1[1],y1[1],x1[2],y1[2],x1[3],y1[3]);

      

      comp2D.draw(qc);

     

      comp2D.drawLine((int)x1[1]-5,(int)y1[1],(int)x1[1]+5,(int)y1[1]);

      comp2D.drawLine((int)x1[1],(int)y1[1]-5,(int)x1[1],(int)y1[1]+5);

     

      comp2D.drawLine((int)x1[2]-5,(int)y1[2],(int)x1[2]+5,(int)y1[2]);

      comp2D.drawLine((int)x1[2],(int)y1[2]-5,(int)x1[2],(int)y1[2]+5);

     

      float dash1[] = {10.0f};

     

      //画虚线

      BasicStroke dashed = new BasicStroke(1.0f,

                                         BasicStroke.CAP_BUTT,

                                         BasicStroke.JOIN_MITER,

                                         10.0f, dash1, 0.0f);



      comp2D.setStroke(dashed);

      comp2D.setPaint(Color.darkGray);

      comp2D.drawLine((int)x1[1],(int)y1[1],(int)x1[2],(int)y1[2]);

    

     //画实线

      BasicStroke stroke = new BasicStroke(1.0f);

      comp2D.setStroke(stroke);

      comp2D.setPaint(Color.blue);

     

      x1[1]=180;

      y1[1]=70;

      x1[2]=80;

      y1[2]=190;

     

      qc.setCurve(x1[0],y1[0],x1[1],y1[1],x1[2],y1[2],x1[3],y1[3]);

      

      comp2D.draw(qc);

     

      comp2D.drawLine((int)x1[1]-5,(int)y1[1],(int)x1[1]+5,(int)y1[1]);

      comp2D.drawLine((int)x1[1],(int)y1[1]-5,(int)x1[1],(int)y1[1]+5);

     

      comp2D.drawLine((int)x1[2]-5,(int)y1[2],(int)x1[2]+5,(int)y1[2]);

      comp2D.drawLine((int)x1[2],(int)y1[2]-5,(int)x1[2],(int)y1[2]+5);

     

      comp2D.setStroke(dashed);

      comp2D.setPaint(Color.darkGray);

      comp2D.drawLine((int)x1[1],(int)y1[1],(int)x1[2],(int)y1[2]);

      comp2D.setStroke(stroke);

  }

}













   

    三、自定义样条曲线编程

   

当我们需要平滑多个数据样本点的时候,贝塞尔曲线就不能满足要求了,为此,可以采用最早由美国“波音”飞机制造公司提出来的样条曲线来完成,这种曲线所以称之为样条,是因为它模拟了造船业中的放样原理。

样条曲线的数学原理请参考计算机图形学,这里给出的是由java编写的三次样条曲线的例子。曲线平滑的原则是,必须通过所有的样本点,另外,不论有多少样本点,曲线的阶次最大为三次,所以是稳定的。

这里我们可以看出来,程序设计的生命是什么呢?数学!这是程序设计着的生命所在。语言只是一种规范或者是一个工具,要真正写出好的程序,没有深厚的数学功底,是万万不可能的。



样例:



package myDrawDemo;



import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.awt.geom.*;



public class DrawCurve extends JFrame

{

  public JPanel contentPane; //绘图窗口



  JPanel jPanel1 = new JPanel();//控件容器

  JButton jButton1 = new JButton();

  JButton jButton2 = new JButton();

  JButton jButton3 = new JButton();



 

  GraphicsCurve gracu;





  //构造函数

  public DrawCurve() {

    enableEvents(AWTEvent.WINDOW_EVENT_MASK);

    try {

      jbInit();

    }

    catch(Exception e) {

      e.printStackTrace();

    }

  }



    //控件初始化



    private void jbInit() throws Exception  {

    contentPane = (JPanel) this.getContentPane();

    contentPane.setLayout(new BorderLayout());

    this.setSize(new Dimension(500,400));

    this.setTitle("Frame Title");

    //contentPane.setSize(400,240);

    jPanel1.setLayout(null);

    jButton1.setBounds(new Rectangle(30, 310, 100, 31));

    jButton1.setText("直线");





    jButton1.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton1_actionPerformed(e);

      }

    });





    jButton2.setBounds(new Rectangle(150, 310, 100, 30));

    jButton2.setText("样条曲线");

  

    jButton2.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton2_actionPerformed(e);

      }

    });

   

    jButton3.setBounds(new Rectangle(270, 310, 100, 30));

    jButton3.setText("粗线条");

  

    jButton3.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton3_actionPerformed(e);

      }

    });

  

     contentPane.add(jPanel1, BorderLayout.CENTER);

    jPanel1.add(jButton1, null);

    jPanel1.add(jButton2, null);

    jPanel1.add(jButton3, null);

   

    gracu=new GraphicsCurve();

  }



   public static void main(String[] args) {

   

    DrawCurve frame=new DrawCurve();

    frame.show();

    frame.gracu.myGraphics=(Graphics2D)frame.contentPane .getGraphics();

    frame.gracu.myGraphics.setBackground(Color.white);

    frame.gracu.myGraphics.clearRect(0,0,500,300);

   }



  //Overridden so we can exit when window is closed

  protected void processWindowEvent(WindowEvent e) {

    super.processWindowEvent(e);

    if (e.getID() == WindowEvent.WINDOW_CLOSING) {

      System.exit(0);

    }

  }

    int Xs1[]={10,60,120,200,260,340};

    int Ys1[]={10,200,120,180,60,130};



  //画折线

  void jButton1_actionPerformed(ActionEvent e){

         

      gracu.myGraphics.setPaint(Color.blue);

      gracu.myGraphics.drawPolyline(Xs1,Ys1,Xs1.length);    

  }

 

  //画样条 

  void jButton2_actionPerformed(ActionEvent e) {

     

      gracu.myGraphics.setPaint(Color.red);

      gracu.DrawCurves(Xs1,Ys1);

  }



  //画粗线

  void jButton3_actionPerformed(ActionEvent e) {

      //笔宽度     

      float thick = 10f;

      //设置笔刷

      //方头园连接

      //gracu.myGraphics.setStroke(new BasicStroke(thick, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));

      //园头园连接

      gracu.myGraphics.setStroke(new BasicStroke(thick, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

      gracu.myGraphics.setPaint(Color.blue);

       //通过该方法使图形去除锯齿状

      gracu.myGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

                          RenderingHints.VALUE_ANTIALIAS_ON);

      gracu.myGraphics.drawPolyline(Xs1,Ys1,Xs1.length);    

         }

  }



class GraphicsCurve

{

     //绘图对象

       public Graphics2D myGraphics;

      

       public GraphicsCurve()

       {       

       

       }

      

       public GraphicsCurve(Graphics2D graphics)

       {       

         this.myGraphics=graphics;

       }

       //参数表

       //x数组,y数组,笔刷      

       public void DrawCurves(int[] xa,int[] ya)

       {

             

              int[] x, y;

              double[] a, b, c;

              double[] px, py, qx, qy, tt;

              double[] dx, dy;

              int px1,py1,px2,py2;

           x=xa;

              y=ya;

              px1=x[0];

              py1=y[0];

              int n=x.length;

                     a=new double[n];

                     b=new double[n];

                     c=new double[n];

                     px=new double[n];

                     py=new double[n];

                     qx=new double[n];

                     qy=new double[n];

                     tt=new double[n];

                     dx=new double[n];

                     dy=new double[n];

                     int i, t, es;

                     double bx3, bx4, by3, by4, cx, cy;

                     bx4 = 0;

                     by3 = 0;

                     es = 3;

                     px[0] = 1;

                     py[0] = 1;

                     px[n-1] = 1;

                     py[n-1] = 1;

                     if (n>1)

                     {

                            for (i = 1;i<n;i++)

                                   tt[i] = Math.sqrt((x[i] - x[i - 1]) * (x[i] - x[i - 1]) + (y[i] - y[i - 1]) * (y[i] - y[i - 1]));

                            switch(n)      

                            {   

                                   case 2:

                                          break;

                                   case 3:

                                          for (i = 1;i<n - 1;i++)

                                          {

                                                 a[i] = 2 * (tt[i] + tt[i + 1]);

                                                 b[i] = tt[i + 1];

                                                 c[i] = tt[i];

                                                 dx[i] = 3 * (tt[i] * (x[i + 1] - x[i]) / tt[i + 1] + tt[i + 1] * (x[i] - x[i - 1]) / tt[i]);

                                                 dy[i] = 3 * (tt[i] * (y[i + 1] - y[i]) / tt[i + 1] + tt[i + 1] * (y[i] - y[i - 1]) / tt[i]);

                                          }



                                          dx[1] = dx[1] - tt[2] * px[0];

                                          dx[n - 2] = dx[n - 2] - tt[n - 2] * px[n-1];

                                          dy[1] = dy[1] - tt[2] * py[0];

                                          dy[n - 2] = dy[n - 2] - tt[n - 2] * py[n-1];



                                          //注意,这是n=3的情况专有计算

                                          px[1] = dx[1] / a[1];

                                          py[1] = dy[1] / a[1];

                                         

                                          break;

                                   default:

                                          for (i = 1;i<n - 1;i++)

                                          {

                                                 a[i] = 2 * (tt[i] + tt[i + 1]);

                                                 b[i] = tt[i + 1];

                                                 c[i] = tt[i];

                                                 dx[i] = 3 * (tt[i] * (x[i + 1] - x[i]) / tt[i + 1] + tt[i + 1] * (x[i] - x[i - 1]) / tt[i]);

                                                 dy[i] = 3 * (tt[i] * (y[i + 1] - y[i]) / tt[i + 1] + tt[i + 1] * (y[i] - y[i - 1]) / tt[i]);

                                          }

                                          dx[1] = dx[1] - tt[2] * px[0];

                                          dx[n - 2] = dx[n - 2] - tt[n - 2] * px[n-1];

                                          dy[1] = dy[1] - tt[2] * py[0];

                                          dy[n - 2] = dy[n - 2] - tt[n - 2] * py[n-1];

                                          c[1] = c[1]/ a[1];

                                          for (i = 2 ;i< n - 1;i++)

                                          {

                                                 a[i] = a[i] - b[i] * c[i - 1];

                                                 c[i] = c[i] / a[i];

                                          }

                                          qx[1] = dx[1] / a[1];

                                          qy[1] = dy[1] / a[1];

                                          for (i = 2 ;i< n - 1;i++)

                                          {

                                                 qx[i] = (dx[i] - b[i] * qx[i - 1]) / a[i];

                                                 qy[i] = (dy[i] - b[i] * qy[i - 1]) / a[i];

                                          }

                                          px[n - 2] = qx[n - 2];

                                          py[n - 2] = qy[n - 2];

                                          for (i = n - 3;i>=1;i--)

                                          {

                                                 px[i] = qx[i] - c[i] * px[i + 1];

                                                 py[i] = qy[i] - c[i] * py[i + 1];

                                          }

                                          break;

                            }

                            for (i = 0 ;i< n - 1;i++)

                            {

                                   bx3 = (3 * (x[i + 1] - x[i]) / tt[i + 1] - 2 * px[i] - px[i + 1]) / tt[i + 1];

                                   bx4 = ((2 * (x[i] - x[i + 1]) / tt[i + 1] + px[i] + px[i + 1]) / tt[i + 1]) / tt[i + 1];

                                   by3 = (3 * (y[i + 1] - y[i]) / tt[i + 1] - 2 * py[i] - py[i + 1]) / tt[i + 1];

                                   by4 = ((2 * (y[i] - y[i + 1]) / tt[i + 1] + py[i] + py[i + 1]) / tt[i + 1]) / tt[i + 1];

                                   t = 0;

                                   while (t < tt[i + 1])

                                   {

                                          t = t + es;

                                          cx = x[i] + (px[i] + (bx3 + bx4 * t) * t) * t;

                                          cy = y[i] + (py[i] + (by3 + by4 * t) * t) * t;

                                          px2 = (int)cx;

                                          py2 = (int)cy;

                                          myGraphics.drawLine(px1,py1,px2,py2);

                                          px1 = px2;

                                          py1 = py2;

                                   }

                            }

                     }                         

       }

}











    四、用户数据的曲线显示



当需要用曲线表达数据的时候,我们虽然可以使用由厂家提供的“图表”组件,但更多的还是需要自己编写的,请仔细研究下面的程序,当对图表设计有更深入的理解。

下面的例子,我们构造一个专门处理用户数据的类,在这个类里,实现了用户坐标和屏幕坐标的转换,同时给出了一个自动绘制坐标的方法。我们也直接使用了上面我们讨论过的样条曲线的类实现数据平滑。例子中的数据可以来自于数据库或其它任何地方,仔细的研究这个例子,可以看出只要我们开动脑筋,把java强大的功能和我们对问题的理解结合在一起,就可以写出多么灵活多变的程序来呀!



样例:



package myDrawDemo;



import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.event.*;

import java.awt.geom.*;



public class DataDrawDemo extends JFrame

{

  public JPanel contentPane; //控件容器

 

  JPanel jPanel1 = new JPanel();//绘图控件

 

  JButton jButton1 = new JButton();

  JButton jButton2 = new JButton();

  JButton jButton3 = new JButton();

  JButton jButton4 = new JButton();

  JButton jButton5 = new JButton();



  JButton jButton6 = new JButton();

  JButton jButton7 = new JButton();

  JButton jButton8 = new JButton();

  JButton jButton9 = new JButton();



  JButton jButton10 = new JButton();

 

  JTextField jText1=new JTextField();



  JTextField jText2=new JTextField();



  boolean kcu=true;

 

  //用户坐标转换对象

  myGraphicsData mp=new myGraphicsData();

 

  //曲线转换对象

  GraphicsCurve gracu=new GraphicsCurve();

 

 

    //窗口范围

    double wx1,wx2,wy1,wy2;



  //构造函数

  public DataDrawDemo() {

    enableEvents(AWTEvent.WINDOW_EVENT_MASK);

    try {

      jbInit();

    }

    catch(Exception e) {

      e.printStackTrace();

    }

  }



    //初始化代码

    private void jbInit() throws Exception  {



   

    contentPane = (JPanel) this.getContentPane();

    contentPane.setLayout(null);

  

    this.setSize(new Dimension(650, 500));

    this.setTitle("Frame Title");

    //contentPane.setSize(400,240);

    //jPanel1.setLayout(null);



    jPanel1.setBounds(0,90,650,420);

    jButton1.setBounds(new Rectangle(30, 20, 80, 25));

    jButton1.setText("开始");



    jButton1.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton1_actionPerformed(e);

      }

    });



    jButton2.setBounds(new Rectangle(120, 20, 80, 25));

    jButton2.setText("左移");

  

    jButton2.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton2_actionPerformed(e);

      }

    });



    jButton3.setBounds(new Rectangle(210, 20, 80, 25));

    jButton3.setText("右移");

  

    jButton3.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton3_actionPerformed(e);

      }

    });



   jButton4.setBounds(new Rectangle(300, 20, 80, 25));

    jButton4.setText("上移");

  

    jButton4.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton4_actionPerformed(e);

      }

    });



  jButton5.setBounds(new Rectangle(390, 20, 80, 25));

    jButton5.setText("下移");

  

    jButton5.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton5_actionPerformed(e);

      }

    });

   

    jButton6.setBounds(new Rectangle(120, 50, 80, 25));

    jButton6.setText("X扩");

  

    jButton6.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton6_actionPerformed(e);

      }

    });



    jButton7.setBounds(new Rectangle(210, 50, 80, 25));

    jButton7.setText("X缩");

  

    jButton7.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton7_actionPerformed(e);

      }

    });



   jButton8.setBounds(new Rectangle(300, 50, 80, 25));

    jButton8.setText("Y扩");

  

    jButton8.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton8_actionPerformed(e);

      }

    });



    jButton9.setBounds(new Rectangle(390, 50, 80, 25));

    jButton9.setText("Y缩");

  

    jButton9.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton9_actionPerformed(e);

      }

    });

   

    //样条控制   

    jButton10.setBounds(new Rectangle(30, 50, 80, 25));

    jButton10.setText("样条");



    jButton10.addActionListener(new java.awt.event.ActionListener() {

      public void actionPerformed(ActionEvent e) {

        jButton10_actionPerformed(e);

      }

    });



    jText1.setBounds(new Rectangle(490, 20, 120, 20));

    jText1.setText("");

 

    jText2.setBounds(new Rectangle(490, 50, 120, 20));

    jText2.setText("");

 

 

    //鼠标按下侦听器

    jPanel1.addMouseListener(new java.awt.event.MouseAdapter(){

       public void mousePressed(MouseEvent e) {

       JPanel_mousePressed(e);

  

     }

       

   });

  

    //鼠标拖动侦听器

    jPanel1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter(){

       public void mouseDragged(MouseEvent e){

       JPanel_mouseDragged(e);

     }

    });

   

   

    //鼠标释放侦听器

    jPanel1.addMouseListener(new java.awt.event.MouseAdapter(){

       public void mouseReleased(MouseEvent e) {

       JPanel_mouseReleased(e);

     }

   });

  

    contentPane.add(jPanel1, BorderLayout.CENTER);

   

    contentPane.add(jButton1, null);

    contentPane.add(jButton2, null);

    contentPane.add(jButton3, null);

    contentPane.add(jButton4, null);

    contentPane.add(jButton5, null);

    contentPane.add(jButton6, null);

    contentPane.add(jButton7, null);

    contentPane.add(jButton8, null);

    contentPane.add(jButton9, null);

    contentPane.add(jButton10, null);

    contentPane.add(jText1, null);

    contentPane.add(jText2, null);

  }



   public static void main(String[] args) {

   

    DataDrawDemo frame=new DataDrawDemo();

    frame.show();

    frame.gracu.myGraphics=(Graphics2D)frame.jPanel1.getGraphics();

    frame.mp.myGraphics=(Graphics2D)frame.jPanel1.getGraphics();

    frame.mp.myGraphics.setBackground(Color.white);

    frame.mp.myGraphics.clearRect(0,0,650,375);

   }

        //第一组数据

              double[] Xs1=new double[]{-2,2,4,6,8,10,12,14};

              double[] Ys1=new double[]{-4,10,3,14,4,10,6,7};

              //第二组数据

              double[] Xs2=new double[]{-1,2,4,6,8,10,12,14,16};

              double[] Ys2=new double[]{1,5,7,1,13,11,4,10,8};

     //这是一个画曲线的程序

       void DwData()

       {

         //剪裁,可以试试没有剪裁是什么表现?

       mp.myGraphics.clipRect(10,10,621,351);

      //由于是用两个对象绘图,所以应该分别剪切

       gracu.myGraphics.clipRect(10,10,621,351); 

         //清除绘图空间    

          mp.myGraphics.clearRect(0,0,650,375);

      //用户坐标和屏幕坐标转换

       mp.truemode(10,630,10,360,wx1,wx2,wy1,wy2);

          //设置颜色             

       mp.myGraphics.setPaint(Color.darkGray);

       //画边框

       mp.myGraphics.drawRect(10,10,620,350);

       mp.myGraphics.setFont(new Font("宋体", 0, 10)); //9为字大小

       //画坐标

       mp.axis(2,2,2,2);                  

       //画红线 

       int[] x=new int[Xs1.length];

       int[] y=new int[Ys1.length];

       int[] myxy;

       //统一实现坐标转换      

       for (int i=0;i<x.length;i++)

       {

           myxy=mp.moxy(Xs1[i],Ys1[i]);

           x[i]=myxy[0];

           y[i]=myxy[1];

       }

       if (kcu)

       {

         mp.myGraphics.setPaint(Color.red);

        mp.myGraphics.drawPolyline(x,y,x.length);

       }

       else

       {

         gracu.myGraphics.setPaint(Color.red);

        gracu.DrawCurves(x,y);

       }

       //画蓝线

       x=new int[Xs2.length];

       y=new int[Ys2.length];

       for (int i=0;i<x.length;i++)

       {

           myxy=mp.moxy(Xs2[i],Ys2[i]);

           x[i]=myxy[0];

           y[i]=myxy[1];

       }

       if (kcu)

       {

         mp.myGraphics.setPaint(Color.blue);

        mp.myGraphics.drawPolyline(x,y,x.length);

       }

       else

       {

         gracu.myGraphics.setPaint(Color.blue);

        gracu.DrawCurves(x,y);

       }          

  }

             

  //退出窗口事件

  protected void processWindowEvent(WindowEvent e) {

    super.processWindowEvent(e);

    if (e.getID() == WindowEvent.WINDOW_CLOSING) {

      System.exit(0);

    }

  }

 

  //鼠标按下事件

  void JPanel_mousePressed(MouseEvent e)

  {

      double[] zs=mp.ScrtoCon(e.getX(),e.getY());

      jText1.setText(String.valueOf((float)zs[0])); 

      jText2.setText(String.valueOf((float)zs[1])); 

  }



  //鼠标释放事件

  void JPanel_mouseReleased(MouseEvent e)

  {

      double[] zs=mp.ScrtoCon(e.getX(),e.getY());

      jText1.setText("");   

      jText2.setText("");

     

       //画红线 

       mp.myGraphics.setPaint(Color.darkGray);

      mp.myGraphics.drawLine(e.getX()-3,e.getY(),e.getX()+3,e.getY());

      mp.myGraphics.drawLine(e.getX(),e.getY()-3,e.getX(),e.getY()+3);

      mp.myGraphics.drawString(String.valueOf((float)zs[0]),e.getX()+10,e.getY());       

      mp.myGraphics.drawString(String.valueOf((float)zs[1]),e.getX()+10,e.getY()+12); 

  }



  //鼠标拖动事件

  void JPanel_mouseDragged(MouseEvent e)

  {

      double[] zs=mp.ScrtoCon(e.getX(),e.getY());

      jText1.setText(String.valueOf((float)zs[0])); 

      jText2.setText(String.valueOf((float)zs[1])); 

  }

 

  //开始 

  void jButton1_actionPerformed(ActionEvent e){



          wx1=1000000;

          wy1=1000000;

          wx2=-1000000;

          wy2=-1000000;

 

          //试验中数据来自一个数组,实际中可来自任何地方

   //设置初始范围

   for (int i=0;i<Xs1.length;i++)

   {

       if (Xs1[i]< wx1)

          wx1=Xs1[i];

       if (Xs1[i]> wx2)

          wx2=Xs1[i];

      

      if (Ys1[i]< wy1)

          wy1=Ys1[i];

       if (Ys1[i]> wy2)

          wy2=Ys1[i];

     }

  for (int i=0;i<Xs2.length;i++)

   {

       if (Xs2[i]< wx1)

          wx1=Xs2[i];

       if (Xs2[i]> wx2)

          wx2=Xs2[i];

      if (Ys2[i]< wy1)

          wy1=Ys2[i];

      if (Ys2[i]> wy2)

          wy2=Ys2[i];

     }

    DwData();

  }



  //左移

  void jButton2_actionPerformed(ActionEvent e) {

     

    wx1-=1;

    wx2-=1; 

    DwData();

  }

 

  //右移

   void jButton3_actionPerformed(ActionEvent e) {

     

   

      wx1+=1;

      wx2+=1; 

      DwData();

  }

 

  //上移

  void jButton4_actionPerformed(ActionEvent e) {

     

    wy1-=1;

    wy2-=1; 

    DwData();

  }



  //下移

  void jButton5_actionPerformed(ActionEvent e) {

     

    wy1+=1;

    wy2+=1; 

    DwData();

  }

 

  //X扩

  void jButton6_actionPerformed(ActionEvent e) {

     

    wx1-=1;

    wx2+=1; 

    DwData();

  }

 

  //X缩

  void jButton7_actionPerformed(ActionEvent e) {

     

    wx1+=1;

    wx2-=1; 

    DwData();

  }

 

  //Y扩

  void jButton8_actionPerformed(ActionEvent e) {

     

    wy1-=1;

    wy2+=1; 

    DwData();

  }



  //Y缩

  void jButton9_actionPerformed(ActionEvent e) {

     

    wy1+=1;

    wy2-=1; 

    DwData();

  }



  //样条控制

  void jButton10_actionPerformed(ActionEvent e) {

     

    if (kcu)

    {

           jButton10.setText("直线");

           kcu=false;

    }

    else

    {

           jButton10.setText("样条");

           kcu=true;

    }

    DwData();

  }

}



//图形处理类

class myGraphicsData

{

       //屏幕坐标

       private int X11, Y11, X12, Y12; //x1,y1,x2,y2

       //用户坐标

       private double W1, W2, W3, W4; //x1,x2,y1,y2

       //绘图对象

       public Graphics2D myGraphics;

       double Ax8, Ay8;

       //用户窗口与屏幕窗口的转换

       //x1,x2,,y1,y2为屏幕坐标

       //wx1,wx2,wy1,wy2为用户坐标

      

       public void truemode(int x1, int x2, int y1,int y2, double wx1, double wx2, double wy1, double wy2)

       {

              X11 = x1 ; X12 = x2;

              Y11 = y1 ; Y12 = y2;

              W1 = wx1 ; W2 = wx2;

              W3 = wy1 ; W4 = wy2;

              Ax8 = (X12 - X11) / (wx2 - wx1);

              Ay8 = (Y12 - Y11) / (wy2 - wy1);

       }



       //把用户坐标转为屏幕坐标

       public int[] moxy(double Xa, double Ya)

       {

              int[] myout=new int[2];

              myout[0] = (int)(Ax8 * (Xa - W1) + X11);

              myout[1] = (int)(Y12 - Ay8 * (Ya - W3));

              return myout;

       }



       //把屏幕坐标转为用户坐标

       public double[] ScrtoCon(int X6, int Y6)

       {

              double[] myout=new double[2];

              myout[0] = (X6 - X11) / Ax8 + W1;

              myout[1] = (Y12 - Y6) / Ay8 + W3;

              return myout;

       }



       //画线

       public void Dline(double xa, double ya, double xb, double yb)

       {

              try

              {

                     int x6, y6, x7, y7;

                     x6 = (int)(Ax8 * (xa - W1) + X11);

                     y6 = (int)(Y12 - Ay8 * (ya - W3));

                     x7 = (int)(Ax8 * (xb - W1) + X11);

                     y7 = (int)(Y12 - Ay8 * (yb - W3));

                     myGraphics.drawLine(x6, y6, x7, y7);

              }

              catch(Exception e){}

       }





       //画坐标U,V为 X,Y轴单位,ns,nt为 x,y轴写字间隔



       public void axis(double u, double v, int ns, int nt)

       {

              double p9, q9, s;

              int n2, swx,swy;

              int xk=0;

              int yk=0;

              double ge;

              int[] showxy=new int[2];

              swx = 0;

              swy=4;

              ge = (double)0.008 * (W2 - W1);

              p9 = W1;

              q9 = (double)(W3 + (W4 - W3) * 0.05);

              if ((W1 < 0) && (W2 > 0)) p9 = 0;

              if ((W3 < 0) && (W4 > 0)) q9 = 0;

              Dline(p9, W3, p9, W4);

              n2 = 0;

              s = 0;

              while (s < W4)

              {

                     Dline(p9, s, p9 + ge, s);

                     if (n2 >= nt)

                     {

                            Dline(p9, s, p9 + ge + ge, s);

                            n2 = 1;

                            showxy=moxy(p9 + ge + ge,s);

                            myGraphics.drawString(String.valueOf(s),showxy[0] - swx+4, showxy[1] - swy+4);

                     }

                     else

                     {

                            n2++;

                     }

                     s += v;

              }                  

              //End While

              s = 0;

              n2 = 0;

              while (s > W3)

              {

                     Dline(p9, s, p9 + ge, s);

                     if (n2 >= nt)

                     {

                            Dline(p9, s, p9 + ge + ge, s);

                            n2 = 1;

                            showxy=moxy(p9 + ge + ge, s);

                        myGraphics.drawString(String.valueOf(s),showxy[0] - swx+4, showxy[1] - swy+4);

                            }

                     else

                     {

                            n2 ++;

                     }

                     s -= v;

              }

              //End While

              Dline(W1, q9, W2, q9);

              ge = (float)(0.008 * (W4 - W3));

              n2 = 0;

              s = 0;

              while (s < W2)

              {

                     Dline(s, q9, s, q9 + ge);

                     if (n2 >= ns)

                     {

                            Dline(s, q9, s, q9 + ge + ge);

                            n2 = 1;

                            showxy=moxy(s, q9);

                        myGraphics.drawString(String.valueOf(s),showxy[0] - swx, showxy[1] - swy-4);

                     }

                     else

                     {

                            n2 ++;

                     }

                     s += u;

              }                  

              //End While

              s = 0;

              n2 =0 ;

              while (s > W1)

              {

                     Dline(s, q9, s, q9 + ge);

                     if (n2 >= ns)

                     {

                            Dline(s, q9, s, q9 + ge + ge);

                            n2 = 1;

                            showxy=moxy(s, q9);

                         myGraphics.drawString(String.valueOf(s),showxy[0] - swx, showxy[1] - swy-4);

                  }

                     else

                     {

                            n2 ++;

                     }

                     s -= u;

              }           

              //End While

       }

}



// GraphicsCurve类与子定义样条曲线相同















五、曲线用Applet显示的数据来源问题



如果需要Applet显示曲线图形,就牵涉到如何提供数据的问题,最简单的办法,是在站点上放置一个有关数据的文本文件,由Applet直接调用这个文本文件,从而读出数据来。但这种办法缺乏必要的灵活性,也是不受推荐的。关键是要能调用数据库数据。当然,经过某些特殊的处理,Applet调用服务器端的数据库也不是不可能,不过这样一来将会带来很多安全隐患,在实用中价值不大。比较好的办法,是在服务器端设置一个动态网页,由这个网页调用数据库,而Applet则通过这个网页取得数据库的数据,由于动态网页的调用是在服务器中执行的,这种方法无论在安全性还是效率上效果都比较好,我们下面来具体讨论一下这种方法。

为了讨论简单,这种动态网页使用最简单的ASP,其它如JSP等的写法,和这个例子是相似的。

数据库

数据处理页面

jsp

asp等

Applet

























首先做一个数据库:BookDB



两张表:

1)xytable







   2)图表







做ASP页面:qt.asp

注意,这里把表名作为传入值使用。



<% tname=Request("tablename") %>

<%

Set cnnDB = Server.CreateObject("ADODB.Connection")

'建立Connection(资料库连结)对象,并设定由cnnDB对象变数引用

cnnDB.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _

                            "Data Source=" & Server.MapPath("BookDB.mdb")

'设定连结对象的连结字串



cnnDB.Open '开启资料库

Set rstObj = Server.CreateObject ("ADODB.Recordset")

'建立Recordset(记录集)对象,并设定由rstObj对象变数引用

rstObj.Open "select * from " & tname , cnnDB '开启记录集对象

%>

<%

       '利用DoLoop循环配合EOF属性将资料表中的记录列出

       Do While Not rstObj.EOF

              %>                      

              <% = (rstObj("x")) %>

                <% = vbCrLf %>

              <% = (rstObj("y")) %>

                <% = vbCrLf %>                

              <%

              rstObj.Mov
8
1
分享到:
评论
2 楼 刘亮love小雪 2015-05-17  
谢谢啦
1 楼 zengsingle 2008-10-19  
好文
分享了,谢谢!

相关推荐

    Java 2D高级绘图技术

    Java 2D高级绘图技术,图形绘制的基本方法,曲线问题的高级应用开发,构造几何形状

    java2D高级绘图.doc

    java2D高级绘图.doc

    Java_2D高级绘图

    java 2D 图形学,包括基本的一些程序指令的解释

    constellation:纯Java实现的高级2D绘图设计包

    使用 100% 纯 Java(Java2D 和 Swing 接口)创建最先进的 2D 绘图包。 特征 高级几何:直线、圆、椭圆和贝塞尔曲线 合作 并发设计模块使用户能够同时创建/更新模型(联合会议) 远程协助模块使用户能够远程控制用户...

    JAVA上百实例源码以及开源项目

    笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对IT的憧憬、向往!此时此...

    JAVA上百实例源码以及开源项目源代码

    Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...

    java开源包4

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包101

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包11

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包6

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包9

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包5

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包8

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包10

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包3

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包1

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包2

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包7

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

Global site tag (gtag.js) - Google Analytics