Java圖形界面編程

一、Java圖形用戶界面(gui)介紹

1、Java GUI簡(jiǎn)介

??圖形用戶界面(Graphics User Interface,GUI)是用戶與程序交互的窗口,比命令行的界面更加直觀并且更好操作。


??Sun已經(jīng)提供了一個(gè)跨平臺(tái)GUI開發(fā)工具包AWT抽象窗口工具箱(Abstract Window Toolkit)。
??Sun又創(chuàng)建了一個(gè)新的GUI框架swing。解決了AWT存在的Icd問題。
??IBM認(rèn)為swing比較消耗內(nèi)存,創(chuàng)建了一個(gè)新的GUI庫,這就是SWT。
??IBM為了方便開發(fā)SWT程序,在SWT基礎(chǔ)上又創(chuàng)建了一個(gè)更易用,功能強(qiáng)大的圖開包"JFace"。
??AWT(Abstract Window Toolkit):抽象窗口工具包,早期編寫圖形界面應(yīng)用程序的包。 AWT的圖形函數(shù)與操作系統(tǒng)提供的圖形函數(shù)有著一一對(duì)應(yīng)的關(guān)系。也就是說,當(dāng)我們利用 AWT構(gòu)件圖形用戶界面的時(shí)候,實(shí)際上是在利用操作系統(tǒng)的圖形庫。
????????AWT的層次關(guān)系

??Swing:為解決 AWT 存在的問題而新開發(fā)的圖形界面包。Swing是對(duì)AWT的改良和擴(kuò)展。 不僅提供了AWT 的所有功能,還用純粹的Java代碼對(duì)AWT的功能進(jìn)行了大幅度的擴(kuò)充,與平臺(tái)無關(guān)。
????????Swing組件層次關(guān)系


2、AWT和Swing的區(qū)別與聯(lián)系

??AWT和Swing都是java中的包。
??AWT(Abstract Window Toolkit):抽象窗口工具包,早期編寫圖形界面應(yīng)用程序的包。
??Swing:為解決 AWT 存在的問題而新開發(fā)的圖形界面包。Swing是對(duì)AWT的改良和擴(kuò)展。
??AWT和Swing的實(shí)現(xiàn)原理不同:
??AWT的圖形函數(shù)與操作系統(tǒng)提供的圖形函數(shù)有著一一對(duì)應(yīng)的關(guān)系。也就是說,當(dāng)我們利用 AWT構(gòu)件圖形用戶界面的時(shí)候,實(shí)際上是在利用操作系統(tǒng)的圖形庫。
??不同的操作系統(tǒng)其圖形庫的功能可能不一樣,在一個(gè)平臺(tái)上存在的功能在另外一個(gè)平臺(tái)上則可能不存在。為了實(shí)現(xiàn)Java語言所宣稱的"一次編譯,到處運(yùn)行"的概念,AWT不得不通過犧牲功能來實(shí)現(xiàn)平臺(tái)無關(guān)性。因此,AWT 的圖形功能是各操作系統(tǒng)圖形功能的“交集”。
??因?yàn)锳WT是依靠本地方法來實(shí)現(xiàn)功能的,所以AWT控件稱為“重量級(jí)控件”。
??而Swing,不僅提供了AWT 的所有功能,還用純粹的Java代碼對(duì)AWT的功能進(jìn)行了大幅度的擴(kuò)充。例如:并不是所有的操作系統(tǒng)都提供了對(duì)樹形控件的支持,Swing則利用了AWT中所提供的基本作圖方法模擬了一個(gè)樹形控件。
??由于 Swing是用純粹的Java代碼來實(shí)現(xiàn)的,因此Swing控件在各平臺(tái)通用。因?yàn)镾wing不使用本地方法,故Swing控件稱為“輕量級(jí)控件”。
??AWT和Swing之間的區(qū)別:
??1)、AWT 是基于本地方法的C/C++程序,其運(yùn)行速度比較快;Swing是基于AWT的Java程序,其運(yùn)行速度比較慢。
??2)、AWT的控件在不同的平臺(tái)可能表現(xiàn)不同,而Swing在所有平臺(tái)表現(xiàn)一致。
??在實(shí)際應(yīng)用中,應(yīng)該使用AWT還是Swing取決于應(yīng)用程序所部署的平臺(tái)類型。例如:
??1)、對(duì)于一個(gè)嵌入式應(yīng)用,目標(biāo)平臺(tái)的硬件資源往往非常有限,而應(yīng)用程序的運(yùn)行速度又是項(xiàng)目中至關(guān)重要的因素。在這種矛盾的情況下,簡(jiǎn)單而高效的AWT當(dāng)然成了嵌入式Java的第一選擇。
??2)、在普通的基于PC或者是工作站的標(biāo)準(zhǔn)Java應(yīng)用中,硬件資源對(duì)應(yīng)用程序所造成的限制往往不是項(xiàng)目中的關(guān)鍵因素。所以在標(biāo)準(zhǔn)版的Java中則提倡使用Swing,也就是通過犧牲速度來實(shí)現(xiàn)應(yīng)用程序的功能。
??在java中,AWT包的名稱是java.awt,Swing包的名稱是javax.swing。

