日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java图形化界面编程之——AWT

發(fā)布時間:2023/12/29 java 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java图形化界面编程之——AWT 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

1、AWT簡介

2、AWT繼承體系

3、Container容器

3.1、Container繼承體系

3.2、常用API

3.2.1、Component的常用方法

3.2.2、Container的常用方法

3.3、容器演示

3.3.1、Window

3.3.2、Panel

3.3.3、ScrollPane

4、LayoutManager布局管理器

4.1、FlowLayout(流式布局)

4.2、BorderLayout(邊框布局)

4.3、GridLayout(網(wǎng)格布局)

4.4、GridBagLayout(網(wǎng)格包布局)

4.5、CardLayout(卡片布局)

4.6、BoxLayout(盒子布局)

4.6.1、Box容器

5、AWT中常用組件

5.1、基本組件

5.2、Dialog(對話框)

5.2.1、FileDialog(文件對話框)

6、事件處理

6.1、GUI事件處理機制

6.2、GUI中常見事件和事件監(jiān)聽器

6.2.1、事件

6.2.2、事件監(jiān)聽器

6.2.3、案例

7、菜單組件

8、繪圖

8.1、組件繪圖原理

8.2、Graphics對象的使用

8.3、處理位圖

8.4、ImageIO的使用


1、AWT簡介

AWT的全稱是抽象窗口工具集(Abstract Window Toolkit),它是sun公司最早提供的GUI庫,這個GUI類庫希望可以在所有平臺下都能運行,它為Java應(yīng)用程序提供了基本的圖形組件,但這個GUI庫的功能比較有限,所以后來sun公司又提供了Swing庫。通過使用AWT和Swing提供的圖形化界面組件庫,java的圖形化界面編程非常簡單,程序只需要依次創(chuàng)建所需的圖形組件,并以合適的方式將這些組件組織在一起,就可以開發(fā)出非常美觀的用戶界面。

AWT是窗口框架,它從不同平臺的窗口系統(tǒng)中抽取出共同組件,當(dāng)程序運行時,將這些組件的創(chuàng)建和動作委托給程序所在的運行平臺。簡而言之,當(dāng)使用AWT編寫圖形界面應(yīng)用時,程序僅制定了界面組件的位置和行為,并為提供真正的實現(xiàn),JVM調(diào)用操作系統(tǒng)本地的圖形界面來創(chuàng)建和平臺一致的對等體。

使用AWT創(chuàng)建的圖形界面應(yīng)用和所在的運行平臺有相同的界面風(fēng)格,比如在Windows操作系統(tǒng)上,它就表現(xiàn)出Windows風(fēng)格;在UNIX操作系統(tǒng)上,它就表現(xiàn)出UNIX風(fēng)格。Sun希望采用這種方式來實現(xiàn)“Write Once,Run Anywhere”的目標(biāo)。

2、AWT繼承體系

AWT繼承體系

所有和AWT編程相關(guān)的類都放在java.awt包以及它的子包中。AWT編程中有兩個基類:Component和MenuComponent:

  • Component:代表一個能以圖形化方式顯式出來,并可與用戶交互的對象。
  • MenuComponent:代表圖形界面的菜單組件,包括MenuBar(菜單條)、MenuItem(菜單項)等子類。

其中Container是一種特殊的Component,它代表一種容器,可以盛裝普通的Component。

AWT中還有一個非常重要的接口叫LayoutManager,如果一個容器中有多個組件,那么容器就需要使用LayoutManager來管理這些組件的布局方式。

接口LayoutManager:

  • GridLayout
  • FlowLayout
  • ...

3、Container容器

3.1、Container繼承體系

Container容器:

??????? 1、Window窗口容器:

??????????????? Frame:創(chuàng)建窗口

??????????????? Dialog:創(chuàng)建對話框

??????? 2、Panel內(nèi)嵌容器:

??????????????? Applet

??????? 3、ScrollPane含有滾動條的容器

  • Window是可以獨立存在的頂級窗口,默認使用BorderLayout管理其內(nèi)部組件布局;
  • Panel可以容納其他組件,但不能獨立存在,它必須內(nèi)嵌其他容器中使用,默認使用FlowLayout管理其內(nèi)部組件布局;
  • ScrollPane是一個帶滾動條的容器,它也不能獨立存在,默認使用BorderLayout管理其內(nèi)部組件布局。

3.2、常用API

3.2.1、Component的常用方法

Component作為基類,提供了如下常用的方法來設(shè)置組件的大小、位置、可見性等。

方法簽名方法功能
setLocation(int x, int y)設(shè)置i組件的位置
setSize(int width, int height)設(shè)置組件的大小
setBounds(int x, int y, int width, int height)同時設(shè)置組件的位置、大小
setVisible(Boolean b)設(shè)置該組件的可見性

3.2.2、Container的常用方法

方法簽名方法功能
Component add(Component comp)向容器中添加其他組件(該組件既可以是普通組件,也可以是容器),并返回被添加的組件
Component getComponentAt(int x, int y)返回指定點的組件
int getComponentCount()返回該容器內(nèi)組件的數(shù)量
Component[] getComponent()返回該容器內(nèi)的所有組件

3.3、容器演示

3.3.1、Window

