知識要點:
第一節(jié) Java 2D的增強功能
概述、AWT圖形能力的不足、Java 2D API
第二節(jié) 圖形繪制的基本方法
轉(zhuǎn)換Graphics2D對象、Graphics 類特性、繪圖的屬性和基本編程方法
第三節(jié) 曲線問題的高級應(yīng)用開發(fā)
直線問題深入研究、貝塞爾(Bezier)曲線、自定義樣條曲線編程、
用戶數(shù)據(jù)的曲線顯示、曲線用Applet顯示的數(shù)據(jù)來源問題
第四節(jié) 字符串的高級處理
TextLayout類、LineMetrics類
第五節(jié) 構(gòu)造幾何形狀
2D幾何形狀的設(shè)計、構(gòu)造型區(qū)域幾何形狀、變換、緩沖的圖像
第六節(jié) 三維圖形處理的設(shè)計技術(shù)
透視投影、透視圖形的顯示、隱蔽面消除問題
第七節(jié) 同環(huán)境交互
GraphicsEnvironment類、GraphicsDevice類、GraphicsConfiguration類
第一節(jié) Java 2D的增強功能
一、概述:
由Sun公司與Adobe系統(tǒng)公司合作推出的Java 2D API,提供了一個功能強大而且非常靈活的二維圖形框架。Java 2D API擴展了java.awt包中定義的Graphics類和Image類,提供了高性能的二維圖形、圖像和文字,同時又維持了對現(xiàn)有AWT應(yīng)用的兼容。
二、AWT圖形能力的不足:
在 AWT 的初始實現(xiàn)中,圖形能力并不十分完善。因為開發(fā) JDK 是打算將其作為平臺中立的實現(xiàn)平臺,所以其原始的功能被限制于“最少公共功能”上,所有被支持的操作系統(tǒng)上保證提供這些公共功能;
在 Java 2D 出現(xiàn)之前,對繪制能力、字體操作和圖像控制的支持非常少。而對諸如用圖案進行著色、形狀操作以及圖形變換之類的重要操作的支持則完全沒有。
Java 2D 滿足了跨平臺實現(xiàn)中對這些功能以及其它功能的需求。
三、Java 2D API:
它是JFC (Java Fundation Classes)的一員,加強了傳統(tǒng)AWT( Abstract Windowing Toolkit )的描繪功能。在 JDK1.2中已經(jīng)支援 Java 2D 的使用。透過Java 2D API ,程序員可以輕松地描繪出任意的幾何圖形、運用不同的填色效果、對圖形做旋轉(zhuǎn)( rotate)、縮放( scale)、扭曲( shear)等。如圖所示,程序員透過2D API所提供的功能,簡單地利用不同類型的線或是填色效果繪出統(tǒng)計圖,以區(qū)分出不同的資料。
它們是基于Graphics2D類的繪圖功能,是對AWT中的Graphics類的進一步的擴展和增強。主要體現(xiàn)在:
1。對渲染質(zhì)量的控制:消除鋸齒以平滑繪制對象的邊緣
2.裁剪、合成和透明度:它們允許使用任意形狀來限定繪制操作的邊界。它們還提供對圖形進行分層以及控制透明度和不透明度的能力。
3.控制和填充簡單及復(fù)雜的形狀:這種功能提供了一個 Stroke 代理和一個 Paint 代理,前者定義用來繪制形狀輪廓的筆(定義繪制的筆的寬度和樣式),后者允許用純色、漸變色和圖案來填充形狀。
4。圖像處理和變換:Java 2D 同 Java 高級圖像 API(Java Advanced Imaging API (JAI))協(xié)作,支持用大量圖形格式處理復(fù)雜的圖像。Java 2D 還為您提供了修改圖像、形狀和字體字符的變換能力。
5。特殊的填充方式,如梯度或者圖案
6.高級字體處理和字符串格式化:允許象操作任何其它圖形形狀一樣操作字體字符。除此以外,可以象文字處理程序一樣,通過為 String 中的字符應(yīng)用屬性和樣式信息來創(chuàng)建格式化文本。
java.awt.geom 包中的Areas類支援聯(lián)集( union)、交集( intersection)、差集(subtraction )、Exclusive OR (XOR)等布爾運算。最後, AffineTransform 類別則提供圖形物件做Scale(比例)、Shear(剪裁) 、Rotate(旋轉(zhuǎn))等座標(biāo)上的轉(zhuǎn)換。
第二節(jié) 圖形繪制的基本方法
一、轉(zhuǎn)換Graphics2D對象
繪制圖形時,可以在Graphics對象或者Graphics2D對象上進行,它們都代表了需要繪圖的區(qū)域,選擇那個取決于是否要使用所增加的Java2D的圖形功能。但要注意的是,所有的Java2D圖形操作都必須在Graphics2D對象上調(diào)用。Graphics2D是Graphics的子類,同樣包含在java.awt包中。
public void paintComponent(Graphics comp)
{ Graphics2D comp2D=(Graphics2D)comp;
}
或者
public void paint (Graphics comp)
{ Graphics2D comp2D=(Graphics2D)comp;
}
二、Graphics 類特性
Graphics 類支持幾種確定圖形環(huán)境狀態(tài)的特性。以下列出了部分特性:
1)Color:當(dāng)前繪制顏色,它屬于 java.awt.Color 類型。所有的繪制、著色和純文本輸出都將以指定的顏色顯示。
2)Font:當(dāng)前字體,它屬于 java.awt.Font 類型。它是將用于所有純文本輸出的字體。
3)Clip:java.awt.Shape 類型的對象,它充當(dāng)用來定義幾何形狀的接口。該特性包含的形狀定義了圖形環(huán)境的區(qū)域,繪制將作用于該區(qū)域。通常情況下,這一形狀與整個圖形環(huán)境相同,但也并不一定如此。
4)ClipBounds:java.awt.Rectangle 對象,它表示將包圍由 Clip 特性定義的 Shape 的最小矩形。它是只讀特性。
5)FontMetrics:java.awt.FontMetrics 類型的只讀特性。該對象含有關(guān)于圖形環(huán)境中當(dāng)前起作用的 Font 的信息。如同我們將看到的那樣,獲取此信息的這種機制已被 LineMetrics 類所取代
6)Paint Mode:該特性控制環(huán)境使用當(dāng)前顏色的方式。如果調(diào)用了 setPaintMode() 方法,那么所有繪制操作都將使用當(dāng)前顏色。如果調(diào)用了 setXORMode() 方法(該方法獲取一個 Color 類型的參數(shù)),那么就用指定的顏色對像素做“XOR”操作。XOR 具有在重新繪制時恢復(fù)初始位模式的特性,因此它被用作橡皮擦除和動畫操作。
三、繪圖的屬性和基本編程方法
1)顏色Color類:沒有變化。
2)填充方式:
Paint(油漆桶) 接口有幾個具體的實現(xiàn),它們允許用純色、漸變色或圖案來填充形狀。
1,純色填充(Color類):對 java.awt.Color 類做了一些調(diào)整以實現(xiàn) Paint,并且可以用于純色填充。
2,漸變色來填充(梯度填充GradientPaint類):java.awt.GradientPaint 類允許用線性顏色漸變色來填充形狀,線性顏色漸變色允許在兩個指定的 Color 對象之間創(chuàng)建過渡??梢詫u變色設(shè)置成“周期性的”,這將導(dǎo)致漸變色圖案重復(fù)出現(xiàn)。
3,圖案填充(紋理TexturePaint類):提供了 java.awt.TexturePaint 類,它可以用由 BufferedImage 描述的圖案填充形狀
編程方法:
使用Graphics2D類中的setPaint()方法并使用Paint對象作為其參數(shù),但由于任何可以作為填充的類如GradientPaint、TexturePaint和Color都實現(xiàn)了Paint接口(該接口注意定義了在Graphics2D下的顏色填充方式),因此可以將它們作為參數(shù)。如:
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)設(shè)置筆的形狀:
Stroke 接口由 java.awt.BasicStroke 類實現(xiàn)。該類允許進行大量的選擇以修改線的繪制細節(jié)??梢跃幊讨付?BasicStroke 寬度,也可以指定對名為柱頭和交點的路徑上端點和交點的“裝飾”?,F(xiàn)在也可以繪制點劃線了,只須設(shè)置 BasicStroke 的破折號屬性即可。
在Graphics類中線條是一個點寬,而在Graphics2D中可以通過BasicStoke類中的setStroke()方法來設(shè)置。其構(gòu)造函數(shù)是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; //設(shè)置畫刷的粗細為 0.5
BufferedImage bi = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D)bi.getGraphics();
Stroke stroke = g.getStroke(); //得到當(dāng)前的畫刷
g.setStroke(new BasicStroke(thick, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));
g.draw(new Line2D.Float(x1, y1, x2, y2)); 畫線
g.setStroke( stroke ); //將畫刷復(fù)原
5)創(chuàng)建要繪制的形狀對象
在Java2D中進行繪圖時,不是采用對應(yīng)的方法來實現(xiàn),而是為要實現(xiàn)某中形狀創(chuàng)建出相應(yīng)的形狀對象。這可以通過使用java.awt.geom包中的類來定義所要創(chuàng)建的形狀。如線條Line2D.Float類、距形Rectangle2D.Float或者Rectangle2D.Double類、橢圓Ellipes2D.Float、圓弧Arc2D.Float類等。
6)繪制對象:
1,可以使用Graphics2D類中的方法draw()用于繪制輪廓,而fill()方法用于填充。它們都以前面所創(chuàng)建的圖形對象作為參數(shù)。
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”后綴。這些新的形狀使用浮點值(而不是整數(shù))來描述其幾何形狀。
Polygon類(int[] xpoints, int[] ypoints, int npoints)
RectangularShape(抽象類,其子類有Arc2D, Ellipse2D, Rectangle2D, RoundRectangle2D), Rectangle(距形)
QuadCurve2D(二次貝塞爾樣條曲線,貝塞爾曲線由兩個端點以及一個或兩個控制點指定。貝塞爾曲線創(chuàng)建了適合于大多數(shù)表示的曲線。)
CubicCurve2D(三次貝塞爾樣條曲線)
Area(區(qū)域)
GeneralPath(由直線、二次樣條曲線、三次樣條曲線所構(gòu)成)
Line2D
8)基本步驟
繪圖的第一個步驟是產(chǎn)生 Graphics2D 對象。 然后設(shè)定所要的狀態(tài)屬性。例如你想要對一物件做漸層式的填色,可以設(shè)定屬性 Paint為 GradientPaint。最後再調(diào)用Graphics2D所提供的方法fill或是draw,完成整個繪圖的程序。
9)程序?qū)嵗?br />
例一:
這是一個最簡單的例子,也可以認為是繪圖的一個最簡單的框架。
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);
通過該方法的設(shè)置,使圖形去除鋸齒狀,可以得到多么細膩的圖形。
樣例:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class DrawDemo extends JFrame {
public DrawDemo(){
//設(shè)置窗口的大小、標(biāo)題
this.setSize(new Dimension(600, 400));
//創(chuàng)建繪制各種形狀的容器
ShapesPanel shapesPanel = new ShapesPanel();
//將該容器加入窗口
getContentPane().add(shapesPanel, BorderLayout.CENTER);
}
public static void main(String[] args) {
DrawDemo frame = new DrawDemo();
frame.setVisible(true);
//當(dāng)窗口關(guān)閉時清空內(nèi)存
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
//創(chuàng)建各種容器的類
class ShapesPanel extends JPanel {
final int maxCharHeight = 15;
final Color bg = Color.white; //聲明背景顏色為灰色
final Color fg = Color.blue; //聲明前景顏色為藍色
public ShapesPanel() {
setBackground(bg); //設(shè)置背景顏色
setForeground(fg); //設(shè)置前景顏色
//創(chuàng)建組合邊框
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createRaisedBevelBorder(),
BorderFactory.createLoweredBevelBorder()));
}
public void paintComponent(Graphics g1) {
super.paintComponent(g1); //清空背景顏色
float thick = 0.5f; //設(shè)置畫刷的粗細為 0.5
Graphics2D g = (Graphics2D)g1;
Stroke stroke = g.getStroke(); //得到當(dāng)前的畫刷
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為字大小
//設(shè)置筆刷為黑色
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); //將畫刷復(fù)原
}
}
例三:圖形靈活的顯示
在上面的例子中,是使用一個繼承于JPanel的類,覆蓋它的void paintComponent(Graphics g1)事件方法,實現(xiàn)繪圖的,這樣雖然方便,但顯得靈活性不高。
實際上,通過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();
//構(gòu)造函數(shù)
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);
}
}
例四:剪裁
圖形處理問題中,剪裁由的時候是非常難處理的,所謂剪裁是指超過繪圖取得內(nèi)容不顯示,看起來這是個簡單問題,但由于所有的線條必須計算與邊界的交點,而且邊界有四個方向,這就使問題變得很復(fù)雜。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();
//構(gòu)造函數(shù)
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);
}
}
第三節(jié) 曲線問題的高級應(yīng)用開發(fā)
在jdk尚未支援 2D圖形之前,只可以畫出直的、相同粗細的線條?,F(xiàn)在可以通過2D API繪出不同粗細的線條及圓滑的曲線。在java.awt.geom包中提供了Line2D、 QuadCurve2D(二次貝塞爾曲線)及 CubicCurve2D(三次貝塞爾曲線)等相關(guān)的類,讓程序員能夠輕松地繪出想要的線條。
其實繪圖的核心是畫線,下面通過一些實例對一些問題進行深入的討論。
一、直線問題深入研究
樣例:
我們通過一個例子,深入的研究一下繪制直線和折線需要掌握哪些內(nèi)容。
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();
//構(gòu)造函數(shù)
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;
//設(shè)置筆刷
//園頭園連接
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;
//設(shè)置筆刷
//方頭方連接
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;
//設(shè)置筆刷
//方頭方連接
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(三次貝塞爾曲線)等相關(guān)的類,可以很容易的畫出貝賽爾曲線。
QuadCurve2D為三個數(shù)據(jù),中間一個為控制點。
CubicCurve2D為四個數(shù)據(jù),中間兩個為控制點。
樣例:
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();
//構(gòu)造函數(shù)
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);
}
}
三、自定義樣條曲線編程
當(dāng)我們需要平滑多個數(shù)據(jù)樣本點的時候,貝塞爾曲線就不能滿足要求了,為此,可以采用最早由美國“波音”飛機制造公司提出來的樣條曲線來完成,這種曲線所以稱之為樣條,是因為它模擬了造船業(yè)中的放樣原理。
樣條曲線的數(shù)學(xué)原理請參考計算機圖形學(xué),這里給出的是由java編寫的三次樣條曲線的例子。曲線平滑的原則是,必須通過所有的樣本點,另外,不論有多少樣本點,曲線的階次大為三次,所以是穩(wěn)定的。
這里我們可以看出來,程序設(shè)計的生命是什么呢?數(shù)學(xué)!這是程序設(shè)計著的生命所在。語言只是一種規(guī)范或者是一個工具,要真正寫出好的程序,沒有深厚的數(shù)學(xué)功底,是萬萬不可能的。
樣例:
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;
//構(gòu)造函數(shù)
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;
//設(shè)置筆刷
//方頭園連接
//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;
}
//參數(shù)表
//x數(shù)組,y數(shù)組,筆刷
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
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
{
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
{
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;
}
}
}
}
}
四、用戶數(shù)據(jù)的曲線顯示
當(dāng)需要用曲線表達數(shù)據(jù)的時候,我們雖然可以使用由廠家提供的“圖表”組件,但更多的還是需要自己編寫的,請仔細研究下面的程序,當(dāng)對圖表設(shè)計有更深入的理解。
下面的例子,我們構(gòu)造一個專門處理用戶數(shù)據(jù)的類,在這個類里,實現(xiàn)了用戶坐標(biāo)和屏幕坐標(biāo)的轉(zhuǎn)換,同時給出了一個自動繪制坐標(biāo)的方法。我們也直接使用了上面我們討論過的樣條曲線的類實現(xiàn)數(shù)據(jù)平滑。例子中的數(shù)據(jù)可以來自于數(shù)據(jù)庫或其它任何地方,仔細的研究這個例子,可以看出只要我們開動腦筋,把java強大的功能和我們對問題的理解結(jié)合在一起,就可以寫出多么靈活多變的程序來呀!
樣例:
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;
//用戶坐標(biāo)轉(zhuǎn)換對象
myGraphicsData mp=new myGraphicsData();
//曲線轉(zhuǎn)換對象
GraphicsCurve gracu=new GraphicsCurve();
//窗口范圍
double wx1,wx2,wy1,wy2;
//構(gòu)造函數(shù)
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("");
//鼠標(biāo)按下偵聽器
jPanel1.addMouseListener(new java.awt.event.MouseAdapter(){
public void mousePressed(MouseEvent e) {
JPanel_mousePressed(e);
}
});
//鼠標(biāo)拖動偵聽器
jPanel1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
JPanel_mouseDragged(e);
}
});
//鼠標(biāo)釋放偵聽器
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);
}
//第一組數(shù)據(jù)
double[] Xs1=new double[]{-2,2,4,6,8,10,12,14};
double[] Ys1=new double[]{-4,10,3,14,4,10,6,7};
//第二組數(shù)據(jù)
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()
{
//剪裁,可以試試沒有剪裁是什么表現(xiàn)?
mp.myGraphics.clipRect(10,10,621,351);
//由于是用兩個對象繪圖,所以應(yīng)該分別剪切
gracu.myGraphics.clipRect(10,10,621,351);
//清除繪圖空間
mp.myGraphics.clearRect(0,0,650,375);
//用戶坐標(biāo)和屏幕坐標(biāo)轉(zhuǎn)換
mp.truemode(10,630,10,360,wx1,wx2,wy1,wy2);
//設(shè)置顏色
mp.myGraphics.setPaint(Color.darkGray);
//畫邊框
mp.myGraphics.drawRect(10,10,620,350);
mp.myGraphics.setFont(new Font("宋體", 0, 10)); //9為字大小
//畫坐標(biāo)
mp.axis(2,2,2,2);
//畫紅線
int[] x=new int[Xs1.length];
int[] y=new int[Ys1.length];
int[] myxy;
//統(tǒng)一實現(xiàn)坐標(biāo)轉(zhuǎn)換
for (int i=0;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
{
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);
}
}
//鼠標(biāo)按下事件
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]));
}
//鼠標(biāo)釋放事件
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);
}
//鼠標(biāo)拖動事件
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;
//試驗中數(shù)據(jù)來自一個數(shù)組,實際中可來自任何地方
//設(shè)置初始范圍
for (int i=0;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
{
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
{
//屏幕坐標(biāo)
private int X11, Y11, X12, Y12; //x1,y1,x2,y2
//用戶坐標(biāo)
private double W1, W2, W3, W4; //x1,x2,y1,y2
//繪圖對象
public Graphics2D myGraphics;
double Ax8, Ay8;
//用戶窗口與屏幕窗口的轉(zhuǎn)換
//x1,x2,,y1,y2為屏幕坐標(biāo)
//wx1,wx2,wy1,wy2為用戶坐標(biāo)
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);
}
//把用戶坐標(biāo)轉(zhuǎn)為屏幕坐標(biāo)
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;
}
//把屏幕坐標(biāo)轉(zhuǎn)為用戶坐標(biāo)
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){}
}
//畫坐標(biāo)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;
網(wǎng)站名稱:Java2D高級繪圖-創(chuàng)新互聯(lián)
文章起源:
http://weahome.cn/article/dihejd.html