二、Swing的基本使用

1、幾個(gè)常用的組件

??1、文本框(JTextField)
??2、密碼框(JPasswordField)
??3、標(biāo)簽(JLable)
??4、復(fù)選框組件(JCheckBox)
??5、單選框組件(JRadioButton):同一組單選按鈕必須先創(chuàng)建ButtonGroup,然后把單選框組件放入到ButtonGroup中。



??6、下拉框(JComboBox)
??7、列表框(JList)
??8、滾動(dòng)窗格(JScrollPane)

??9、列表框(JList)和滾動(dòng)窗格(JScrollPane)一般會(huì)一起使用。
??10、拆分窗格(JSpitPane):屬于容器類組件。
??11、JTextArea:多行文本框。
??12、JTabbedPane:選項(xiàng)卡窗格(業(yè)簽組件)。
??13、JMenuBar:菜單條組件
??14、JMenu:菜單組件
??15、JMenuItem:菜單項(xiàng)組件
??16、JToolBar:容器類組件

2、Java布局管理

??Java為我們提供了幾個(gè)常用的布局管理器類,例如:FlowLayout、BorderLayout、GridLayout、GridBagLayout等。
??1、java.awt FlowLayout(流布局) 將組件按從左到右而后從上到下的順序依次排列,一行不能放完則折到下一行繼續(xù)放置。流式布局可以以左對(duì)齊、居中對(duì)齊、右對(duì)齊的方式排列組件。


??流式布局不限制他所管理的組件的大小,允許他們有最佳的大小。當(dāng)容器最縮放時(shí),組件的位置可以改變,但組件的大小不改變。JPanel的默認(rèn)布局為流式布局管理。
??2、java.awt BorderLayout(邊界布局) 將組件按東、南、西、北、中五個(gè)區(qū)域放置,每個(gè)方向最多只能放置一個(gè)組件。

??JFrame窗體,JDialog對(duì)話框組件默認(rèn)布局方法為邊界布局(BorderLayout),邊界布局的五個(gè)部分不是都要添加,中間部分會(huì)自動(dòng)調(diào)節(jié)大小。
??3、java.awt GridLayout(網(wǎng)格布局) 形似一個(gè)無框線的表格,每個(gè)單元格中放一個(gè)組件。將容器分割成多行多列,組件被填充到每個(gè)網(wǎng)格中,添加到容器中的組件首先放置在左上角的網(wǎng)格中,然后從左到右放置其他組件,當(dāng)占滿該行的所有網(wǎng)格后,接著繼續(xù)在下一行從左到右放置組件。

??組件的相對(duì)位置不隨容器的縮放而改變,但大小會(huì)改變,所有組件的大小相同。
??可以通過GridLayout(int rows, int cols, int hgap, int vgap)來指定網(wǎng)格的行/列,水平間隙/垂直間隙。
??java.awt GridBagLayout 非常靈活,可指定組件放置的具體位置及占用單元格數(shù)目。