package Package1;import java.awt.*;public class FrameDemo {public static void main(String[] args) {//1、創(chuàng)建窗口對象Frame frame = new Frame("這是一個窗口容器Frame");//2、設(shè)置窗口的位置和大小frame.setLocation(100,100); //單位是像素frame.setSize(500,300); //單位是像素//3、設(shè)置窗口對象可見frame.setVisible(true);} }

3.3.2、Panel

package Package1;import java.awt.*;public class PanelDemo {public static void main(String[] args) {//1、創(chuàng)建一個Window對象,因為Panel以及其它的容器,都不能獨立存在,必須依附于Window存在Frame frame = new Frame("這是一個窗口容器Frame");//2、創(chuàng)建一個Panel對象Panel p = new Panel();//3、創(chuàng)建一個文本框和一個按鈕,并且把它們放入Panel容器中p.add(new TextField("這是一個測試文本"));p.add(new Button("這是一個測試按鈕"));//4、把Panel放入Window中frame.add(p);//5、設(shè)置Window的位置和大小frame.setBounds(400,200,500,300);//6、設(shè)置Window可見frame.setVisible(true);} }

按鈕文本顯示亂碼解決辦法:依次點擊Run -> Edit Configurations -> 左邊選中要修改的項 -> 在右側(cè)找到并點擊Modify options -> 點擊Add VM options -> 在新出現(xiàn)的框中輸入 -Dfile.encoding=gbk -> 點擊OK 。

3.3.3、ScrollPane

package Package1;import java.awt.*;public class ScrollPaneDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//創(chuàng)建一個ScrollPane對象ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);sp.add(new TextField("這是測試文本"));sp.add(new Button("這是測試按鈕"));//把ScrollPane添加到Frame中frame.add(sp);//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

程序明明向ScrollPane中添加了一個文本框和一個按鈕,但只能看到一個按鈕,卻看不到文本框,這是因為ScrollPane使用BorderLayout布局管理器的緣故,BorderLayout導(dǎo)致了該容器中只有一個組件被顯示出來。

4、LayoutManager布局管理器

如果要讓我們的程序在不同的操作系統(tǒng)下,都有相同的體驗,那么手動設(shè)置組件的位置和大小,無疑是一種災(zāi)難,因為有太多的組件,需要分別設(shè)置不同操作系統(tǒng)下的大小和位置。為了解決這個問題,Java提供了LayoutManager布局管理器,可以根據(jù)運行平臺來自動調(diào)整組件大小,程序員不用再手動設(shè)置組件大小和位置了,只需要為容器選擇合適的布局管理器即可。

AWT中接口LayoutManager有五個實現(xiàn)類:GridLayout(網(wǎng)格布局)、FlowLayout(流式布局)、CardLayout(卡片布局)、GridBagLayout(網(wǎng)格包布局)和BorderLayout(邊框布局)。為了簡化開發(fā),Swing引入了一個新的布局管理器BoxLayout。

4.1、FlowLayout(流式布局)

在FlowLayout布局管理器中,組件像水流一樣向某方向流動(排列),遇到障礙(邊界)就折回,中心開始排列。在默認情況下,FlowLayout布局管理器從左向右排列所有組件,遇到邊界就會折回下一行重新開始。

構(gòu)造方法方法功能
FlowLayout()使用默認的對齊方式及默認的垂直間距、水平間距創(chuàng)建FlowLayout布局管理器
FlowLayout(int align)使用指定的對齊方式及默認的垂直間距、水平間距創(chuàng)建FlowLayout布局管理器
FlowLayout(int align, int hgap, int vgap)使用指定的對齊方式及指定的垂直間距、水平間距創(chuàng)建FlowLayout布局管理器

FlowLayout中組件的排列方向(從左向右、從右向左、從中間向兩邊等),該參數(shù)應(yīng)該使用FlowLayout類的靜態(tài)常量:FlowLayout.LEFT、FlowLayout.CENTER、FlowLayout.RIGHT。默認是左對齊。

FlowLayout中組件中間距通過整數(shù)設(shè)置,單位是像素,默認是5個像素。

代碼演示:

package Package1;import java.awt.*;public class FlowLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//通過setLayout()方法設(shè)置容器的布局管理器frame.setLayout(new FlowLayout(FlowLayout.LEFT,20,20));//添加多個按鈕到frame中for (int i = 0; i < 10; i++) {frame.add(new Button("按鈕"+i));}//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

4.2、BorderLayout(邊框布局)

BorderLayout將容器分為EAST、SOUTH、WEST、CENTER五個區(qū)域,普通組件可以被放置在這5個區(qū)域的任意一個中。

?當(dāng)改變使用BorderLayout的容器大小時,NORTH、SOUTH和CENTER區(qū)域水平調(diào)整,而EAST、WEST和CENTER區(qū)域垂直調(diào)整,使用BorderLayout有如下兩個注意點:

  • 當(dāng)向使用BorderLayout布局的容器中添加組件時,需要指定要添加到哪個區(qū)域中。如果沒有指定添加到哪個區(qū)域中,則默認添加到中間區(qū)域中;
  • 如果向同一個區(qū)域中添加多個組件,后放入的組件會覆蓋先放入的組件。
構(gòu)造方法方法功能
BorderLayout()使用默認的水平間距、垂直間距創(chuàng)建BorderLayout布局管理器
BorderLayout(int hgap, int vgap)使用指定的水平間距、垂直間距創(chuàng)建BorderLayout布局管理器

代碼演示:

package Package1;import java.awt.*;public class BorderLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//通過setLayout()方法設(shè)置容器的布局管理器frame.setLayout(new BorderLayout(30,10));//往frame的指定區(qū)域添加組件frame.add(new Button("北側(cè)按鈕"),BorderLayout.NORTH);frame.add(new Button("南側(cè)按鈕"),BorderLayout.SOUTH);frame.add(new Button("東側(cè)按鈕"),BorderLayout.EAST);frame.add(new Button("西側(cè)按鈕"),BorderLayout.WEST);frame.add(new Button("中間按鈕"),BorderLayout.CENTER);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

4.3、GridLayout(網(wǎng)格布局)

GridLayout布局管理器將容器分割成縱橫線分隔的網(wǎng)格,每個網(wǎng)格所占的區(qū)域大小相同。當(dāng)向使用GridLayout布局管理器的容器中添加組件時,默認從左到右、從上到下依次添加到每個網(wǎng)格中。與FlowLayout不同的是,放置在GridLayout布局管理器中的各組件的大小由組件所處的區(qū)域決定(每個組件將自動占滿整個區(qū)域)。

構(gòu)造方法方法功能
GridLayout(int rows, int cols)采用指定的行數(shù)、列數(shù),以及默認的橫向間距、縱向間距將容器分割成多個網(wǎng)格。
GridLayout(int rows, int cols, int hgap, int vgap)采用指定的行數(shù)、列數(shù),以及指定的橫向間距、縱向間距將容器分割成多個網(wǎng)格。

代碼演示:

package Package1;import java.awt.*;public class GridLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//通過setLayout()方法設(shè)置容器的布局管理器frame.setLayout(new BorderLayout());//創(chuàng)建一個Panel對象,里面存放一個TextField組件Panel p1 = new Panel();p1.add(new TextField(50));//把這個Panel添加到frame的北邊區(qū)域frame.add(p1,BorderLayout.NORTH);//創(chuàng)建一個Panel對象,并且設(shè)置它的布局管理器為GridLayoutPanel p2 = new Panel();p2.setLayout(new GridLayout(3,5,4,4));//往Panel中添加內(nèi)容for (int i = 0; i < 10; i++) {p2.add(new Button(i+""));}p2.add(new Button("+"));p2.add(new Button("-"));p2.add(new Button("*"));p2.add(new Button("/"));p2.add(new Button("."));//把當(dāng)前的Panel添加到frame中frame.add(p2,BorderLayout.CENTER);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(500,200,400,250);//設(shè)置Frame可見frame.setVisible(true);} }

4.4、GridBagLayout(網(wǎng)格包布局)

GridBagLayout布局管理器的功能最強大,但也最復(fù)雜,與GirdLayout布局管理器不同的是,在GridBagLayout布局管理器中,一個組件可以跨越一個或多個網(wǎng)格,并且可以設(shè)置網(wǎng)格的大小互不相同,從而增加了布局的靈活性。當(dāng)窗口的大小發(fā)生變化時,GridBagLayout布局管理器也可以準(zhǔn)確地控制窗口各部分的拉伸。

由于在GirdBagLayout布局中,每個組件可以占用多個網(wǎng)格,此時,我們往容器中添加組件的時候,就需要具體地控制每個組件占用多少個網(wǎng)格,java提供的GridBagConstraints類,與特定的組件綁定,可以完成具體大小和跨越性的設(shè)置。

GirdBagConstraints API:

變量和類型字段描述
static intBOTH水平和垂直調(diào)整組件大小
static intCENTER將組件放在其顯示區(qū)域的中心
static intEAST將組件放在顯示區(qū)域的右側(cè),垂直居中
static intREMAINDER指定此組件是其列或行中的最后一個組件
intgridheight指定組件顯示區(qū)域的列中的單元格數(shù)
intgridwidth指定組件顯示區(qū)域的行中單元格數(shù)
intgridx指定包含組件顯示區(qū)域前沿的單元格,其中一行中的第一個單元格具有g(shù)ridx=0
intgridy指定組件顯示區(qū)域頂部的單元格,其中最頂層的單元格為gridy=0
doubleweightx指定如何分配額外的水平空間
doubleweighty指定如何分配額外的垂直空間

代碼演示:

package Package1;import java.awt.*;public class GirdBagLayoutDemo {public static void main(String[] args) {//創(chuàng)建Frame對象Frame frame = new Frame("這是一個窗口容器Frame");//創(chuàng)建GridBagLayout對象GridBagLayout gbLayout = new GridBagLayout();//把Frame對象的布局管理器設(shè)置為GridBagLayoutframe.setLayout(gbLayout);//創(chuàng)建GridBagConstraints對象GridBagConstraints gbCon = new GridBagConstraints();/*設(shè)置所有的GridBagConstraints對象的fill屬性為GridBagConstraints.BOTH。當(dāng)有空白區(qū)域時,組件自動擴大占滿空白區(qū)域*/gbCon.fill = GridBagConstraints.BOTH;//設(shè)置GridBagConstraints對象的weightx設(shè)置為1,表示橫向擴展比例為1gbCon.weightx = 1;//把GridBagConstraints的weighty設(shè)置為1,表示縱向擴展比例為1gbCon.weighty = 1;//創(chuàng)建容量為10的Button數(shù)組并初始化Button[] btns = new Button[10];for (int i = 0; i < btns.length; i++) {btns[i] = new Button("按鈕"+i);}//往frame中添加數(shù)組中的第0,1,2個ButtonaddComponent(frame,btns[0],gbLayout,gbCon);addComponent(frame,btns[1],gbLayout,gbCon);addComponent(frame,btns[2],gbLayout,gbCon);//把GridBagConstraints的gridwidth設(shè)置為GridBagConstraints.REMAINDER,表明當(dāng)前組件是橫向最后一個組件gbCon.gridwidth = GridBagConstraints.REMAINDER;//把Button數(shù)組中第3個按鈕添加到frame中addComponent(frame,btns[3],gbLayout,gbCon);//把Button數(shù)組中第4個按鈕添加到frame中addComponent(frame,btns[4],gbLayout,gbCon);//把GridBagConstraints的gridheight和gridwidth設(shè)置為2,表示縱向和橫向會占用2個網(wǎng)格gbCon.gridwidth = 2;gbCon.gridheight = 2;//把Button數(shù)組中第5個按鈕添加到frame中addComponent(frame,btns[5],gbLayout,gbCon);//把GridBagConstraints的gridheight和gridwidth設(shè)置為1,表示縱向會占用1個網(wǎng)格gbCon.gridwidth = 1;gbCon.gridheight = 1;//把Button數(shù)組中第6個按鈕添加到frame中addComponent(frame,btns[6],gbLayout,gbCon);//把GridBagConstraints的gridwidth設(shè)置為GridBagConstraints.REMAINDER,表明當(dāng)前組件是橫向最后一個組件gbCon.gridwidth = GridBagConstraints.REMAINDER;//把Button數(shù)組中第7個按鈕添加到frame中addComponent(frame,btns[7],gbLayout,gbCon);//把GridBagConstraints的gridheight設(shè)置為1,表示縱向會占用1個網(wǎng)格gbCon.gridwidth = 1;gbCon.gridheight = 1;//把Button數(shù)組中第8,9個按鈕添加到frame中addComponent(frame,btns[8],gbLayout,gbCon);addComponent(frame,btns[9],gbLayout,gbCon);//設(shè)置frame為最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置frame可見frame.setVisible(true);}public static void addComponent(Container container, Component c, GridBagLayout gbLayout, GridBagConstraints gbCon) {gbLayout.setConstraints(c,gbCon);container.add(c);} }

4.5、CardLayout(卡片布局)

CardLayout布局管理器以時間而非空間來管理它里面的組件,它將加入容器的所有組件看成一疊卡片(每個卡片其實就是一個組件),每次只有最上面的哪個Component才可見。

方法名稱方法功能
CardLayout()創(chuàng)建默認的CardLayout布局管理器
CardLayout(int hgap, int vgap)通過指定卡片與容器左右邊界的間距(hgap)、上下邊界的間距(vgap)的間距來創(chuàng)建CardLayout布局管理器
first(Container target)顯示target容器中的第一張卡片
last(Container target)顯示target容器中的最后一張卡片
previous(Container target)顯示target容器中的前一張卡片
next(Container target)顯示target容器中的后一張卡片
show(Container target, String name)顯示target容器中指定名字的卡片

代碼演示:

package Package1;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class CardLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//創(chuàng)建一個Panel,用來存儲多張卡片Panel p1 = new Panel();//創(chuàng)建CardLayout對象,并且把該對象設(shè)置給p1CardLayout cLayout = new CardLayout();p1.setLayout(cLayout);//往p1中存儲多個組件String[] names = {"第一張", "第二張", "第三張", "第四張", "第五張", "第六張"};for (int i = 0; i < names.length; i++) {//每次添加都是作為最后一個組件添加到末尾p1.add(names[i], new Button(names[i])); //添加時指定組件的名字}//把p1放到frame的中間區(qū)域frame.add(p1, BorderLayout.CENTER);//創(chuàng)建另外一個Panel,用來存放5個按鈕組件Panel p2 = new Panel();Button btn1 = new Button("上一張");Button btn2 = new Button("下一張");Button btn3 = new Button("第一張");Button btn4 = new Button("最后一張");Button btn5 = new Button("第三張");//創(chuàng)建一個事件監(jiān)聽器,監(jiān)聽按鈕的點擊動作ActionListener listener = new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String actionCommand = e.getActionCommand(); //這個字符串其實就是按鈕上的文字switch (actionCommand) {case "上一張":cLayout.previous(p1);break;case "下一張":cLayout.next(p1);break;case "第一張":cLayout.first(p1);break;case "最后一張":cLayout.last(p1);break;case "第三張":cLayout.show(p1, "第三張");break;}}};//把當(dāng)前事件監(jiān)聽器和多個按鈕綁定到一起btn1.addActionListener(listener);btn2.addActionListener(listener);btn3.addActionListener(listener);btn4.addActionListener(listener);btn5.addActionListener(listener);//把按鈕添加到容器p2中p2.add(btn1);p2.add(btn2);p2.add(btn3);p2.add(btn4);p2.add(btn5);//把p2放到frame的南邊區(qū)域frame.add(p2, BorderLayout.SOUTH);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400, 200, 500, 300);//設(shè)置Frame可見frame.setVisible(true);} }

4.6、BoxLayout(盒子布局)

為了簡化開發(fā),Swing引入了一個新的布局管理器BoxLayout。BoxLayout可以在垂直和水平兩個方向上擺放GUI組件,BoxLayout提供了如下一個簡單的構(gòu)造器:

方法名稱方法功能
BoxLayout(Container target, int axis)指定創(chuàng)建基于target容器的BoxLayout布局管理器,該布局管理器里的組件按axis方向排列。其中axis有BoxLayout.X_AXIS(橫向)和BoxLayout.Y_AXIS(縱向)兩個方向。

代碼演示:

package Package1;import javax.swing.*; import java.awt.*;public class BoxLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//基于frame容器創(chuàng)建一個BoxLayout對象,并且該對象存放組件是垂直存放BoxLayout boxLayout = new BoxLayout(frame,BoxLayout.Y_AXIS);//把BoxLayout設(shè)置給frameframe.setLayout(boxLayout);//往frame中添加兩個Button組件frame.add(new Button("按鈕1"));frame.add(new Button("按鈕2"));//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

4.6.1、Box容器

為了更方便地使用BoxLayout,在java.swing包中,提供了一個新的容器Box,該容器地默認布局管理器就是BoxLayout,大多數(shù)情況下,使用Box容器去容納多個GUI組件,然后再把Box容器作為一個組件,添加到其它地容器中,從而形成整體窗口布局。

方法名稱方法功能
static Box createHorizontalBox()創(chuàng)建一個水平排列組件的Box容器
static Box createVerticalBox()創(chuàng)建一個垂直排列組件的Box容器

代碼演示:

package Package1;import javax.swing.*; import java.awt.*;public class BoxLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//創(chuàng)建一個水平排列組件的Box容器Box hBox = Box.createHorizontalBox();//往當(dāng)前容器中添加兩個按鈕hBox.add(new Button("水平按鈕1"));hBox.add(new Button("水平按鈕2"));//創(chuàng)建一個垂直排列組件的Box容器Box vBox = Box.createVerticalBox();//往當(dāng)前容器中添加兩個按鈕vBox.add(new Button("垂直按鈕1"));vBox.add(new Button("垂直按鈕2"));//把兩個Box添加到Frame中展示frame.add(hBox,BorderLayout.NORTH);frame.add(vBox,BorderLayout.CENTER);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

通過上面的演示,我們會發(fā)現(xiàn),被它管理的容器中的組件之間是沒有間隔的,是不是特別的美觀,但之前學(xué)習(xí)的幾種布局,組件之間都會有一些間距,那使用BoxLayout如何給組件設(shè)置間距呢?

其實很簡單,我們只需要在原有的組件需要間隔的地方,添加間隔即可,而每個間隔可以是一個組件,只不過該組件沒有內(nèi)容,僅僅起到一種分隔的作用。

Box類中,提供了幾個方便的靜態(tài)方法來生成這些間隔組件:

方法名稱方法功能
static Component createHorizontalGlue()創(chuàng)建一條水平Glue(可在兩個方向上同時拉伸的間距)。
static Component createVerticalGlue()創(chuàng)建一條垂直Glue(可在兩個方向上同時拉伸的間距)。
static Component createHorizontalStrut(int width)創(chuàng)建一條指定寬度(寬度固定,不能拉伸)的水平Strut(可在垂直方向上拉伸的間距)。
static Component createVerticalStrut(int height)創(chuàng)建一條只當(dāng)高度(高度固定,不能拉伸)的垂直Strut(可在水平方向上拉伸的間距)。

代碼演示:

package Package1;import javax.swing.*; import java.awt.*;public class BoxLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//創(chuàng)建一個水平排列組件的Box容器Box hBox = Box.createHorizontalBox();//往當(dāng)前容器中添加兩個按鈕hBox.add(new Button("水平按鈕1"));hBox.add(Box.createHorizontalGlue()); //該分隔在兩個方向上都可以拉伸hBox.add(new Button("水平按鈕2"));hBox.add(Box.createHorizontalStrut(20));hBox.add(new Button("水平按鈕3"));//創(chuàng)建一個垂直排列組件的Box容器Box vBox = Box.createVerticalBox();//往當(dāng)前容器中添加兩個按鈕vBox.add(new Button("垂直按鈕1"));vBox.add(Box.createVerticalGlue()); //該分隔在兩個方向上都可以拉伸vBox.add(new Button("垂直按鈕2"));vBox.add(Box.createVerticalStrut(20));vBox.add(new Button("垂直按鈕3"));//把兩個Box添加到Frame中展示frame.add(hBox,BorderLayout.NORTH);frame.add(vBox,BorderLayout.CENTER);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

5、AWT中常用組件

5.1、基本組件

組件名功能
Button按鈕
Canvas用于繪圖的畫布
Checkbox復(fù)選框組件(也可當(dāng)作單選框組件使用)
CheckboxGroup用于將多個Checkbox組件合成一組,一組Checkbox組件將只有一個可以被選中,即全部變成單選框組件
Choice下拉選擇框
Frame窗口,在GUI程序里通過該類創(chuàng)建窗口
Label標(biāo)簽類,用于放置提示文本
List列表框組件,可以添加多項條目。條目通過調(diào)用列表元素對象的toString()方法來顯示其信息
Panel不能單獨存在的基本容器類,必須放到其它容器中
Scrollbar滑動條組件。如果需要用戶輸入位于某個范圍的值,就可以使用滑動條組件。當(dāng)創(chuàng)建一個滑動條時,必須指定它的方向、初始值、滑塊的大小、最小值和最大值。
ScrollPane帶水平及垂直滾動條的容器組件
TextArea多行文本域
TextField單行文本框

這些AWT組件的用法比較簡單,可以查閱API文檔來獲取它們的各自構(gòu)造方法、成員方法等詳細信息。

代碼演示:

package Package1;import javax.swing.*; import java.awt.*;public class BasicComponentDemo {//組裝界面Frame frame = new Frame("這是一個窗口容器Frame");TextArea ta = new TextArea(5,20); //文本域Choice colorChooser = new Choice(); //下拉選擇框CheckboxGroup cbg = new CheckboxGroup(); //一組CheckboxCheckbox male = new Checkbox("男",cbg,true);Checkbox female = new Checkbox("女",cbg,false);Checkbox isMarried = new Checkbox("是否已婚?"); //一個CheckboxTextField tf = new TextField(50); //單行文本框Button ok = new Button("確認"); //按鈕List colorList = new List(6,true); //支持多選的6行列表//組裝界面public void init() {//組裝選擇部分為cBoxBox cBox = Box.createHorizontalBox();colorChooser.add("紅色");colorChooser.add("綠色");colorChooser.add("藍色");cBox.add(colorChooser);cBox.add(male);cBox.add(female);cBox.add(isMarried);//組裝文本域和選擇部分為topleftBox topLeft = Box.createVerticalBox();topLeft.add(ta);topLeft.add(cBox);//組裝topleft和列表框為top,并放置在frame的中間區(qū)域Box top = Box.createHorizontalBox();top.add(topLeft);colorList.add("紅色");colorList.add("綠色");colorList.add("藍色");top.add(colorList);frame.add(top,BorderLayout.CENTER);//組裝底部為bBox,并放置在frame的南邊區(qū)域Box bBox = Box.createHorizontalBox();bBox.add(tf);bBox.add(ok);frame.add(bBox,BorderLayout.SOUTH);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);}public static void main(String[] args) {new BasicComponentDemo().init();} }

5.2、Dialog(對話框)

Dialog是Window類的子類,是一個容器類,屬于特殊組件。Dialog是可以獨立存在的頂級窗口,因此用法與普通窗口的用法幾乎完全一樣,但是使用對話框需要注意下面兩點:

  • 對話框通常依賴于其它窗口,就是通常需要有一個父窗口;
  • 對話框有非模式(non-modal)和模式(modal)兩種。當(dāng)某個模式對話框被打開后,該模式對話框總是位于它的父窗口之上,在模式對話框被關(guān)閉之前,父窗口無法獲得焦點。
方法名稱方法功能
Dialog(Frame owner, String title, boolean modal)

創(chuàng)建一個對話框?qū)ο?#xff1a;

owner:當(dāng)前對話框的父窗口;

title:當(dāng)前對話框的標(biāo)題;

modal:當(dāng)前對話框是否是模式對話框。true / false

代碼演示:

package Package1;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class DialogDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//創(chuàng)建兩個對話框Dialog對象,一個模式的,一個非模式的Dialog mDialog = new Dialog(frame,"模式對話框",true);Dialog dialog = new Dialog(frame,"非模式對話框",false);//通過setBounds()方法設(shè)置Dialog 的位置及大小mDialog.setBounds(200,100,500,300);dialog.setBounds(200,100,500,300);//創(chuàng)建兩個按鈕Button btn1 = new Button("打開模式對話框");Button btn2 = new Button("打開非模式對話框");//給這兩個按鈕添加點擊后的行為btn1.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {mDialog.setVisible(true);}});btn2.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {dialog.setVisible(true);}});//把按鈕添加到frame中frame.add(btn1,BorderLayout.NORTH);frame.add(btn2,BorderLayout.CENTER);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

5.2.1、FileDialog(文件對話框)

Dialog類還有一個子類FileDialog,它代表一個文件對話框,用于打開或者保存文件,需要注意的是FileDialog無法確定模態(tài)或者非模態(tài),這是因為FIleDialog依賴于運行平臺的實現(xiàn),如果運行平臺的文件對話框是模態(tài)的,那么FileDialog也是模態(tài)的;否則就是非模態(tài)的。

方法名稱方法功能
FileDialog(Frame parent, String title, int mode)

創(chuàng)建一個文件對話框:

parent:指定父窗口;

title:對話框標(biāo)題;

mode:文件對話框類型,如果指定為FileDialog.LOAD,用于打開文件;如果指定為FileDialog.SAVE,用于保存文件。

String getDirectory()獲取被打開或保存文件的絕對路徑
String getFile()獲取被打開或保存文件的文件名

代碼演示:

package Package1;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class FileDialogDemo {public static void main(String[] args) {Frame frame = new Frame("這是一個窗口容器Frame");//創(chuàng)建2個FileDialog對象FileDialog f1 = new FileDialog(frame,"選擇要打開的文件",FileDialog.LOAD);FileDialog f2 = new FileDialog(frame,"選擇要保存的路徑",FileDialog.SAVE);//創(chuàng)建兩個按鈕Button b1 = new Button("打開文件");Button b2 = new Button("保存文件");//給這兩個按鈕設(shè)置點擊后的行為:獲取打開或者保存的路徑文件名b1.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {f1.setVisible(true); //代碼會阻塞到這里//獲取選擇的路徑及文件String directory = f1.getDirectory();String file = f1.getFile();System.out.println("打開的文件路徑為:"+directory);System.out.println("打開的文件名稱為:"+file);}});b2.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {f2.setVisible(true); //代碼會阻塞到這里String directory = f2.getDirectory();String file = f2.getFile();System.out.println("保存的文件路徑為:"+directory);System.out.println("保存的文件名稱為:"+file);}});//把按鈕添加到frame中frame.add(b1,BorderLayout.NORTH);frame.add(b2,BorderLayout.CENTER);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

6、事件處理

前面介紹了如何放置各種組件,從而得到了豐富多彩的圖形界面,但這些界面還不能響應(yīng)用戶的任何操作。因為在AWT編程中,所有用戶的操作,都必須要經(jīng)過一套事件處理機制來完成,而Frame和組件本身沒有事件處理能力。

6.1、GUI事件處理機制

定義:當(dāng)在某個組件上發(fā)生某個操作的時候,會自動地觸發(fā)一段代碼的執(zhí)行。

在GUI事件處理機制中涉及到4個重要的概念需要理解:

  • 事件源(Event Source):操作發(fā)生的場所,通常指某個組件,例如按鈕、窗口等。
  • 事件(Event):在事件源上發(fā)生的操作可以叫作事件,GUI會把事件都封裝到一個Event對象中,如果需要直到該事件的詳細信息,就可以通過Event對象來獲取。
  • 事件監(jiān)聽器(Event Listener):當(dāng)在某個事件源上發(fā)生了某個事件,事件監(jiān)聽器就可對這個事件進行處理。
  • 注冊監(jiān)聽:把某個事件監(jiān)聽器(A)通過某個事件(B)綁定到某個事件源(C)上,當(dāng)在事件源C上發(fā)生了事件B之后,那么事件監(jiān)聽器A的代碼就會自動執(zhí)行。
  • 使用步驟:

  • 創(chuàng)建事件源組件對象;
  • 自定義類,實現(xiàn)XxxListener接口,重寫方法;
  • 創(chuàng)建事件監(jiān)聽器對象(自定義類對象);
  • 調(diào)用事件源組件對象的addXxxListener方法完成注冊監(jiān)聽。
  • 代碼演示:

    package Package1;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class EventDemo {Frame frame = new Frame("這是一個窗口容器Frame");TextField tf = new TextField(30); //30列的單行文本框Button ok = new Button("確定");//組裝視圖public void init() {MyListener myListener = new MyListener(); //創(chuàng)建自定義監(jiān)聽器對象ok.addActionListener(myListener); //注冊監(jiān)聽//把tf和ok翻入frame中frame.add(tf,BorderLayout.NORTH);frame.add(ok);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);}//自定義事件監(jiān)聽器private class MyListener implements ActionListener {@Overridepublic void actionPerformed(ActionEvent e) {tf.setText("Hello World");}}public static void main(String[] args) {new EventDemo().init();} }

    6.2、GUI中常見事件和事件監(jiān)聽器

    事件監(jiān)聽器必須實現(xiàn)事件監(jiān)聽器接口,AWT提供了大量的事件監(jiān)聽器接口用于實現(xiàn)不同類型的事件監(jiān)聽器,來監(jiān)聽不同類型的事件。AWT中提供了豐富的事件類,用于封裝不同組件上所發(fā)生的特定操作,AWT的事件類都是AWTEvent類的子類,AWTEvent類是EventObject類的子類。

    6.2.1、事件

    AWT把事件分為了兩大類:

    1、低級事件:這類事件是基于某個特定動作的事件。比如進入、點擊、拖放等動作的鼠標(biāo)事件,再比如得到焦點和失去焦點等焦點事件。

    事件觸發(fā)時機
    ComponentEvent組件事件,當(dāng)組件尺寸發(fā)生變化、位置發(fā)生移動、顯示/隱藏狀態(tài)發(fā)生改變時觸發(fā)該事件。
    ContainerEvent容器事件,當(dāng)容器里發(fā)生添加組件、刪除組件時觸發(fā)該事件。
    WindowEvent窗口事件,當(dāng)窗口狀態(tài)發(fā)生改變(如打開、關(guān)閉、最大化、最小化)時觸發(fā)該事件。
    FocusEvent焦點事件,當(dāng)組件得到焦點或失去焦點時觸發(fā)該事件。
    KeyEvent鍵盤事件,當(dāng)案件被按下、松開、單機時觸發(fā)該事件。
    MouseEvent鼠標(biāo)事件,當(dāng)進行單機、按下、松開、移動鼠標(biāo)等動作時觸發(fā)該事件。
    PaintEvent組件繪制事件,該事件是一個特殊的事件類型,當(dāng)GUI組件調(diào)用update/paint方法來呈現(xiàn)自身時觸發(fā)該事件,該事件并非專用于事件處理模型。

    2、高級事件:這類事件并不會基于某個特定動作,而是根據(jù)功能含義定義的事件。

    事件觸發(fā)時機
    ActionEvent動作事件,當(dāng)按鈕、菜單項被單擊,在TextField中按Enter鍵時觸發(fā)。
    AdjustmentEvent調(diào)節(jié)事件,在滑動條上移動滑塊以調(diào)節(jié)數(shù)值時觸發(fā)該事件。
    ItemEvent選項事件,當(dāng)用戶選中某項,或取消選中某項時觸發(fā)該事件。
    TextEvent文本事件,當(dāng)文本框、文本域里的文本發(fā)生改變時觸發(fā)該事件。

    6.2.2、事件監(jiān)聽器

    不同的事件需要使用不同的事件監(jiān)聽器監(jiān)聽,不同的監(jiān)聽器需要實現(xiàn)不同的監(jiān)聽器接口,當(dāng)指定事件發(fā)生后,事件監(jiān)聽器就會調(diào)用所包含的事件處理器(實例方法)來處理事件。

    事件類別描述信息監(jiān)聽器接口名
    ActionEvent激活組件ActionListener
    ItemEvent選擇了某些項目ItemListener
    MouseEvent鼠標(biāo)移動MouseMotionListener
    MouseEvent鼠標(biāo)點擊等MouseListener
    KeyEvent鍵盤輸入KeyListener
    FocusEvent組件收到或失去焦點FocusListener
    AdjustmentEvent移動了滾動條等組件AdjustmentListener
    ComponentEvent對象移動縮放顯示隱藏等ComponentListener
    WindowEvent窗口收到窗口級事件WindowListener
    ContainerEvent容器中增加或刪除了組件ContainerListener
    TextEvent文本字段或文本區(qū)發(fā)生改變TextListener

    6.2.3、案例

    案例1:

    package Package1;import javax.swing.*; import java.awt.*; import java.awt.event.*;public class ListenerDemo {public static void main(String[] args) {Frame frame = new Frame();//創(chuàng)建組件TextField tf = new TextField(30);Choice names = new Choice();names.add("張三");names.add("李四");names.add("王五");//給文本域添加TextListener,監(jiān)聽內(nèi)容的變化tf.addTextListener(new TextListener() {@Overridepublic void textValueChanged(TextEvent e) {String text = tf.getText();System.out.println("當(dāng)前文本框的內(nèi)容為:"+text);}});//給下拉選擇框添加ItemListener,監(jiān)聽條目選項的變化names.addItemListener(new ItemListener() {@Overridepublic void itemStateChanged(ItemEvent e) {Object item = e.getItem();System.out.println("當(dāng)前選中的條目為:"+item);}});//給frame注冊ContainerListener監(jiān)聽器,監(jiān)聽容器中組件的添加frame.addContainerListener(new ContainerListener() {@Overridepublic void componentAdded(ContainerEvent e) {Component child = e.getChild();System.out.println("frame中添加了:"+child);}@Overridepublic void componentRemoved(ContainerEvent e) {}});//添加到frame中Box hBox = Box.createHorizontalBox();hBox.add(names);hBox.add(tf);frame.add(hBox);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

    案例2:給Frame設(shè)置WindowListener,監(jiān)聽用戶點擊x的動作,如果用戶點擊x,則關(guān)閉當(dāng)前窗口。

    package Package1;import java.awt.*; import java.awt.event.*;public class ListenerDemo {public static void main(String[] args) {Frame frame = new Frame();//設(shè)置WindowListener,監(jiān)聽用戶點擊x的動作,如果點擊x,則關(guān)閉窗口frame.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {//停止當(dāng)前程序System.exit(0); //退出JVM}});//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);} }

    7、菜單組件

    在實際開發(fā)中,除了主界面,還有一類比較重要的內(nèi)容就是菜單相關(guān)組件,可以通過菜單相關(guān)組件很方便地使用特定的功能。在AWT中,菜單相關(guān)組件的使用和之前學(xué)習(xí)的組件是一模一樣的,只需要把菜單條、菜單、菜單項組合到一起,按照一定的布局,放入到容器中即可。

    下表給出常用的菜單相關(guān)組件:

    菜單組件名稱功能
    MenuBar菜單條,菜單的容器。
    Menu菜單組件,菜單項的容器。它也是MenuItem的子類,所以可作為菜單項使用。
    PopupMenu上下文菜單組件(右鍵菜單組件)。
    MenuItem菜單項組件。
    CheckboxMenuItem復(fù)選框菜單項組件。

    下圖是常見菜單相關(guān)組件繼承體系圖:

    菜單相關(guān)組件使用:

  • 準(zhǔn)備菜單項組件,這些組件可以是MenuItem及其子類對象;
  • 準(zhǔn)備菜單組件Menu或者PopupMenu(右擊彈出菜單),把第一步中準(zhǔn)備好的菜單項組件添加進來;
  • 準(zhǔn)備菜單條組件MenuBar,把第二步中準(zhǔn)備好的菜單組件Menu添加進來;
  • 把第三步中準(zhǔn)備好的菜單條組件添加到窗口對象中顯示。
  • 小技巧:

    • 如果要在某個菜單的菜單項之間添加分割線,那么只需要調(diào)用Menu的add(new MenuItem("-"));即可;
    • 如果要給某個菜單項關(guān)聯(lián)快捷鍵功能,那么只需要在創(chuàng)建菜單項對象時設(shè)置即可,例如給菜單項關(guān)聯(lián)Ctrl+Shift+Q快捷鍵,只需要:new MenuItem("菜單項名字",new MenuShortCun(KeyEvent.VK_Q,true));

    案例1:

    代碼演示:

    package Package1;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent;public class MenuDemo {Frame frame = new Frame("這是一個窗口容器Frame");//創(chuàng)建菜單條MenuBar menuBar = new MenuBar();//創(chuàng)建菜單組件Menu fileMenu = new Menu("文件");Menu editMenu = new Menu("編輯");Menu formatMenu = new Menu("格式");//創(chuàng)建菜單項組件MenuItem auto = new MenuItem("自動換行");MenuItem copy = new MenuItem("復(fù)制");MenuItem paste = new MenuItem("粘貼");MenuItem comment = new MenuItem("注釋",new MenuShortcut(KeyEvent.VK_Q,true)); //關(guān)聯(lián)快捷鍵ctrl+shift+QMenuItem cancelComment = new MenuItem("取消注釋");//創(chuàng)建文本框TextArea ta = new TextArea(6,40);//組裝視圖public void init() {comment.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {ta.append("您點擊了菜單項:"+e.getActionCommand()+"\n");}});formatMenu.add(comment);formatMenu.add(cancelComment);//組裝編輯菜單editMenu.add(auto);editMenu.add(copy);editMenu.add(paste);editMenu.add(formatMenu);//組裝菜單條menuBar.add(fileMenu);menuBar.add(editMenu);//把菜單條和文本框放入frame中frame.setMenuBar(menuBar);frame.add(ta,BorderLayout.CENTER);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);}public static void main(String[] args) {new MenuDemo().init();} }

    案例2:

    package Package1;import java.awt.*; import java.awt.event.*;public class MenuDemo {Frame frame = new Frame("這是一個窗口容器Frame");//創(chuàng)建文本域TextArea ta = new TextArea("默認顯示的文本\n",6,40);//創(chuàng)建Panel容器Panel p = new Panel();//創(chuàng)建PopupMenuPopupMenu popupMenu = new PopupMenu();//創(chuàng)建菜單項MenuItem comment = new MenuItem("注釋");MenuItem cancelComment = new MenuItem("取消注釋");MenuItem copy = new MenuItem("復(fù)制");MenuItem save = new MenuItem("保存");//組裝視圖public void init() {ActionListener listener = new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String actionCommand = e.getActionCommand();ta.append("您點擊了:"+actionCommand+"\n");}};comment.addActionListener(listener);cancelComment.addActionListener(listener);copy.addActionListener(listener);save.addActionListener(listener);//組裝PopupMenupopupMenu.add(comment);popupMenu.add(cancelComment);popupMenu.add(copy);popupMenu.add(save);p.add(popupMenu);//設(shè)置Panel的大小p.setPreferredSize(new Dimension(400,100));//給Panel注冊鼠標(biāo)事件,監(jiān)聽用戶釋放鼠標(biāo)的動作,展示菜單p.addMouseListener(new MouseAdapter() {@Overridepublic void mouseReleased(MouseEvent e) {boolean flag = e.isPopupTrigger();if(flag) {//顯示PopupMenupopupMenu.show(p,e.getX(),e.getY());}}});//放置ta和pframe.add(ta,BorderLayout.CENTER);frame.add(p,BorderLayout.SOUTH);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);}public static void main(String[] args) {new MenuDemo().init();} }

    8、繪圖

    很多程序如各種游戲都需要在窗口中繪制各種圖形,除此之外,即使在開發(fā)javaEE項目時,有時候也必須“動態(tài)”地向客戶端生成各種圖形、圖標(biāo),比如圖形驗證碼、統(tǒng)計圖等,這都需要利用AWT地繪圖功能。

    8.1、組件繪圖原理

    之前我們已經(jīng)學(xué)過很多組件,例如Button、Frame。Checkbox等等,不同的組件,展示出來的圖形都不一樣,其實這些組件展示出來的圖形,其本質(zhì)就是用AWT的繪圖來完成的。

    在AWT中,真正提供繪圖功能的是Graphics對象,那么Component組件和Graphics對象存在什么關(guān)系,才能讓Component繪制自身圖形呢?在Component類中,提供了下列三個方法來完成組件圖形的繪制與刷新:

    • paint(Graphics g):繪制組件的外觀;
    • update(Graphics g):調(diào)用內(nèi)部paint方法,刷新組件外觀;
    • repaint():調(diào)用update方法,刷新組件外觀。

    一般情況下,update和paint方法是由AWT系統(tǒng)負責(zé)調(diào)用,如果程序要希望系統(tǒng)重新繪制組件,可以調(diào)用repaint()方法完成。

    8.2、Graphics對象的使用

    AWT中提供了Canvas類充當(dāng)畫布,提供了Graphics類來充當(dāng)畫筆,通過調(diào)用Graphics對象的setColor()方法可以給畫筆設(shè)置顏色。

    畫圖的步驟:

  • 自定義類,繼承Canvas類,重寫paint(Graphics g)方法完成畫圖;
  • 在paint()方法內(nèi)部,真正開始畫圖之前調(diào)用Graphics對象的setColor()、setFont()等方法設(shè)置畫筆的顏色、字體等屬性;
  • 調(diào)用Graphics畫筆的drawXxx()方法開始畫圖。
  • 其實畫圖的核心就在于使用Graphics畫筆在Canvas畫布上畫出什么顏色、什么樣式的圖形,所以核心在畫筆上,下表給出了Graphics類中常用的一些方法:

    方法名稱方法功能
    setColor(Color c)設(shè)置顏色
    setFont(Font font)設(shè)置字體
    drawLine()繪制直線
    drawRect()繪制矩形
    drawRoundRect()繪制圓角矩形
    drawOval()繪制橢圓形
    drawPolygon()繪制多邊形
    drawArc()繪制圓弧
    drawPolyline()繪制折線
    fillRect()填充矩形區(qū)域
    fillRoundRect()填充圓角矩形區(qū)域
    fillOval()填充橢圓區(qū)域
    fillPolygon()填充多邊形區(qū)域
    fillArc()填充圓弧對應(yīng)的扇形區(qū)域
    drawImage()繪制位圖

    案例1——繪制矩形和橢圓:

    package Package1;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class GraphicsDemo {private final String RECT_SHAPE = "rect";private final String OVAL_SHAPE = "oval";private Frame frame = new Frame("這是一個窗口容器Frame");Button btnRect = new Button("繪制矩形");Button btnOval = new Button("繪制橢圓");//創(chuàng)建Panel,承載按鈕Panel p = new Panel();//定義一個變量,記錄當(dāng)前要繪制橢圓還是矩形private String shape = "";//自定義類,繼承Canvas類,重寫paint(Graphics g)方法完成畫圖private class MyCanvas extends Canvas {@Overridepublic void paint(Graphics g) {//繪制不同的圖形if(shape.equals(RECT_SHAPE)) {//繪制矩形g.setColor(Color.BLACK); //設(shè)置當(dāng)前畫筆的顏色為黑色g.drawRect(50,100,100,50);}else if(shape.equals(OVAL_SHAPE)) {//繪制橢圓g.setColor(Color.RED); //設(shè)置當(dāng)前畫筆的顏色為紅色g.drawOval(100,50,50,100);}}}//自定義畫布對象MyCanvas drawArea = new MyCanvas();//組裝視圖public void init() {btnRect.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {shape = RECT_SHAPE; //修改標(biāo)記的值為rectdrawArea.repaint();}});btnOval.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {shape = OVAL_SHAPE; //修改標(biāo)記的值為rectdrawArea.repaint();}});//設(shè)置drawArea的大小drawArea.setPreferredSize(new Dimension(300,200));frame.add(drawArea);p.add(btnRect);p.add(btnOval);frame.add(p,BorderLayout.SOUTH);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);}public static void main(String[] args) {new GraphicsDemo().init();} }

    Java也可用于開發(fā)一些動畫,就是間隔一定的時間(通常小于0.1秒)重新繪制新的圖像,兩次繪制的圖像之間差異較小,肉眼看起來就成了所謂的動畫。為了實現(xiàn)間隔一定時間就重新調(diào)用組件的repaint()方法,可以借助于Swing提供的Timer類,Timer類是一個定時器,它有如下一個構(gòu)造器:Timer(int delay, ActionListener listener):每間隔delay毫秒,系統(tǒng)自動觸發(fā)ActionListener監(jiān)聽器里的事件處理器方法,在方法內(nèi)部我們就可以調(diào)用組件的repaint()方法,完成組件重繪。

    案例2——彈球小游戲:

    package Package1;import javax.swing.*; import java.awt.*; import java.awt.event.*;public class GraphicsDemo {//創(chuàng)建窗口對象private Frame frame = new Frame("這是一個窗口容器Frame");//設(shè)置桌面寬度和高度private final int TABLE_WIDTH = 300;private final int TABLE_HEIGHT = 400;//設(shè)置球拍的寬度和高度private final int RACKET_WIDTH = 60;private final int RACKET_HEIGHT = 20;//定義變量,記錄球拍的坐標(biāo)private int racketX = 120;private final int racketY = 340;//設(shè)置小球的大小private final int BALL_SIZE = 16;//定義變量,記錄小球的坐標(biāo)private int ballX = 120;private int ballY = 20;//定義變量,記錄小球在x和y方向上分別移動的速度private int speedX = 5;private int speedY = 0;//定義變量,表示當(dāng)前游戲是否已結(jié)束private boolean isOver = false;//聲明一個定時器private Timer timer;//自定義一個類繼承Canvas充當(dāng)畫布private class MyCanvas extends Canvas {@Overridepublic void paint(Graphics g) {//在這里繪制內(nèi)容if (isOver) {//游戲結(jié)束g.setColor(Color.BLUE);g.setFont(new Font("Times", Font.BOLD, 30));g.drawString("游戲結(jié)束!", 80, 200);} else {//游戲中//繪制小球g.setColor(Color.RED);g.fillOval(ballX, ballY, BALL_SIZE, BALL_SIZE);//繪制球拍g.setColor(Color.PINK);g.fillRect(racketX, racketY, RACKET_WIDTH, RACKET_HEIGHT);}}}//創(chuàng)建繪畫區(qū)域MyCanvas myCanvas = new MyCanvas();//組裝視圖以及游戲邏輯的控制public void init() {//完成球拍坐標(biāo)的變化KeyListener listener = new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {//獲取當(dāng)前按下的鍵int keyCode = e.getKeyCode();if (keyCode == KeyEvent.VK_LEFT) {//<- 應(yīng)該向左移動if (racketX > 0) {racketX -= 10;}}if (keyCode == KeyEvent.VK_RIGHT) {//-> 應(yīng)該向右移動if (racketX < TABLE_WIDTH - RACKET_WIDTH) {racketX += 10;}}}};MouseMotionListener mouseMotionListener = new MouseMotionAdapter() {@Overridepublic void mouseMoved(MouseEvent e) {//獲取當(dāng)前鼠標(biāo)位置int mouseX = e.getX();if (mouseX < (RACKET_WIDTH / 2)) {//設(shè)置球拍的位置racketX = 0;} else if (mouseX > (TABLE_WIDTH - RACKET_WIDTH / 2)) {racketX = TABLE_WIDTH - RACKET_WIDTH;} else {racketX = mouseX - (RACKET_WIDTH / 2);}}};//給frame和myCanvas注冊監(jiān)聽器frame.addKeyListener(listener);myCanvas.addKeyListener(listener);myCanvas.addMouseMotionListener(mouseMotionListener);frame.addMouseMotionListener(mouseMotionListener);//完成小球坐標(biāo)的變化ActionListener task = new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//更新小球的坐標(biāo)speedY += 1;ballX += speedX;ballY += speedY;//根據(jù)邊界范圍,修正速度if (ballX <= 0 || ballX >= (TABLE_WIDTH - BALL_SIZE)) {speedX = -speedX; //反向運動}if (ballY <= 0 || (ballY > (racketY - BALL_SIZE) &&ballX >= (racketX - BALL_SIZE) && (ballX <= racketX + RACKET_WIDTH))) {speedY = -speedY;}if (ballY > (racketY - BALL_SIZE) &&(ballX < (racketX - BALL_SIZE) || ballX > (racketX + RACKET_WIDTH))) {//當(dāng)小球超出了球拍的范圍,游戲結(jié)束//停止定時器timer.stop();//修改游戲是否結(jié)束的標(biāo)記isOver = true;}//重繪界面myCanvas.repaint();}};timer = new Timer(30, task);timer.start();//myCanvas.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT));frame.add(myCanvas);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame可見frame.setVisible(true);}public static void main(String[] args) {new GraphicsDemo().init();} }

    8.3、處理位圖

    如果僅僅繪制一些簡單的幾何圖形,程序的圖形效果依然比較單調(diào)。AWT也允許在組件上繪制位圖,Graphics提供了drawImage(Image image)方法用于繪制位圖,該方法需要一個Image參數(shù)代表位圖,通過該方法就可以繪制出指定的位圖。

    位圖使用步驟:

  • 創(chuàng)建Image的子類對象BufferedImage(int width, int height, int ImageType),創(chuàng)建時需要指定位圖的寬高及類型屬性;此時相當(dāng)于在內(nèi)存中生成了一張圖片;
  • 調(diào)用BufferedImage對象的getGraphics()方法獲取畫筆,此時就可以往內(nèi)存中的這張圖片上繪圖了,繪圖的方法和之前學(xué)習(xí)的一模一樣;
  • 調(diào)用組件paint方法中提供的Graphics對象的drawImage()方法,一次性地將內(nèi)存中地圖片BufferedImage繪制到特定的組件上。
  • 使用位圖繪制組件的好處:

    使用位圖來繪制組件,相當(dāng)于實現(xiàn)類圖的緩沖區(qū),此時繪圖時沒有直接把圖形繪制到組件上,而是先繪制到內(nèi)存中的BufferedImage上,等全部繪制完畢,再一次性地將圖像顯示到組件上即可,這樣用戶的體驗會好一些。

    代碼演示:

    package Package1;import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage;public class ImageDemo {//定義窗口對象Frame frame = new Frame("這是一個窗口容器Frame");//定義畫圖區(qū)的寬高private final int AREA_WIDTH = 500;private final int AREA_HEIGHT = 400;//定義一個右鍵菜單,用于設(shè)置畫筆的顏色private PopupMenu colorMenu = new PopupMenu();private MenuItem redItem = new MenuItem("紅色");private MenuItem greenItem = new MenuItem("綠色");private MenuItem blueItem = new MenuItem("藍色");//定義一個變量,記錄當(dāng)前畫筆的顏色,默認為黑色private Color forceColor = Color.BLACK;//創(chuàng)建一個BufferedImage位圖對象BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_RGB);//通過位圖,獲取關(guān)聯(lián)的Graphics對象Graphics g = image.getGraphics();//自定義一個類,繼承Canvasprivate class MyCanvas extends Canvas {@Overridepublic void paint(Graphics g) {g.drawImage(image, 0, 0, null);}}MyCanvas myCanvas = new MyCanvas();//定義變量,記錄鼠標(biāo)拖動過程中,上一次所處的坐標(biāo)private int preX = -1;private int preY = -1;//組裝視圖public void init() {ActionListener listener = new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String actionCommand = e.getActionCommand();switch (actionCommand) {case "紅色":forceColor = Color.RED;break;case "綠色":forceColor = Color.GREEN;break;case "藍色":forceColor = Color.BLUE;break;}}};redItem.addActionListener(listener);greenItem.addActionListener(listener);blueItem.addActionListener(listener);colorMenu.add(redItem);colorMenu.add(greenItem);colorMenu.add(blueItem);//把colorMenu設(shè)置給繪圖區(qū)域myCanvasmyCanvas.add(colorMenu);myCanvas.addMouseListener(new MouseAdapter() {@Override//當(dāng)鼠標(biāo)鍵抬起時被調(diào)用public void mouseReleased(MouseEvent e) {boolean popupTrigger = e.isPopupTrigger();if (popupTrigger) {colorMenu.show(myCanvas, e.getX(), e.getY());}//重置preX和preYpreX = -1;preY = -1;}});//設(shè)置位圖的背景為白色g.setColor(Color.WHITE);g.fillRect(0, 0, AREA_WIDTH, AREA_HEIGHT);//通過監(jiān)聽鼠標(biāo)的移動,完成繪制myCanvas.addMouseMotionListener(new MouseMotionAdapter() {@Override//該方法,當(dāng)鼠標(biāo)左鍵按下,并進行拖動時,會被調(diào)用public void mouseDragged(MouseEvent e) {if (preX > 0 && preY > 0) {g.setColor(forceColor);//畫線條,需要兩組坐標(biāo),分別代表線條的起點和終點g.drawLine(preX, preY, e.getX(), e.getY());}//修正preX和preY的值preX = e.getX();preY = e.getY();//重繪組件myCanvas.repaint();}});myCanvas.setPreferredSize(new Dimension(AREA_WIDTH, AREA_HEIGHT));frame.add(myCanvas);frame.pack();frame.setVisible(true);}public static void main(String[] args) {new ImageDemo().init();} }

    8.4、ImageIO的使用

    在實際生活中,很多軟件都支持打開本地磁盤已經(jīng)存在的圖片,然后進行編輯,編輯完畢后,再重新保存到本地磁盤。如果使用AWT要文成這樣的功能,那么需要使用到ImageIO這個類,可以操作本地磁盤的圖片文件。

    方法名稱方法功能
    static BufferedImage read(File input)讀取本地磁盤圖片文件
    static BufferedImage read(InputStream input)讀取本地磁盤圖片文件
    static boolean write(RenderedImage img, String formatName, File output)往本地磁盤中輸出圖片文件

    代碼演示:

    package Package1;import javax.imageio.ImageIO; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException;public class LASImage {private Frame frame = new Frame("這是一個窗口容器Frame");MenuBar menuBar = new MenuBar();Menu menu = new Menu("文件");MenuItem open = new MenuItem("打開");MenuItem save = new MenuItem("另存為");//聲明BufferedImage對象,記錄本地讀取到內(nèi)存中的圖片BufferedImage image;private class MyCanvas extends Canvas {@Overridepublic void paint(Graphics g) {g.drawImage(image,0,0,null);}}MyCanvas myCanvas = new MyCanvas();//組裝視圖public void init() {open.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//打開一個文件對話框FileDialog fileDialog = new FileDialog(frame,"打開圖片",FileDialog.LOAD);fileDialog.setVisible(true);//獲取用戶選擇的圖片路徑以及名稱String directory = fileDialog.getDirectory();String file = fileDialog.getFile();try {image = ImageIO.read(new File(directory,file));myCanvas.repaint();} catch (IOException ex) {ex.printStackTrace();}}});save.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//展示一個文件對話框FileDialog fileDialog = new FileDialog(frame,"保存圖片",FileDialog.SAVE);fileDialog.setVisible(true);//獲取用戶設(shè)置的保存路徑以及文件名稱String directory = fileDialog.getDirectory();String file = fileDialog.getFile();try {ImageIO.write(image,"JPEG",new File(directory,file));} catch (IOException ex) {ex.printStackTrace();}}});menu.add(open);menu.add(save);menuBar.add(menu);frame.setMenuBar(menuBar);frame.add(myCanvas);//通過pack()方法設(shè)置最佳大小frame.pack();//設(shè)置Frame的位置和大小frame.setBounds(400,200,500,300);//設(shè)置Frame可見frame.setVisible(true);}public static void main(String[] args) {new LASImage().init();} }

    總結(jié)

    以上是生活随笔為你收集整理的Java图形化界面编程之——AWT的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    黄色片网站免费 | 久久久久国产精品免费网站 | 99亚洲国产精品 | 国产精品久久久影视 | www.91av在线 | 成人影片免费 | 午夜成人免费影院 | 国产尤物在线视频 | 97超视频在线观看 | 久久久精品高清 | 欧美一级视频在线观看 | 黄色毛片视频免费观看中文 | 国产精品观看 | 国产精品一区二区久久国产 | 久久精品三 | 四虎8848免费高清在线观看 | 免费视频一区 | 精品中文字幕在线 | 一区 二区 精品 | 91精品伦理 | 日韩在线高清视频 | 日韩成人免费在线观看 | 国产日韩欧美在线观看视频 | 亚洲成人黄色av | 午夜精品一区二区三区在线视频 | 国产中文在线字幕 | 亚洲爽爽网 | 欧美a影视| 国产成人99av超碰超爽 | 91在线视频网址 | 国产美女免费视频 | 高清av免费看 | 在线亚洲欧美视频 | 国产精品a久久久久 | 操老逼免费视频 | 亚洲天堂自拍视频 | 日韩久久网站 | 精品久久久久久国产91 | 久艹在线免费观看 | 久久精品中文字幕一区二区三区 | 国产999精品久久久 免费a网站 | 免费看片日韩 | 91在线国内视频 | 狠狠的日 | 国产精品成人自产拍在线观看 | 在线视频电影 | 亚洲精品国偷拍自产在线观看 | 中文字幕超清在线免费 | 国产精品视频观看 | 日韩中文免费视频 | 玖玖在线资源 | 蜜臀av免费一区二区三区 | 日韩在线 | 最近中文字幕在线中文高清版 | 97超碰国产精品女人人人爽 | 国产精品美女久久久久久久网站 | 国产精品久久久久毛片大屁完整版 | 国产啊v在线 | 欧美精品久久久 | 美女视频黄免费的久久 | 久久欧美视频 | 国内揄拍国产精品 | 激情五月视频 | 久久怡红院 | 三级视频日韩 | 国产色视频一区 | 色操插| 国产资源网 | 97超碰色| 96精品高清视频在线观看软件特色 | 免费在线色视频 | 九九热在线播放 | 美女网站视频色 | 波多野结衣在线视频免费观看 | 超碰最新网址 | 91香蕉视频黄色 | 国产精品午夜免费福利视频 | 在线免费黄色片 | 国产一级在线看 | 玖玖国产精品视频 | 天天干.com | www.狠狠色 | 成人av网站在线播放 | 中文字幕高清有码 | 久久精品久久综合 | 精品视频999 | 久久精品小视频 | 国产亚洲人成网站在线观看 | 97日日碰人人模人人澡分享吧 | 99超碰在线播放 | 五月婷婷中文网 | 国产一区二区精 | 一区二区三区四区免费视频 | 国产97免费 | 狠狠狠狠狠狠狠狠干 | 中文字幕精品一区二区三区电影 | 国产美女主播精品一区二区三区 | 国产视频一区二区在线观看 | 狠狠五月天 | 91精品在线免费观看 | 91成人精品在线 | 国产特黄色片 | 国产成人久久精品77777综合 | 精品久久久久国产 | 精品久久久久国产免费第一页 | 国产大陆亚洲精品国产 | 人人射人人射 | 国外成人在线视频网站 | 色瓜 | 精品在线播放视频 | 18+视频网站链接 | 久久精品成人欧美大片古装 | 日韩精品久久久免费观看夜色 | 人人干97 | 亚洲九九精品 | 69久久久久久久 | 最近高清中文字幕在线国语5 | 天天插天天操天天干 | 国产精选在线 | 久久免费看a级毛毛片 | 99在线观看视频网站 | 99久久精品免费 | 免费午夜网站 | 亚洲精品影院在线观看 | 99热官网 | 国产一区二区精品久久91 | 91视频国产高清 | 一区二区三区四区免费视频 | 欧美日韩性 | 成人av免费电影 | 日本中文字幕在线免费观看 | 久久国产亚洲精品 | 婷婷亚洲综合 | 亚洲精品麻豆 | 国产精品黑丝在线观看 | 日韩精品一区二区三区在线视频 | 人人精品 | 97超在线视频 | 婷婷日韩 | 亚洲永久免费av | 精品国产乱码久久久久久久 | 一区二区三区手机在线观看 | 久久国产精品影视 | 国产精品门事件 | 91看片淫黄大片一级在线观看 | 婷婷在线免费观看 | 中文 一区二区 | 精品国自产在线观看 | 国产精品成人自产拍在线观看 | 91亚洲狠狠婷婷综合久久久 | 免费视频区| 麻豆91视频| 婷婷久久久久 | 久久精国产 | 日韩精品视频免费看 | 碰天天操天天 | 91精品在线播放 | 久久免费黄色网址 | 黄色av一级 | 久久99爱视频 | 人人澡人人添人人爽一区二区 | 亚洲欧洲一级 | 国产a高清 | 在线黄色国产电影 | 免费视频色 | 亚洲综合精品视频 | 精品嫩模福利一区二区蜜臀 | 91精品国产成人观看 | 999国内精品永久免费视频 | 九九免费精品 | 三级黄色片在线观看 | av成人在线电影 | 亚洲免费资源 | 香蕉久久久久 | 国产色视频网站 | 欧美做受高潮 | 亚洲欧美综合 | 亚洲视频每日更新 | 91视频91蝌蚪 | 麻豆影视在线观看 | 色五月色开心色婷婷色丁香 | 天天天干夜夜夜操 | 久久免费国产电影 | 亚洲国产综合在线 | 伊人开心激情 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 日韩一区二区三区观看 | 亚洲色图色 | 成人手机在线视频 | 久久不卡电影 | 中文乱码视频在线观看 | 国产伦理久久精品久久久久_ | 国产精品久久久久国产a级 激情综合中文娱乐网 | 久久综合综合久久综合 | 欧美va天堂在线电影 | av黄色av| 亚洲在线高清 | 精品中文字幕在线观看 | 高清视频一区二区三区 | 在线免费视 | 伊人久操 | 又湿又紧又大又爽a视频国产 | 国产精品18久久久久久vr | 黄色高清视频在线观看 | 免费在线一区二区 | 亚洲专区免费观看 | 久爱精品在线 | 亚洲精品视频在线免费 | 天天干天天操天天拍 | 久久精品中文字幕免费mv | 亚洲动漫在线观看 | 81国产精品久久久久久久久久 | 亚洲va欧美va | 天天色天天射天天操 | 久久精品99国产精品亚洲最刺激 | 久久久久国产一区二区 | 91免费试看| 99视频久久 | 91精品成人久久 | 成人av免费 | 天天插天天色 | 开心丁香婷婷深爱五月 | 国产看片免费 | 国产成人精品在线播放 | 久久黄网站 | 久久另类小说 | 免费在线一区二区 | 久久国产精品免费 | 黄色一级大片在线观看 | 中文字幕在线观看91 | 天天干天天在线 | 久久成年视频 | 精品麻豆入口免费 | 国产一区精品在线 | 人人插人人草 | 精品久久一区二区 | 欧美激情片在线观看 | 在线观看亚洲电影 | a级国产毛片 | 久久精品国产第一区二区三区 | 在线精品在线 | 亚洲一级性 | 久久综合中文字幕 | 欧美激情xxxx | 久草视频资源 | 一级c片| 色黄久久久久久 | 国产黄a三级三级三级三级三级 | 成人免费网站在线观看 | 97免费在线视频 | 国产精品欧美一区二区 | 欧美精品在线观看 | av资源免费观看 | 激情电影影院 | 精品国产一区二区三区av性色 | 日韩大陆欧美高清视频区 | 99精品在线免费视频 | 国产免费嫩草影院 | 成人黄色在线 | 国产视频丨精品|在线观看 国产精品久久久久久久久久久久午夜 | 亚洲国产成人在线播放 | 久久精品国产第一区二区三区 | 99精品视频一区二区 | 免费观看性生活大片3 | 久久电影网站中文字幕 | 久久天天躁狠狠躁亚洲综合公司 | 欧美成人久久 | 日本韩国欧美在线观看 | 99产精品成人啪免费网站 | 亚洲精品日韩av | 黄色免费视频在线观看 | 在线超碰av | 91人人视频在线观看 | 麻豆视频大全 | 亚洲精品男人天堂 | 色婷婷av一区二 | av电影免费观看 | 国产免费观看高清完整版 | 欧美肥妇free | 四虎国产精品免费 | 国产精品久久久久久久久久新婚 | 一区在线观看 | 免费在线观看91 | 中文字幕最新精品 | 久久av在线播放 | 波多野结衣在线播放一区 | 中文字幕在线不卡国产视频 | 亚洲精品视频久久 | 中文字幕欧美三区 | 国产玖玖视频 | 久久免费视频在线观看6 | 在线成人免费 | 国产在线观看你懂得 | 国产夫妻自拍av | 欧美精品一区二区三区一线天视频 | 久久免费看片 | 最近中文字幕久久 | 免费在线看v | 免费a现在观看 | 久热免费在线观看 | 久久精品视频在线观看免费 | 亚洲九九爱 | 91视频免费网站 | 国产精品自产拍在线观看网站 | 精品一区二区免费视频 | 成人免费一级 | 国产护士av | 精品国产一区二区三区久久久久久 | 97精品国产91久久久久久 | 亚洲天堂香蕉 | 免费亚洲成人 | 国产亚洲精品久久久久久移动网络 | 精品嫩模福利一区二区蜜臀 | 亚洲综合网站在线观看 | 黄色一级在线免费观看 | 亚洲天堂激情 | 国产在线免费观看 | 久久久久久久久久久影院 | 国产欧美日韩精品一区二区免费 | 激情综合色播五月 | 成人h视频在线播放 | 国产不卡视频在线 | av黄免费看| 国产精品免费视频久久久 | 国产视频午夜 | 日韩精品一区二区三区三炮视频 | 国产精品不卡一区 | 91桃色免费观看 | 97在线免费观看视频 | 香蕉视频在线视频 | 夜夜骑天天操 | 丁香婷婷电影 | 国产精品久久99 | 成人97视频一区二区 | 九九精品视频在线观看 | 婷婷综合成人 | 国产精品18久久久久久久久 | 国产一级电影免费观看 | 天天操天天怕 | 激情视频免费观看 | 亚洲日本成人网 | 欧美日本不卡 | 色婷婷六月天 | 久久天天躁| 成人黄色短片 | 久久国产精品视频 | 成人一级在线 | 国产群p| 国产最顶级的黄色片在线免费观看 | av免费在线免费观看 | 日韩免费观看高清 | 91香蕉国产在线观看软件 | 波多野结衣精品视频 | 97在线看片 | 日韩一级黄色av | 日韩美女一级片 | 在线看的av网站 | www免费看 | 国产91精品欧美 | 999亚洲国产996395 | 亚洲播放一区 | 天天综合色天天综合 | 国产麻豆视频免费观看 | 欧美日韩国产亚洲乱码字幕 | 国产在线97| 99久久免费看 | 美女久久久久久 | 亚洲精品国产精品国产 | 久插视频 | 91精品在线麻豆 | 亚洲视频六区 | 永久免费的啪啪网站免费观看浪潮 | 国产综合香蕉五月婷在线 | 久久99精品国产麻豆婷婷 | 不卡av在线免费观看 | 国产精品一区二区美女视频免费看 | 国产麻豆精品久久一二三 | 日本中文字幕网 | 天天综合网在线 | 91亚洲永久精品 | 日本精品视频在线观看 | .国产精品成人自产拍在线观看6 | 精品xxx | 天堂在线视频中文网 | 欧美精品被 | 98福利在线 | 久久久精品成人 | 日韩色在线观看 | 手机成人在线电影 | 在线观看视频你懂 | 久久国产精品免费观看 | 毛片网在线播放 | 欧美成人亚洲 | 日韩四虎| 欧洲不卡av | 麻豆国产电影 | 欧美日韩成人一区 | 亚洲欧美视频一区二区三区 | 丁香花中文在线免费观看 | 特级毛片aaa | 午夜成人免费电影 | 亚洲精品日韩一区二区电影 | 国产区精品区 | 久久久久一区二区三区四区 | 欧美日韩国内在线 | 国产99久 | 黄色软件大全网站 | 国产精品亚州 | 亚洲爱av| 99精品视频免费看 | 在线观看免费福利 | 国产九九九精品视频 | 亚洲区视频在线 | 国内精品二区 | 午夜精品久久久久久久久久久久 | 99在线热播 | 超碰九九 | 成人蜜桃 | 99久久久成人国产精品 | 又污又黄网站 | 午夜精品久久久久久久99无限制 | 激情图片久久 | 亚洲v欧美v国产v在线观看 | 亚洲成熟女人毛片在线 | 激情电影在线观看 | 亚洲国产精品500在线观看 | 午夜视频黄 | av免费片 | 日韩中文在线电影 | 久久婷婷国产色一区二区三区 | 免费av的网站 | 久久久久久久久久久免费av | 亚洲影视九九影院在线观看 | 激情丁香月 | 婷婷综合网 | 天天操天天操天天操天天 | 久久久久激情 | 中文字幕一区二区三区精华液 | 99视频在线免费播放 | 玖玖视频国产 | 美女视频黄免费的 | 亚洲热久久 | 国产精品免费不 | www.黄色在线| 婷婷色在线观看 | 福利精品在线 | 久久久免费播放 | 国产精品久久久久久久久毛片 | 欧美性一级观看 | 亚欧日韩成人h片 | 欧美国产精品久久久久久免费 | 88av色| 久久中国精品 | 欧美精品久久久久久久免费 | 亚洲九九九在线观看 | 91在线精品视频 | 久久天天躁夜夜躁狠狠85麻豆 | 亚洲不卡av一区二区三区 | 婷婷六月综合网 | 国产成人久久久久 | 深夜免费福利 | 国产日韩精品一区二区在线观看播放 | a久久免费视频 | 免费亚洲一区二区 | 国产麻豆精品一区二区 | 久久精品国产一区二区三 | 国产99在线 | 中日韩欧美精彩视频 | 国产麻豆果冻传媒在线观看 | 深夜国产福利 | 国产成人精品女人久久久 | 日韩av成人在线 | 日本aaaa级毛片在线看 | 国产馆在线播放 | 精品免费一区二区三区 | 欧美精品三级在线观看 | 波多野结衣亚洲一区二区 | 亚洲精品av在线 | 日韩v在线91成人自拍 | 精品资源在线 | 99久久久国产精品免费观看 | 涩涩成人在线 | 亚洲视频h | 亚洲视频免费在线观看 | 精壮的侍卫呻吟h | 婷婷在线播放 | 男女靠逼app | 欧美日韩精品在线播放 | 黄色com| 婷婷免费在线视频 | 国产又粗又猛又爽又黄的视频先 | av网站在线免费观看 | 99久久精品国产系列 | 成人91在线 | 国产精品成人久久久久久久 | 一级黄色在线免费观看 | 中文字幕在线观看完整版 | 特黄色大片| 黄色电影网站在线观看 | 精品一区二区免费视频 | 天天曰 | 91欧美在线 | 天天干天天摸 | 波多野结衣一区二区三区中文字幕 | 黄色资源在线观看 | 欧美日韩成人一区 | 国产午夜免费视频 | 美女网站黄在线观看 | 国模精品在线 | 久久久黄视频 | 国产精品青青 | 97超碰国产精品 | 午夜三级福利 | 91精品久久香蕉国产线看观看 | 国产精品99久久久久久武松影视 | 97电影网手机版 | 国产精品字幕 | 波多野结衣在线播放视频 | 伊人五月天 | 欧美日韩调教 | 久久福利国产 | av大全在线免费观看 | 久久久国产精品成人免费 | 亚洲精品乱码久久久久久蜜桃91 | 精品无人国产偷自产在线 | 在线免费高清一区二区三区 | 午夜婷婷在线播放 | 免费高清在线视频一区· | 超碰97国产| 日日夜夜添 | 综合色天天 | 免费观看一级特黄欧美大片 | 色网站视频 | 免费av的网站 | 欧美与欧洲交xxxx免费观看 | 久久久影院官网 | 免费av影视 | 蜜臀av一区二区 | 国产色在线,com | 久久国语 | 午夜精品福利一区二区 | 亚洲国产精品激情在线观看 | 国产破处视频在线播放 | 国产伦理剧 | 四虎永久网站 | 国产日产av| 女人18精品一区二区三区 | 五月天久久综合网 | a级成人毛片 | 国内精品久久久久影院优 | 91视频在线观看免费 | 欧美日韩国产在线 | 91在线视频网址 | 日韩av电影免费观看 | 在线91av| 国产精品久久久久久久午夜片 | 伊人五月 | 国产黑丝一区二区三区 | 国产在线成人 | av中文字幕日韩 | 免费观看www视频 | 免费日韩高清 | 国产成人l区 | 欧美日韩高清一区二区 国产亚洲免费看 | 色视频在线观看 | 国产三级香港三韩国三级 | 探花视频在线观看免费 | 色婷婷丁香 | 91精品啪在线观看国产线免费 | 欧美一区二区三区免费观看 | 美女网站在线观看 | 久久高清国产视频 | 欧美九九九| 免费成人av | 99国产精品视频免费观看一公开 | 国产精品第一页在线 | 黄色a级片在线观看 | 蜜臀久久99静品久久久久久 | 亚洲国产天堂av | 在线免费黄色毛片 | 久久免费视频6 | 亚洲另类在线视频 | 在线观看免费黄视频 | 国产无吗一区二区三区在线欢 | 日韩电影中文,亚洲精品乱码 | 欧美精品一区二区蜜臀亚洲 | 国产精品久久久久久久久软件 | 99在线视频观看 | 亚洲伊人av | 久草a视频 | 国产成a人亚洲精v品在线观看 | 九色自拍视频 | 在线精品视频免费播放 | 在线看v片 | 国产成人一区二区精品非洲 | 色多多污污 | 久久久久久久久久久福利 | 亚洲视频99 | aⅴ视频在线 | 伊人久在线 | 97色资源| 国产手机视频在线播放 | 亚洲一区动漫 | 国产黄色在线观看 | 欧美在线观看视频一区二区 | 久久日本视频 | 免费视频色 | 96精品高清视频在线观看软件特色 | 九九热免费观看 | 国产精品久久久久久久久毛片 | 狠狠的干 | 中文字幕欧美日韩va免费视频 | 国产精品一区二区中文字幕 | 成人亚洲精品国产www | 国产精品v欧美精品 | 深爱激情站 | 国产麻豆电影 | 国产精品不卡一区 | 欧美日韩国产二区三区 | 欧美成人黄色片 | 97超碰人| 国产日韩欧美综合在线 | 久久视频6 | 国产成人免费观看久久久 | 成人欧美日韩国产 | 天天操天天干天天综合网 | 91福利免费 | 黄污网| 97视频在线免费播放 | 久草在线中文888 | 国产精品视频区 | 欧美韩国日本在线观看 | 日韩精品综合在线 | 日本久久免费电影 | 欧美激情精品久久久久久免费印度 | 亚洲视频在线视频 | 天天干夜夜擦 | 在线观看视频一区二区三区 | 三级黄色在线 | 亚洲中字幕 | 亚洲精品国产成人 | 国产精品网红福利 | 天堂av观看| 日韩免费二区 | 欧美日韩视频在线一区 | 国产又粗又猛又爽又黄的视频先 | 免费观看成人av | 亚洲a网| 又黄又刺激的视频 | 国内精品毛片 | 国产va饥渴难耐女保洁员在线观看 | 九九免费精品视频在线观看 | 激情网五月 | 日韩精品免费在线观看 | 97久久精品午夜一区二区 | 成人午夜精品久久久久久久3d | 国产高清免费 | 久久国产精品久久精品国产演员表 | 久久久久久久久久网 | 中文字幕中文中文字幕 | 国产在线一区二区三区播放 | 国产在线第三页 | 亚洲精品视频一二三 | 免费视频三区 | 福利视频区 | av在线看片| 国产一级片免费播放 | 免费看片日韩 | 日韩av视屏在线观看 | 五月天婷亚洲天综合网鲁鲁鲁 | 丁香婷婷综合色啪 | 国产精品久久久久久久久久久杏吧 | 亚洲精品国产品国语在线 | 国产黄色资源 | 午夜成人影视 | 国产视频一区在线免费观看 | 欧美在线视频一区二区三区 | 在线看福利av | 日韩精品不卡 | 99在线精品视频观看 | 欧美视屏一区二区 | 亚洲成人免费 | 黄色的网站免费看 | 极品美女被弄高潮视频网站 | 国产精品午夜av | 国产福利在线不卡 | 九九免费精品视频 | 激情五月***国产精品 | 92中文资源在线 | 91在线看视频| 天天干天天做天天爱 | 成人h在线播放 | 免费在线观看亚洲视频 | 国产淫片| 色婷婷综合视频在线观看 | 亚洲黄色免费电影 | 天天插视频| av免费网页 | 国产免费成人 | 成人午夜片av在线看 | 在线日韩亚洲 | 97免费中文视频在线观看 | 国产一区成人 | 午夜色场| 天堂va在线高清一区 | 在线看的av网站 | 国产成人一二片 | 在线v片免费观看视频 | 日本精品视频在线观看 | 久久免费资源 | 99精品系列 | 久久96国产精品久久99漫画 | 国产精品久久久久久久久久不蜜月 | 日韩黄色中文字幕 | 在线看av网址 | 欧美小视频在线观看 | 天天色棕合合合合合合 | 免费在线观看av的网站 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 免费看片网站91 | 又污又黄的网站 | 国产乱老熟视频网88av | 婷婷伊人综合 | 在线电影av | 免费观看高清 | 国产精品一区一区三区 | av黄色免费网站 | 美女视频黄免费网站 | 西西444www大胆高清视频 | 亚洲黄色影院 | 久久国产精品区 | 国产 欧美 日产久久 | 亚洲国产精品电影在线观看 | 在线看片视频 | 黄视频色网站 | 碰超在线97人人 | 中日韩在线 | 国产精品久久久久久久av电影 | 国产免费又爽又刺激在线观看 | 一区二区三区免费在线 | 7777精品伊人久久久大香线蕉 | 婷婷丁香激情五月 | 美女网站在线看 | 天天干人人 | 久久99久久99免费视频 | www天天操 | 久久久久电影网站 | 国产黄色一级大片 | 国产精品福利午夜在线观看 | 欧美夫妻性生活电影 | 岛国大片免费视频 | 成人国产在线 | 天天操夜 | 久久久久久蜜桃一区二区 | 精品国产伦一区二区三区观看方式 | 99999精品| 久黄色 | 夜夜躁狠狠躁日日躁视频黑人 | 欧美做受高潮1 | 三上悠亚在线免费 | 亚洲国产精品电影在线观看 | 天天射网 | 色综合www| 色五丁香| 免费在线观看毛片网站 | 中文字幕在线有码 | 欧美综合在线视频 | 久久精品www人人爽人人 | 国产中文字幕在线看 | 免费看特级毛片 | 99精品视频一区二区 | 国产成人精品福利 | 欧美少妇xxx | 免费在线观看成人av | 国产精品久久久久久久7电影 | 国产伦精品一区二区三区免费 | 四虎永久免费在线观看 | 国产精品青草综合久久久久99 | 日本高清xxxx | 日本在线观看一区二区 | 久久久久日本精品一区二区三区 | 麻豆精品在线视频 | 日韩久久精品一区二区 | 中文字幕一区在线观看视频 | 综合久久一本 | 国产中文字幕一区 | 欧美极品xxxxx | 一区二区视频免费在线观看 | 国产精品久久久久久电影 | 亚洲国产精品久久久久婷婷884 | 亚洲黄色免费在线 | 在线天堂中文www视软件 | 久久久国产影院 | 天天操天天色天天 | 亚洲综合婷婷 | 在线免费黄色片 | 国产一级视频在线观看 | 最新av在线网站 | 992tv成人免费看片 | 日日日日 | 免费在线成人av | 成人av电影免费在线观看 | 欧美一区免费在线观看 | www天天干| 国产毛片aaa| 国产亚洲精品久 | 色婷婷综合久久久久中文字幕1 | 欧美成人在线网站 | 日本天天操 | 手机在线日韩视频 | 又黄又刺激视频 | 色片网站在线观看 | 懂色av一区二区三区蜜臀 | 日本超碰在线 | 激情五月婷婷综合 | 国产精品免费久久久久 | 国产成人精品综合 | 99热超碰 | 亚洲永久精品在线 | 午夜久久电影网 | www黄色大片 | 天天干,狠狠干 | 日韩精品免费在线观看视频 | 狠狠色伊人亚洲综合网站野外 | 香蕉久草在线 | 天堂av在线7 | 婷婷色综合色 | 日韩黄色av网站 | 色综合天天做天天爱 | 欧美亚洲精品一区 | 久久免费视频7 | 99九九视频 | 亚洲最新av在线网站 | 综合中文字幕 | 国内久久久久久 | v片在线看| 在线观看av免费观看 | 国产三级在线播放 | 国产精品成人自产拍在线观看 | 最近中文字幕视频完整版 | 久久欧美综合 | 国产黄色av | 亚洲专区一二三 | a黄在线观看 | 果冻av在线 | 精品国产午夜 | 久久 地址 | 亚洲va韩国va欧美va精四季 | 一区二区中文字幕在线播放 | 中文字幕乱在线伦视频中文字幕乱码在线 | 黄色日本免费 | 亚洲欧美国产视频 | 成人午夜影院在线观看 | 国产视频一区二区三区在线 | 在线视频 区 | 国产成人三级三级三级97 | 91久久久久久久 | 欧美美女激情18p | 久久久久久毛片精品免费不卡 | 国产精品视频永久免费播放 | 国内精品久久久久久久97牛牛 | 香蕉91视频 | 久久国产精品一区二区三区四区 | 午夜国产在线观看 | 插久久 | 精品美女国产在线 | 国产精品久久久电影 | 午夜视频一区二区三区 | adn—256中文在线观看 | 日韩午夜视频在线观看 | 久草精品在线播放 | 国产高清成人av | 国产免码va在线观看免费 | 久久久精品国产一区二区三区 | 欧美伦理一区二区 | 在线观看视频黄 | 99视频在线免费观看 | 亚洲高清视频在线观看 | www.天天干| 精品国产黄色片 | 香蕉视频18| 国产精品免费麻豆入口 | 婷婷久久五月天 | 精品视频网站 | 亚洲成人资源 | 久久一区二区三区超碰国产精品 | 国产一区二区久久 | 国产资源免费在线观看 | 超碰国产在线播放 | 中文不卡视频 | 欧美日韩中文在线 | 国产手机精品视频 | 97超视频在线观看 | 亚洲天堂网在线视频观看 | 亚洲一级免费观看 | 日日日日 | 日日操日日插 | 婷婷在线免费视频 | 天天色图 | 精品国产一二三 | 91av在线免费看| 久久亚洲免费 | 亚洲欧美少妇 | 国产日本亚洲高清 | 免费国产在线观看 | 美女精品在线 | 精品久久久久久综合 | 欧美精品乱码久久久久 | 国产精品一区二区三区电影 | 狠狠干狠狠色 | 天天想夜夜操 | 6080yy精品一区二区三区 | 欧美日韩高清一区二区三区 | 国产人成精品一区二区三 | 国产亚洲视频系列 | 97超碰人人干 | 久免费 | 国产高清免费在线播放 | 成人av一二三区 | 欧美日韩免费一区二区 | 亚洲精品在线一区二区 | 国产偷国产偷亚洲清高 | 日本精品在线 | 国产麻豆成人传媒免费观看 | aaa黄色毛片 | av电影 一区二区 | 久草在线 | 日韩在线观看影院 | 免费观看久久 | 成人在线一区二区三区 | 精品一区 精品二区 | 色亚洲激情 | 国产精品国产三级国产不产一地 | 99精品国产一区二区三区不卡 | 91在线网址 | 在线观看岛国片 | 欧美一级性生活片 | 夜夜骑日日操 | av短片在线 | 成人黄色国产 | 开心色停停 | 91丨九色丨91啦蝌蚪老版 | 国产午夜精品一区二区三区四区 | 九九九视频精品 | 亚洲日本激情 | 日韩午夜大片 | 中文字幕韩在线第一页 | 午夜在线看片 | av在线电影免费观看 | 天天干天天插 | 天天爱天天草 | 播五月婷婷 | 色综合天天色综合 | 97超碰人人模人人人爽人人爱 | 天天艹天天 | 国产精品久久久久永久免费 | 999成人免费视频 | 亚洲欧洲国产视频 | 中文字幕av在线电影 | 国产剧情一区二区 | 久久爽久久爽久久av东京爽 | 日韩精品三区四区 | 婷婷亚洲综合五月天小说 | 色偷偷网站视频 | 国产va精品免费观看 | 黄色软件在线观看免费 | 欧美午夜性 | 不卡的一区二区三区 | 国产乱老熟视频网88av | 亚洲欧洲精品久久 | 欧美激情片在线观看 | 国产91亚洲 | 懂色av懂色av粉嫩av分享吧 | 在线中文视频 | 免费av高清 | 国产精品婷婷午夜在线观看 | 久草剧场| 国产精品毛片一区视频播 | 麻豆视频免费入口 | 亚洲综合在线播放 | 一级黄色片在线免费看 | 黄色aaaaa| 人人干在线观看 | 久久国产精品免费一区二区三区 | 国产做a爱一级久久 | 一级黄色在线视频 | 91完整版观看 | 亚洲成人av一区二区 | 91精品婷婷国产综合久久蝌蚪 | 日韩在线观 | 99免费看片 | 国产精品欧美久久 | 成人av影视在线 | 人人爽影院 | 亚洲精品在线观看网站 | 天天操天天干天天干 | 日p视频在线观看 | 天天操天天谢 |