??4、一個(gè)界面只可以有一個(gè)JFrame窗體組件,但可以有多個(gè)Jpanel面板組件,而JPanel上也可使用各種布局管理器,這樣可以組合使用達(dá)到較為復(fù)雜的布局效果。
??JPanel是JComponent的子類。默認(rèn)布局為流式布局(FlowLayout),屬于容器類組件,可以加入別的組件。

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MultiLayout extends JFrame {
    private static final long serialVersionUID = 1L;
    
    // 定義組件
    JPanel jp1, jp2;
    JButton jb1, jb2, jb3, jb4, jb5, jb6;

    public static void main(String[] args) {
        new MultiLayout();
    }

    public MultiLayout() {
        // 創(chuàng)建組件
        // JPanel布局默認(rèn)是FlowLayout流布局
        jp1 = new JPanel();
        jp2 = new JPanel();

        jb1 = new JButton("西瓜");
        jb2 = new JButton("蘋果");
        jb3 = new JButton("荔枝");
        jb4 = new JButton("葡萄");
        jb5 = new JButton("桔子");
        jb6 = new JButton("香蕉");

        // 設(shè)置布局管理器(Jpanel默認(rèn)流布局)
        jp1.add(jb1);
        jp1.add(jb2);
        jp2.add(jb3);
        jp2.add(jb4);
        jp2.add(jb5);

        // 把Panel加入JFrame
        this.add(jp1, BorderLayout.NORTH);
        this.add(jb6, BorderLayout.CENTER);
        this.add(jp2, BorderLayout.SOUTH);

        // 設(shè)置窗體
        // 窗體大小
        this.setSize(300, 250);
        // 屏幕顯示初始位置
        this.setLocation(200, 200);
        // 顯示
        this.setVisible(true);
        // 退出窗體后將JFrame同時(shí)關(guān)閉
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

??5、 GroupLayout(分組布局) ,它將組件按層次分組,以決定它們?cè)?Container 中的位置。GroupLayout 主要供生成器使用,但也可以手工編碼。分組由 Group 類的實(shí)例來完成。GroupLayout 支持兩種組。串行組 (sequential group) 按順序一個(gè)接一個(gè)地放置其子元素。并行組 (parallel group)能夠以四種方式對(duì)齊其子元素。
??每個(gè)組可以包含任意數(shù)量的元素,其中元素有 Group、Component 或間隙 (gap)。間隙可被視為一個(gè)具有最小大小、首選大小和最大大小的不可見組件。此外,GroupLayout 還支持其值取自 LayoutStyle 的首選間隙。
??GroupLayout是一個(gè)很重要的布局管理器,在jdk 1.6才加入,配合其它的管理器可以實(shí)現(xiàn)很好的界面。GroupLayout必須要設(shè)置它的GroupLayout.setHorizontalGroup和GroupLayout.setVerticalGroup。
??GroupLayout.setHorizontalGroup是指按照水平來確定,下面例子“賬號(hào)”和“密碼”是一個(gè)級(jí)別的,其它的組件也是一個(gè)級(jí)別的。
??GroupLayout.setVerticalGroup。是按照垂直來確定的。他們的級(jí)別是按照Group去設(shè)置組件的優(yōu)先級(jí)別,級(jí)別越高就顯示越上面。

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

public class GroupLayoutTest extends JFrame {
    private static final long serialVersionUID = -5159330521192113057L;

    public static void main(String[] args) {
        new GroupLayoutTest();
    }

    JLabel label1;
    JLabel label2;
    JLabel label3;
    JTextField tf;
    JPasswordField psf;
    JRadioButton rb1;
    JRadioButton rb2;
    JButton bt1;
    JButton bt2;

    public GroupLayoutTest() {
        this.setVisible(true);
        this.setSize(250, 220);
        this.setVisible(true);
        this.setLocation(400, 200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        label1 = new JLabel("登陸界面");
        label2 = new JLabel("賬號(hào):");
        label3 = new JLabel("密碼:");
        tf = new JTextField();
        psf = new JPasswordField();
        rb1 = new JRadioButton("記住密碼");
        rb2 = new JRadioButton("自動(dòng)登陸");
        bt1 = new JButton("登陸");
        
        // 為指定的 Container 創(chuàng)建 GroupLayout
        GroupLayout layout = new GroupLayout(this.getContentPane());
        this.getContentPane().setLayout(layout);
        
        // 創(chuàng)建GroupLayout的水平連續(xù)組,,越先加入的ParallelGroup,優(yōu)先級(jí)級(jí)別越高。
        GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
        // 添加間隔
        hGroup.addGap(5);
        hGroup.addGroup(layout.createParallelGroup().addComponent(label2).addComponent(label3));
        hGroup.addGap(5);
        hGroup.addGroup(layout.createParallelGroup().addComponent(label1).addComponent(psf).addComponent(rb1)
                .addComponent(rb2).addComponent(tf).addComponent(bt1));
        hGroup.addGap(5);
        // 設(shè)置水平分組
        layout.setHorizontalGroup(hGroup);
        
        // 創(chuàng)建GroupLayout的垂直連續(xù)組,,越先加入的ParallelGroup,優(yōu)先級(jí)級(jí)別越高。
        GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
        vGroup.addGap(10);
        vGroup.addGroup(layout.createParallelGroup().addComponent(label1));
        vGroup.addGap(10);
        vGroup.addGroup(layout.createParallelGroup().addComponent(label2).addComponent(tf));
        vGroup.addGap(5);
        vGroup.addGroup(layout.createParallelGroup().addComponent(label3).addComponent(psf));
        vGroup.addGroup(layout.createParallelGroup().addComponent(rb1));
        vGroup.addGroup(layout.createParallelGroup().addComponent(rb2));
        vGroup.addGroup(layout.createParallelGroup(Alignment.TRAILING).addComponent(bt1));
        vGroup.addGap(10);
        // 設(shè)置垂直組
        layout.setVerticalGroup(vGroup);
    }

}



三、Java繪圖技術(shù)

?? 坐標(biāo)原點(diǎn)位于左上角,以像素為單位。像素是計(jì)算機(jī)屏幕上最小的顯示單位。 在java的坐標(biāo)系中,第一個(gè)是X坐標(biāo),表示當(dāng)前位置為水平方向,距離坐標(biāo)原點(diǎn)X個(gè)像素;第二個(gè)是Y坐標(biāo),表示當(dāng)前位置為垂直方向,距離坐標(biāo)原點(diǎn)Y個(gè)像素。


?? 計(jì)算機(jī)在屏幕上顯示的內(nèi)容都是由屏幕上的每一個(gè)像素組成的。 例如,計(jì)算機(jī)顯示器的分辨率是800×600,表示計(jì)算機(jī)屏幕上的每一行由800個(gè)點(diǎn)組成,共有600行,整個(gè)計(jì)算機(jī)屏幕共有480000個(gè)像素?,F(xiàn)在的計(jì)算機(jī)可以支持更高的分辨率,也就是說,屏幕上可以顯示更多的像素。因此, 像素是一個(gè)密度單位,而厘米是長(zhǎng)度單位,兩者無法比較。
??Component類提供了兩個(gè)和繪圖相關(guān)最重要的方法:
??1、paint(Graphics g)繪制組件的外觀;
??2、repaint()刷新組件的外觀。
??當(dāng)組件第一次在屏幕顯示的時(shí)候,程序會(huì)自動(dòng)的調(diào)用paint()方法來繪制組件,在以下情況paint()將會(huì)被調(diào)用:
??1、窗口最小化,再最大化;
??2、窗口的大小發(fā)生變化;
??3、repaint函數(shù)被調(diào)用。

1、Graphics類

??Graphics類可以理解就是畫筆,為我們提供了各種繪制圖形的方法:
??1、畫直線 drawLine(int x1, int y1, int x2, int y2);
??2、畫矩形邊框 drawRect(int x, int y, int width, int height);
??3、畫橢圓邊框 drawOval(int x, int y, int width, int height);
??4、填充矩形 fillRect(int x, int y, int width, int height);
??5、填充橢圓 fillOval(int x, int y, int width, int height);
??6、畫圖片 drawImage(Image img, int x, int y,..);
??7、畫字符串 drawString(String str, int x, int y);
??8、設(shè)置畫筆的字體 setFont(Font font);
??9、設(shè)置畫筆的顏色 setColor(Color c);

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GraphicsTest extends JFrame {
    // 定義組件
    MyPanel1 mp = null;
    public static void main(String[] args) {
        new GraphicsTest();
    }

    public GraphicsTest() {
        // 構(gòu)建組件
        mp = new MyPanel1();
        // 加入組件
        this.add(mp);
        
        // 設(shè)置窗體
        this.setSize(400, 300);
        this.setVisible(true);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

/**
 * @Description: 定義一個(gè)MyPanel(我自己的面板是用于繪圖和顯示繪圖的區(qū)域)
 */
class MyPanel1 extends JPanel {
    private static final long serialVersionUID = 1L;

    // 重寫(覆蓋)JPanel的paint方法
    public void paint(Graphics g) {
        // 1、調(diào)用父類函數(shù),完成初始化任務(wù)
        super.paint(g);
        // 畫一個(gè)直線
        g.drawLine(10, 10, 40, 10);
        // 畫矩形邊框
        g.drawRect(50, 50, 40, 40);
        // 畫橢圓邊框
        g.drawOval(130, 130, 60, 60);
        // 畫填充矩形
        g.setColor(Color.blue);
        g.fillRect(10, 150, 70, 70);
        
        // 畫填充橢圓
        // 設(shè)置畫筆顏色
        g.setColor(Color.red);
        g.fillOval(270, 140, 100, 80);

        // 如何畫出字
        g.setColor(Color.red);
        g.setFont(new Font("黑體", Font.BOLD, 40));
        g.drawString("祖國(guó)萬歲", 150, 100);
        // 畫弧形
        g.drawArc(100, 100, 120, 200, 50, 100);
    }
}



2、Graphics2D類

??Java語言在Graphics類提供繪制各種基本的幾何圖形的基礎(chǔ)上,擴(kuò)展Graphics類提供一個(gè)Graphics2D類,它擁用更強(qiáng)大的二維圖形處理能力,提供、坐標(biāo)轉(zhuǎn)換、顏色管理以及文字布局等更精確的控制。
??繪圖屬性
??Graphics2D定義了幾種方法,用于添加或改變圖形的狀態(tài)屬性??梢酝ㄟ^設(shè)定和修改狀態(tài)屬性,指定畫筆寬度和畫筆的連接方式;設(shè)定平移、旋轉(zhuǎn)、縮放或修剪變換圖形;以及設(shè)定填充圖形的顏色和圖案等。圖形狀態(tài)屬性用特定的對(duì)象存儲(chǔ)。

2.1、stroke屬性

??stroke屬性控制線條的寬度、筆形樣式、線段連接方式或短劃線圖案。該屬性的設(shè)置需要先創(chuàng)建BasicStroke對(duì)象,再調(diào)用setStroke()方法來設(shè)置。創(chuàng)建BasicStroke對(duì)象的方法有:
??BasicStroke(float w):指定線條寬w。
??BasicStroke(float w, int cap, int join):
??cap是端點(diǎn)樣:CAP_BUTT(無修飾),CAP_ROUND(半圓形末端),CAP_SQUARE(方形末端,默認(rèn)值)。
??Join定義兩線段交匯處的連接方式:JOIN_BEVEL(無修飾),JOIN_MTTER(尖形末端,默認(rèn)值),JOIN_ROUND(圓形末端)。

2.2、paint屬性

??paint屬性控制填充效果。先調(diào)用以下方法確定填充效果,理用setPaint()方法設(shè)置。
??GradientPaint(float x1, float y1, Color c1, float x2, flaot y2, Color c2):從(x1, y1)到(x2, y2)顏色從c1漸變到c2。其中:參數(shù)c1, c2決定這個(gè)漸變色是從顏色c1漸變到顏色c2。參數(shù)x1, y1, x2, y2決定了漸變的強(qiáng)弱,即要求從點(diǎn)(x1, y1)出發(fā)到達(dá)點(diǎn)(x2, y2),顏色從c1變成c2。
??GradientPaint(float x1, float y1, Color c1, float x2, float y2, Color c2, Boolean cyclic):如果希望漸變到終點(diǎn)又是起點(diǎn)的顏色,應(yīng)將cyclic設(shè)置為true。

2.3、transform屬性

??transform 屬性用來實(shí)現(xiàn)常用的圖形平移、縮放和斜切等變換操作。首先創(chuàng)建AffineTransform對(duì)象,然后調(diào)用setTransform()方法設(shè)置transform屬性。最后,用具有指定屬性的Graphics2D對(duì)象繪制圖形。創(chuàng)建AffineTransform對(duì)象的方法有:
??getRotateinstrance(double theta):旋轉(zhuǎn)theta弧度。
??getRotateInstance(double theta, dioble x, double y):繞旋轉(zhuǎn)中心(x, y)旋轉(zhuǎn)。
??getScaleInstance(double sx, double sy):x和y 方向分別按sx, sy比例變換。
??getTranslateInstance(double tx, double ty):平移變換。
??getShearInstance(double shx, double shy):斜切變換,shx和shy指定斜拉度。
??也可以先創(chuàng)建一個(gè)沒有transform屬性的AffineTransform對(duì)象,然后用以下方法指定圖形平移、旋轉(zhuǎn)、縮放變換屬性。
??transelate(double dx, double dy):將圖形在x軸方向平移dx像素。
??scale(double sx, double sy):圖形在x軸方向縮放sx倍,縱向縮放sy倍。
??rotate(double arc, double x, double y):圖形以點(diǎn)(x, y)為軸點(diǎn),旋轉(zhuǎn)arc弧度。
??例如,創(chuàng)建AffineTransform對(duì)象:
??AffineTransform trans = new AffineTransform();
??為AffineTransform對(duì)象指定繞點(diǎn)旋轉(zhuǎn)變換屬性:
??Trans.rotate(50.0*3.1415927/180.0,90,80);
??接著為Graphics2D 的對(duì)象g2d設(shè)置具有上述旋轉(zhuǎn)變換功能的“畫筆”:
??Graphics2D g2d = (Graphics2D)g; g2d.setTranstorm(trans);
??最后,以圖形對(duì)象為參數(shù)調(diào)用具有變換功能的Graphics2D 對(duì)象的draw()方法。例如,設(shè)已有一個(gè)二次曲線對(duì)象curve,以下代碼實(shí)現(xiàn)用上述旋轉(zhuǎn)功能的g2d對(duì)象繪制這條二次曲線:
??g2d.draw(curve);

2.4、clip屬性

??clip屬性用于實(shí)現(xiàn)剪裁效果。設(shè)置剪裁屬性可調(diào)用setClip()方法確定剪裁區(qū)的Shape。連續(xù)多個(gè)setClip()得到它們交集的剪裁區(qū)。

2.5、composit屬性

??composit屬性設(shè)置圖形重疊區(qū)域的效果。先用方法AlphaComposite.getInstance(int rule, float alpha)得到AlphaComposite對(duì)象,再通過setComposite()方法設(shè)置混合效果。Alpha值的范圍為0.0f(完全透明)-0.1f(完全不透明)。

2.6、Graphics2D類的繪圖方法

??Graphics2D類仍然保留Graphics類的繪圖方法,同時(shí)增加了許多新方法。新方法將幾何圖形(線段、圓等)作為一個(gè)對(duì)象來繪制。在java.awt.geom包中聲明的一系列類,分別用于創(chuàng)建各種身體圖形對(duì)象。主要有:
??Line2D線段類,RoundRectangle2D圓角矩形類,Ellipse2D橢圓類,Arc2D圓弧類,QuadCurve2D二次曲線類,CubicCurve2D三次曲線類。
??要用Graphics2D類的新方法畫一個(gè)圖形。先在重畫方法paintComponent()或paint()中,把參數(shù)對(duì)象g強(qiáng)制轉(zhuǎn)換成Graphics2D對(duì)象;然后,用上述圖形類提供的靜態(tài)方法Double()創(chuàng)建該圖形的對(duì)象;最后,以圖形對(duì)象為參數(shù)調(diào)用Graphics2D對(duì)象的draw()方法繪制這個(gè)圖形。例如以下代碼用Graphics2D的新方法繪制線段和圓角矩形:
??// 將對(duì)象g類型從Graphics轉(zhuǎn)換成Graphics2D
??Graphics2D g2d = (Graphics2D)g;
??Line2D line = new Line2D.Double(30.0, 30.0, 340.0, 30.0);
??g2d.draw(line);
??RoundRectangle2D rRect = new RoundRectangle2D.Double(13.0, 30.0, 100.0, 70.0, 40.0, 20.0);
??g2d.draw(rRect);
??也可以先用java.awt.geom包提供的Shape對(duì)象,并用單精度Float坐標(biāo)或雙精度Double坐標(biāo)創(chuàng)建Shape對(duì)象,然后再用draw()方法繪制。例如,以下代碼先創(chuàng)建圓弧對(duì)象,然后繪制圓弧:
??Shape arc = new Arc2D.Float(30, 30, 150, 150, 40, 100, Arc2D.OPEN);
??g2d.draw(arc); //繪制前面創(chuàng)建的圖形對(duì)象arc.

??Graphics2D的幾何圖形類
??1、線段:
??// 聲明并創(chuàng)建線段對(duì)象(起點(diǎn)是(2,3),終點(diǎn)是(200,300))
??Line2D line = new Line2D.Double(2,3,200,300);
??2、矩形:
??// 聲明并創(chuàng)建矩形對(duì)象,矩形的左上角是(20,30),寬是300,高是40。
??Rectangle2D rect = new Rectangle2D.Double(20, 30, 80, 40);
??3、圓角矩形:
??// 左上角是(20,30),寬是130,高是100,圓角的長(zhǎng)軸是18,短軸是15。
??RoundRectangle2D rectRound = new RoundRectangle2D.Double(20, 30, 130, 100, 18, 15);
??4、橢圓:
??// 左上角 (20,30),寬是100,高是50
??Ellipse2D ellipse = new Ellipse2D.Double(20, 30, 100, 50);
??5、圓弧:
??// 外接矩形的左上角(10,30),寬85,高60,起始角是5度,終止角是90度。
??Arc2D arc1 = new Arc2D.Double(10, 30, 85, 60, 5, 90, Arc2D.OPEN);
??Arc2D arc2 = new Arc2D.Double(20,65,90,70,0,180,Arc2D.CHORD);
??Arc2D arc3 = new Arc2D.Double(40,110,50,90,0,270,Arc2D.PIE);
??// 參數(shù)Arc2D.OPEN、Arc2D.CHORD、Arc2D.PIE分別表示圓弧是開弧、弓弧和餅弧。
??6、二次曲線:
??二次曲線用二階多項(xiàng)式表示:y(x) = ax2+bx+c。一條二次曲線需要三個(gè)點(diǎn)確定:始點(diǎn)、控制點(diǎn)和終點(diǎn)。
??QuadCurve2D curve1 = new QuadCurver2D.Double(20,10,90,65,55,115);
??QuadCurve2D curve2 = new QuadCurver2D.Double(20,10,15,63,55,115);
??QuadCurve2D curve3 = new QuadCurver2D.Double(20,10,54,64,55,115);
??// 方法Double()中的6個(gè)參數(shù)分別是二次曲線的始點(diǎn)、控制點(diǎn)和終點(diǎn)。以上3條二次曲線的開始點(diǎn)和終點(diǎn)分別相同。
??7、三次曲線:
??三次曲線用三階多項(xiàng)式表示:y(x)=ax3+bx2+cx+d。一條三次曲線需要四個(gè)點(diǎn)確定:始點(diǎn)、兩個(gè)控制點(diǎn)和終點(diǎn)。
??CubicCurve2D curve1 = new CubicCurve2D.Double(12,30,50,75,15,15,115,93);
??CubicCurve2D curve2 = new CubicCurve2D.Double(12,30,15,70,20,25,35,94);
??CubicCurve2D curve3 = new CubicCurve2D.Double(12,30,50,75,20,95,95,95);
??方法Double()中的8個(gè)參數(shù)分別是三次曲線的始點(diǎn)、兩個(gè)控制點(diǎn)和終點(diǎn)。


??一般的方程曲線的繪制過程用一個(gè)循環(huán)控制。通過循環(huán)產(chǎn)生自變量的值,按照方程計(jì)算出函數(shù)值,再作必要的坐標(biāo)轉(zhuǎn)換:原點(diǎn)定位的平移變換,圖像縮小或放大的縮放變換,得到曲線的圖像點(diǎn),并繪制這個(gè)點(diǎn)。以繪制以下曲線方程為例:
??Y=sin(x)+cos(x)
繪制的部分代碼可以寫成如下:

double x0, y0, x1, y1, x2, y2, scale;
x0 = 100; y0 = 80;
scale = 20.0;
for(x1 = -3.1415926d; x1 <= 2*3.1415926d; x1 += 0.01d) {
    y1 = Math.sin(x1) + Math.cos(x1);
    x2 = x0 + x1 * scale; y2 = y0 + y1 * scale; //(x2,y2)是圖像點(diǎn)
    g.fillOval((int)x2, (int)y2, 1, 1); // 畫一個(gè)圓點(diǎn)作為圖像點(diǎn)
}


四、事件處理機(jī)制

??Java事件處理是采取“委派事件模型”。所謂“委派事件模型”是指當(dāng)事件發(fā)生時(shí),產(chǎn)生事件的對(duì)象(即事件源),會(huì)把此“信息”傳遞給“事件的監(jiān)聽者”處理的一種方式,而這里所說的“信息”實(shí)際上就是java.awt.event事件類庫里的某個(gè)類所創(chuàng)建的對(duì)象。我們暫時(shí)把它稱為“事件的對(duì)象”。


??1、事件源(event source)
??事件源是一個(gè)產(chǎn)生(或觸發(fā))事件的對(duì)象,如文本框、按鈕等。當(dāng)這個(gè)事件源對(duì)象的某些狀態(tài)以某種方式發(fā)生變化時(shí),就會(huì)產(chǎn)生某種類型的事件(一個(gè)事件源可能會(huì)生成多個(gè)不同類型的事件)。如果某個(gè)組件(對(duì)象)希望得到事件源產(chǎn)生的事件,就需要在這個(gè)事件源上注冊(cè),一個(gè)事件源是一個(gè)能夠注冊(cè)監(jiān)聽器并且為它們發(fā)送事件對(duì)象的對(duì)象。
??2、事件(event object)
事件就是承載事件源狀態(tài)改變時(shí)的信息對(duì)象?;蛘哒f,事件是事件源事件監(jiān)聽器傳輸事件源狀態(tài)信息的載體。在用戶與GUI組件進(jìn)行交互時(shí)就會(huì)生成事件,比如當(dāng)鼠標(biāo)在面板中移動(dòng)時(shí),就會(huì)生成一個(gè)鼠標(biāo)移動(dòng)事件的對(duì)象,而這個(gè)對(duì)象保存著當(dāng)前鼠標(biāo)在面板中位置信息。java.awt.event包和javax.swing.event包中定義了各種事件類型,常見的事件類有:

事件類 說明
ActionEvent 通常在按下按鈕,或雙擊一個(gè)列表項(xiàng)或選中某個(gè)菜單時(shí)發(fā)生
AdjustmentEvnet 當(dāng)操作一個(gè)滾動(dòng)條時(shí)發(fā)生
ComponentEvent 當(dāng)一個(gè)組件隱藏、移動(dòng)、改變大小時(shí)發(fā)送
ContainerEvent 當(dāng)一個(gè)組件從容器中加入或者刪除時(shí)發(fā)生
FocusEvent 當(dāng)一個(gè)組件獲得或是失去焦點(diǎn)時(shí)發(fā)生
ItemEvent 當(dāng)一個(gè)復(fù)選框或是列表項(xiàng)被選中時(shí),當(dāng)一個(gè)選擇框或選擇菜單被選中
KeyEvent 當(dāng)從鍵盤的按鍵被按下,松開時(shí)發(fā)生
MouseEvent 當(dāng)鼠標(biāo)被拖動(dòng)、移動(dòng)、點(diǎn)擊、按下..
TextEvent 當(dāng)文本區(qū)和文本域的文本發(fā)生改變時(shí)發(fā)生
WindowEvent 當(dāng)一個(gè)窗口激活、關(guān)閉、失效、恢復(fù)、最小化...

??3、事件監(jiān)聽器接口
??事件源產(chǎn)生一個(gè)事件,可以傳送給事件監(jiān)聽者處理,那么怎樣才能編寫一個(gè)事件監(jiān)聽者呢?
??事件監(jiān)聽者實(shí)際上就是一個(gè)類,該類實(shí)現(xiàn)了某個(gè)事件監(jiān)聽器接口,它就可以作為一個(gè)事件監(jiān)聽者,對(duì)接受到的事件進(jìn)行處理。
??事件監(jiān)聽器接口有多種,不同的事件監(jiān)聽器接口可以監(jiān)聽不同的事件,一個(gè)類可以實(shí)現(xiàn)一個(gè)事件監(jiān)聽接口,也可以實(shí)現(xiàn)多個(gè)監(jiān)聽接口,這些接口在java.awt.event和javax.swing.event包中定義。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容