700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Java图形化界面编程之——AWT

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

时间:2021-02-24 00:29:19

相关推荐

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

目录

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(网格布局)

4.4、GridBagLayout(网格包布局)

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中常见事件和事件监听器

6.2.1、事件

6.2.2、事件监听器

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应用程序提供了基本的图形组件,但这个GUI库的功能比较有限,所以后来sun公司又提供了Swing库。通过使用AWT和Swing提供的图形化界面组件库,java的图形化界面编程非常简单,程序只需要依次创建所需的图形组件,并以合适的方式将这些组件组织在一起,就可以开发出非常美观的用户界面。

AWT是窗口框架,它从不同平台的窗口系统中抽取出共同组件,当程序运行时,将这些组件的创建和动作委托给程序所在的运行平台。简而言之,当使用AWT编写图形界面应用时,程序仅制定了界面组件的位置和行为,并为提供真正的实现,JVM调用操作系统本地的图形界面来创建和平台一致的对等体。

使用AWT创建的图形界面应用和所在的运行平台有相同的界面风格,比如在Windows操作系统上,它就表现出Windows风格;在UNIX操作系统上,它就表现出UNIX风格。Sun希望采用这种方式来实现“Write Once,Run Anywhere”的目标。

2、AWT继承体系

AWT继承体系

所有和AWT编程相关的类都放在java.awt包以及它的子包中。AWT编程中有两个基类:Component和MenuComponent:

Component:代表一个能以图形化方式显式出来,并可与用户交互的对象。MenuComponent:代表图形界面的菜单组件,包括MenuBar(菜单条)、MenuItem(菜单项)等子类。

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

AWT中还有一个非常重要的接口叫LayoutManager,如果一个容器中有多个组件,那么容器就需要使用LayoutManager来管理这些组件的布局方式。

接口LayoutManager:

GridLayoutFlowLayout...

3、Container容器

3.1、Container继承体系

Container容器:

1、Window窗口容器:

Frame:创建窗口

Dialog:创建对话框

2、Panel内嵌容器:

Applet

3、ScrollPane含有滚动条的容器

Window是可以独立存在的顶级窗口,默认使用BorderLayout管理其内部组件布局;Panel可以容纳其他组件,但不能独立存在,它必须内嵌其他容器中使用,默认使用FlowLayout管理其内部组件布局;ScrollPane是一个带滚动条的容器,它也不能独立存在,默认使用BorderLayout管理其内部组件布局。

3.2、常用API

3.2.1、Component的常用方法

Component作为基类,提供了如下常用的方法来设置组件的大小、位置、可见性等。

3.2.2、Container的常用方法

3.3、容器演示

3.3.1、Window

package Package1;import java.awt.*;public class FrameDemo {public static void main(String[] args) {//1、创建窗口对象Frame frame = new Frame("这是一个窗口容器Frame");//2、设置窗口的位置和大小frame.setLocation(100,100); //单位是像素frame.setSize(500,300); //单位是像素//3、设置窗口对象可见frame.setVisible(true);}}

3.3.2、Panel

package Package1;import java.awt.*;public class PanelDemo {public static void main(String[] args) {//1、创建一个Window对象,因为Panel以及其它的容器,都不能独立存在,必须依附于Window存在Frame frame = new Frame("这是一个窗口容器Frame");//2、创建一个Panel对象Panel p = new Panel();//3、创建一个文本框和一个按钮,并且把它们放入Panel容器中p.add(new TextField("这是一个测试文本"));p.add(new Button("这是一个测试按钮"));//4、把Panel放入Window中frame.add(p);//5、设置Window的位置和大小frame.setBounds(400,200,500,300);//6、设置Window可见frame.setVisible(true);}}

按钮文本显示乱码解决办法:依次点击Run -> Edit Configurations -> 左边选中要修改的项 -> 在右侧找到并点击Modify options -> 点击Add VM options -> 在新出现的框中输入 -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");//创建一个ScrollPane对象ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);sp.add(new TextField("这是测试文本"));sp.add(new Button("这是测试按钮"));//把ScrollPane添加到Frame中frame.add(sp);//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}}

程序明明向ScrollPane中添加了一个文本框和一个按钮,但只能看到一个按钮,却看不到文本框,这是因为ScrollPane使用BorderLayout布局管理器的缘故,BorderLayout导致了该容器中只有一个组件被显示出来。

4、LayoutManager布局管理器

如果要让我们的程序在不同的操作系统下,都有相同的体验,那么手动设置组件的位置和大小,无疑是一种灾难,因为有太多的组件,需要分别设置不同操作系统下的大小和位置。为了解决这个问题,Java提供了LayoutManager布局管理器,可以根据运行平台来自动调整组件大小,程序员不用再手动设置组件大小和位置了,只需要为容器选择合适的布局管理器即可。

AWT中接口LayoutManager有五个实现类:GridLayout(网格布局)、FlowLayout(流式布局)、CardLayout(卡片布局)、GridBagLayout(网格包布局)和BorderLayout(边框布局)。为了简化开发,Swing引入了一个新的布局管理器BoxLayout。

4.1、FlowLayout(流式布局)

在FlowLayout布局管理器中,组件像水流一样向某方向流动(排列),遇到障碍(边界)就折回,中心开始排列。在默认情况下,FlowLayout布局管理器从左向右排列所有组件,遇到边界就会折回下一行重新开始。

FlowLayout中组件的排列方向(从左向右、从右向左、从中间向两边等),该参数应该使用FlowLayout类的静态常量:FlowLayout.LEFT、FlowLayout.CENTER、FlowLayout.RIGHT。默认是左对齐。

FlowLayout中组件中间距通过整数设置,单位是像素,默认是5个像素。

代码演示:

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

4.2、BorderLayout(边框布局)

BorderLayout将容器分为EAST、SOUTH、WEST、CENTER五个区域,普通组件可以被放置在这5个区域的任意一个中。

当改变使用BorderLayout的容器大小时,NORTH、SOUTH和CENTER区域水平调整,而EAST、WEST和CENTER区域垂直调整,使用BorderLayout有如下两个注意点:

当向使用BorderLayout布局的容器中添加组件时,需要指定要添加到哪个区域中。如果没有指定添加到哪个区域中,则默认添加到中间区域中;如果向同一个区域中添加多个组件,后放入的组件会覆盖先放入的组件。

代码演示:

package Package1;import java.awt.*;public class BorderLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("这是一个窗口容器Frame");//通过setLayout()方法设置容器的布局管理器frame.setLayout(new BorderLayout(30,10));//往frame的指定区域添加组件frame.add(new Button("北侧按钮"),BorderLayout.NORTH);frame.add(new Button("南侧按钮"),BorderLayout.SOUTH);frame.add(new Button("东侧按钮"),BorderLayout.EAST);frame.add(new Button("西侧按钮"),BorderLayout.WEST);frame.add(new Button("中间按钮"),BorderLayout.CENTER);//通过pack()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}}

4.3、GridLayout(网格布局)

GridLayout布局管理器将容器分割成纵横线分隔的网格,每个网格所占的区域大小相同。当向使用GridLayout布局管理器的容器中添加组件时,默认从左到右、从上到下依次添加到每个网格中。与FlowLayout不同的是,放置在GridLayout布局管理器中的各组件的大小由组件所处的区域决定(每个组件将自动占满整个区域)。

代码演示:

package Package1;import java.awt.*;public class GridLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("这是一个窗口容器Frame");//通过setLayout()方法设置容器的布局管理器frame.setLayout(new BorderLayout());//创建一个Panel对象,里面存放一个TextField组件Panel p1 = new Panel();p1.add(new TextField(50));//把这个Panel添加到frame的北边区域frame.add(p1,BorderLayout.NORTH);//创建一个Panel对象,并且设置它的布局管理器为GridLayoutPanel p2 = new Panel();p2.setLayout(new GridLayout(3,5,4,4));//往Panel中添加内容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("."));//把当前的Panel添加到frame中frame.add(p2,BorderLayout.CENTER);//通过pack()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(500,200,400,250);//设置Frame可见frame.setVisible(true);}}

4.4、GridBagLayout(网格包布局)

GridBagLayout布局管理器的功能最强大,但也最复杂,与GirdLayout布局管理器不同的是,在GridBagLayout布局管理器中,一个组件可以跨越一个或多个网格,并且可以设置网格的大小互不相同,从而增加了布局的灵活性。当窗口的大小发生变化时,GridBagLayout布局管理器也可以准确地控制窗口各部分的拉伸。

由于在GirdBagLayout布局中,每个组件可以占用多个网格,此时,我们往容器中添加组件的时候,就需要具体地控制每个组件占用多少个网格,java提供的GridBagConstraints类,与特定的组件绑定,可以完成具体大小和跨越性的设置。

GirdBagConstraints API:

代码演示:

package Package1;import java.awt.*;public class GirdBagLayoutDemo {public static void main(String[] args) {//创建Frame对象Frame frame = new Frame("这是一个窗口容器Frame");//创建GridBagLayout对象GridBagLayout gbLayout = new GridBagLayout();//把Frame对象的布局管理器设置为GridBagLayoutframe.setLayout(gbLayout);//创建GridBagConstraints对象GridBagConstraints gbCon = new GridBagConstraints();/*设置所有的GridBagConstraints对象的fill属性为GridBagConstraints.BOTH。当有空白区域时,组件自动扩大占满空白区域*/gbCon.fill = GridBagConstraints.BOTH;//设置GridBagConstraints对象的weightx设置为1,表示横向扩展比例为1gbCon.weightx = 1;//把GridBagConstraints的weighty设置为1,表示纵向扩展比例为1gbCon.weighty = 1;//创建容量为10的Button数组并初始化Button[] btns = new Button[10];for (int i = 0; i < btns.length; i++) {btns[i] = new Button("按钮"+i);}//往frame中添加数组中的第0,1,2个ButtonaddComponent(frame,btns[0],gbLayout,gbCon);addComponent(frame,btns[1],gbLayout,gbCon);addComponent(frame,btns[2],gbLayout,gbCon);//把GridBagConstraints的gridwidth设置为GridBagConstraints.REMAINDER,表明当前组件是横向最后一个组件gbCon.gridwidth = GridBagConstraints.REMAINDER;//把Button数组中第3个按钮添加到frame中addComponent(frame,btns[3],gbLayout,gbCon);//把Button数组中第4个按钮添加到frame中addComponent(frame,btns[4],gbLayout,gbCon);//把GridBagConstraints的gridheight和gridwidth设置为2,表示纵向和横向会占用2个网格gbCon.gridwidth = 2;gbCon.gridheight = 2;//把Button数组中第5个按钮添加到frame中addComponent(frame,btns[5],gbLayout,gbCon);//把GridBagConstraints的gridheight和gridwidth设置为1,表示纵向会占用1个网格gbCon.gridwidth = 1;gbCon.gridheight = 1;//把Button数组中第6个按钮添加到frame中addComponent(frame,btns[6],gbLayout,gbCon);//把GridBagConstraints的gridwidth设置为GridBagConstraints.REMAINDER,表明当前组件是横向最后一个组件gbCon.gridwidth = GridBagConstraints.REMAINDER;//把Button数组中第7个按钮添加到frame中addComponent(frame,btns[7],gbLayout,gbCon);//把GridBagConstraints的gridheight设置为1,表示纵向会占用1个网格gbCon.gridwidth = 1;gbCon.gridheight = 1;//把Button数组中第8,9个按钮添加到frame中addComponent(frame,btns[8],gbLayout,gbCon);addComponent(frame,btns[9],gbLayout,gbCon);//设置frame为最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置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才可见。

代码演示:

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");//创建一个Panel,用来存储多张卡片Panel p1 = new Panel();//创建CardLayout对象,并且把该对象设置给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的中间区域frame.add(p1, BorderLayout.CENTER);//创建另外一个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("第三张");//创建一个事件监听器,监听按钮的点击动作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;}}};//把当前事件监听器和多个按钮绑定到一起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的南边区域frame.add(p2, BorderLayout.SOUTH);//通过pack()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400, 200, 500, 300);//设置Frame可见frame.setVisible(true);}}

4.6、BoxLayout(盒子布局)

为了简化开发,Swing引入了一个新的布局管理器BoxLayout。BoxLayout可以在垂直和水平两个方向上摆放GUI组件,BoxLayout提供了如下一个简单的构造器:

代码演示:

package Package1;import javax.swing.*;import java.awt.*;public class BoxLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("这是一个窗口容器Frame");//基于frame容器创建一个BoxLayout对象,并且该对象存放组件是垂直存放BoxLayout boxLayout = new BoxLayout(frame,BoxLayout.Y_AXIS);//把BoxLayout设置给frameframe.setLayout(boxLayout);//往frame中添加两个Button组件frame.add(new Button("按钮1"));frame.add(new Button("按钮2"));//通过pack()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}}

4.6.1、Box容器

为了更方便地使用BoxLayout,在java.swing包中,提供了一个新的容器Box,该容器地默认布局管理器就是BoxLayout,大多数情况下,使用Box容器去容纳多个GUI组件,然后再把Box容器作为一个组件,添加到其它地容器中,从而形成整体窗口布局。

代码演示:

package Package1;import javax.swing.*;import java.awt.*;public class BoxLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("这是一个窗口容器Frame");//创建一个水平排列组件的Box容器Box hBox = Box.createHorizontalBox();//往当前容器中添加两个按钮hBox.add(new Button("水平按钮1"));hBox.add(new Button("水平按钮2"));//创建一个垂直排列组件的Box容器Box vBox = Box.createVerticalBox();//往当前容器中添加两个按钮vBox.add(new Button("垂直按钮1"));vBox.add(new Button("垂直按钮2"));//把两个Box添加到Frame中展示frame.add(hBox,BorderLayout.NORTH);frame.add(vBox,BorderLayout.CENTER);//通过pack()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}}

通过上面的演示,我们会发现,被它管理的容器中的组件之间是没有间隔的,是不是特别的美观,但之前学习的几种布局,组件之间都会有一些间距,那使用BoxLayout如何给组件设置间距呢?

其实很简单,我们只需要在原有的组件需要间隔的地方,添加间隔即可,而每个间隔可以是一个组件,只不过该组件没有内容,仅仅起到一种分隔的作用。

Box类中,提供了几个方便的静态方法来生成这些间隔组件:

代码演示:

package Package1;import javax.swing.*;import java.awt.*;public class BoxLayoutDemo {public static void main(String[] args) {Frame frame = new Frame("这是一个窗口容器Frame");//创建一个水平排列组件的Box容器Box hBox = Box.createHorizontalBox();//往当前容器中添加两个按钮hBox.add(new Button("水平按钮1"));hBox.add(Box.createHorizontalGlue()); //该分隔在两个方向上都可以拉伸hBox.add(new Button("水平按钮2"));hBox.add(Box.createHorizontalStrut(20));hBox.add(new Button("水平按钮3"));//创建一个垂直排列组件的Box容器Box vBox = Box.createVerticalBox();//往当前容器中添加两个按钮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()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}}

5、AWT中常用组件

5.1、基本组件

这些AWT组件的用法比较简单,可以查阅API文档来获取它们的各自构造方法、成员方法等详细信息。

代码演示:

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的中间区域Box top = Box.createHorizontalBox();top.add(topLeft);colorList.add("红色");colorList.add("绿色");colorList.add("蓝色");top.add(colorList);frame.add(top,BorderLayout.CENTER);//组装底部为bBox,并放置在frame的南边区域Box bBox = Box.createHorizontalBox();bBox.add(tf);bBox.add(ok);frame.add(bBox,BorderLayout.SOUTH);//通过pack()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}public static void main(String[] args) {new BasicComponentDemo().init();}}

5.2、Dialog(对话框)

Dialog是Window类的子类,是一个容器类,属于特殊组件。Dialog是可以独立存在的顶级窗口,因此用法与普通窗口的用法几乎完全一样,但是使用对话框需要注意下面两点:

对话框通常依赖于其它窗口,就是通常需要有一个父窗口;对话框有非模式(non-modal)和模式(modal)两种。当某个模式对话框被打开后,该模式对话框总是位于它的父窗口之上,在模式对话框被关闭之前,父窗口无法获得焦点。

代码演示:

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");//创建两个对话框Dialog对象,一个模式的,一个非模式的Dialog mDialog = new Dialog(frame,"模式对话框",true);Dialog dialog = new Dialog(frame,"非模式对话框",false);//通过setBounds()方法设置Dialog 的位置及大小mDialog.setBounds(200,100,500,300);dialog.setBounds(200,100,500,300);//创建两个按钮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()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}}

5.2.1、FileDialog(文件对话框)

Dialog类还有一个子类FileDialog,它代表一个文件对话框,用于打开或者保存文件,需要注意的是FileDialog无法确定模态或者非模态,这是因为FIleDialog依赖于运行平台的实现,如果运行平台的文件对话框是模态的,那么FileDialog也是模态的;否则就是非模态的。

代码演示:

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");//创建2个FileDialog对象FileDialog f1 = new FileDialog(frame,"选择要打开的文件",FileDialog.LOAD);FileDialog f2 = new FileDialog(frame,"选择要保存的路径",FileDialog.SAVE);//创建两个按钮Button b1 = new Button("打开文件");Button b2 = new Button("保存文件");//给这两个按钮设置点击后的行为:获取打开或者保存的路径文件名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()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}}

6、事件处理

前面介绍了如何放置各种组件,从而得到了丰富多彩的图形界面,但这些界面还不能响应用户的任何操作。因为在AWT编程中,所有用户的操作,都必须要经过一套事件处理机制来完成,而Frame和组件本身没有事件处理能力。

6.1、GUI事件处理机制

定义:当在某个组件上发生某个操作的时候,会自动地触发一段代码的执行。

在GUI事件处理机制中涉及到4个重要的概念需要理解:

事件源(Event Source):操作发生的场所,通常指某个组件,例如按钮、窗口等。事件(Event):在事件源上发生的操作可以叫作事件,GUI会把事件都封装到一个Event对象中,如果需要直到该事件的详细信息,就可以通过Event对象来获取。事件监听器(Event Listener):当在某个事件源上发生了某个事件,事件监听器就可对这个事件进行处理。注册监听:把某个事件监听器(A)通过某个事件(B)绑定到某个事件源(C)上,当在事件源C上发生了事件B之后,那么事件监听器A的代码就会自动执行。

使用步骤:

创建事件源组件对象;自定义类,实现XxxListener接口,重写方法;创建事件监听器对象(自定义类对象);调用事件源组件对象的addXxxListener方法完成注册监听。

代码演示:

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(); //创建自定义监听器对象ok.addActionListener(myListener); //注册监听//把tf和ok翻入frame中frame.add(tf,BorderLayout.NORTH);frame.add(ok);//通过pack()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}//自定义事件监听器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中常见事件和事件监听器

事件监听器必须实现事件监听器接口,AWT提供了大量的事件监听器接口用于实现不同类型的事件监听器,来监听不同类型的事件。AWT中提供了丰富的事件类,用于封装不同组件上所发生的特定操作,AWT的事件类都是AWTEvent类的子类,AWTEvent类是EventObject类的子类。

6.2.1、事件

AWT把事件分为了两大类:

1、低级事件:这类事件是基于某个特定动作的事件。比如进入、点击、拖放等动作的鼠标事件,再比如得到焦点和失去焦点等焦点事件。

2、高级事件:这类事件并不会基于某个特定动作,而是根据功能含义定义的事件。

6.2.2、事件监听器

不同的事件需要使用不同的事件监听器监听,不同的监听器需要实现不同的监听器接口,当指定事件发生后,事件监听器就会调用所包含的事件处理器(实例方法)来处理事件。

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();//创建组件TextField tf = new TextField(30);Choice names = new Choice();names.add("张三");names.add("李四");names.add("王五");//给文本域添加TextListener,监听内容的变化tf.addTextListener(new TextListener() {@Overridepublic void textValueChanged(TextEvent e) {String text = tf.getText();System.out.println("当前文本框的内容为:"+text);}});//给下拉选择框添加ItemListener,监听条目选项的变化names.addItemListener(new ItemListener() {@Overridepublic void itemStateChanged(ItemEvent e) {Object item = e.getItem();System.out.println("当前选中的条目为:"+item);}});//给frame注册ContainerListener监听器,监听容器中组件的添加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()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}}

案例2:给Frame设置WindowListener,监听用户点击x的动作,如果用户点击x,则关闭当前窗口。

package Package1;import java.awt.*;import java.awt.event.*;public class ListenerDemo {public static void main(String[] args) {Frame frame = new Frame();//设置WindowListener,监听用户点击x的动作,如果点击x,则关闭窗口frame.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {//停止当前程序System.exit(0); //退出JVM}});//通过pack()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}}

7、菜单组件

在实际开发中,除了主界面,还有一类比较重要的内容就是菜单相关组件,可以通过菜单相关组件很方便地使用特定的功能。在AWT中,菜单相关组件的使用和之前学习的组件是一模一样的,只需要把菜单条、菜单、菜单项组合到一起,按照一定的布局,放入到容器中即可。

下表给出常用的菜单相关组件:

下图是常见菜单相关组件继承体系图:

菜单相关组件使用:

准备菜单项组件,这些组件可以是MenuItem及其子类对象;准备菜单组件Menu或者PopupMenu(右击弹出菜单),把第一步中准备好的菜单项组件添加进来;准备菜单条组件MenuBar,把第二步中准备好的菜单组件Menu添加进来;把第三步中准备好的菜单条组件添加到窗口对象中显示。

小技巧:

如果要在某个菜单的菜单项之间添加分割线,那么只需要调用Menu的add(new MenuItem("-"));即可;如果要给某个菜单项关联快捷键功能,那么只需要在创建菜单项对象时设置即可,例如给菜单项关联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");//创建菜单条MenuBar menuBar = new MenuBar();//创建菜单组件Menu fileMenu = new Menu("文件");Menu editMenu = new Menu("编辑");Menu formatMenu = new Menu("格式");//创建菜单项组件MenuItem auto = new MenuItem("自动换行");MenuItem copy = new MenuItem("复制");MenuItem paste = new MenuItem("粘贴");MenuItem comment = new MenuItem("注释",new MenuShortcut(KeyEvent.VK_Q,true)); //关联快捷键ctrl+shift+QMenuItem cancelComment = new MenuItem("取消注释");//创建文本框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()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置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");//创建文本域TextArea ta = new TextArea("默认显示的文本\n",6,40);//创建Panel容器Panel p = new Panel();//创建PopupMenuPopupMenu popupMenu = new PopupMenu();//创建菜单项MenuItem comment = new MenuItem("注释");MenuItem cancelComment = new MenuItem("取消注释");MenuItem copy = new MenuItem("复制");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);//设置Panel的大小p.setPreferredSize(new Dimension(400,100));//给Panel注册鼠标事件,监听用户释放鼠标的动作,展示菜单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()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}public static void main(String[] args) {new MenuDemo().init();}}

8、绘图

很多程序如各种游戏都需要在窗口中绘制各种图形,除此之外,即使在开发javaEE项目时,有时候也必须“动态”地向客户端生成各种图形、图标,比如图形验证码、统计图等,这都需要利用AWT地绘图功能。

8.1、组件绘图原理

之前我们已经学过很多组件,例如Button、Frame。Checkbox等等,不同的组件,展示出来的图形都不一样,其实这些组件展示出来的图形,其本质就是用AWT的绘图来完成的。

在AWT中,真正提供绘图功能的是Graphics对象,那么Component组件和Graphics对象存在什么关系,才能让Component绘制自身图形呢?在Component类中,提供了下列三个方法来完成组件图形的绘制与刷新:

paint(Graphics g):绘制组件的外观;update(Graphics g):调用内部paint方法,刷新组件外观;repaint():调用update方法,刷新组件外观。

一般情况下,update和paint方法是由AWT系统负责调用,如果程序要希望系统重新绘制组件,可以调用repaint()方法完成。

8.2、Graphics对象的使用

AWT中提供了Canvas类充当画布,提供了Graphics类来充当画笔,通过调用Graphics对象的setColor()方法可以给画笔设置颜色。

画图的步骤:

自定义类,继承Canvas类,重写paint(Graphics g)方法完成画图;在paint()方法内部,真正开始画图之前调用Graphics对象的setColor()、setFont()等方法设置画笔的颜色、字体等属性;调用Graphics画笔的drawXxx()方法开始画图。

其实画图的核心就在于使用Graphics画笔在Canvas画布上画出什么颜色、什么样式的图形,所以核心在画笔上,下表给出了Graphics类中常用的一些方法:

案例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("绘制椭圆");//创建Panel,承载按钮Panel p = new Panel();//定义一个变量,记录当前要绘制椭圆还是矩形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); //设置当前画笔的颜色为黑色g.drawRect(50,100,100,50);}else if(shape.equals(OVAL_SHAPE)) {//绘制椭圆g.setColor(Color.RED); //设置当前画笔的颜色为红色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; //修改标记的值为rectdrawArea.repaint();}});btnOval.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {shape = OVAL_SHAPE; //修改标记的值为rectdrawArea.repaint();}});//设置drawArea的大小drawArea.setPreferredSize(new Dimension(300,200));frame.add(drawArea);p.add(btnRect);p.add(btnOval);frame.add(p,BorderLayout.SOUTH);//通过pack()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}public static void main(String[] args) {new GraphicsDemo().init();}}

Java也可用于开发一些动画,就是间隔一定的时间(通常小于0.1秒)重新绘制新的图像,两次绘制的图像之间差异较小,肉眼看起来就成了所谓的动画。为了实现间隔一定时间就重新调用组件的repaint()方法,可以借助于Swing提供的Timer类,Timer类是一个定时器,它有如下一个构造器:Timer(int delay, ActionListener listener):每间隔delay毫秒,系统自动触发ActionListener监听器里的事件处理器方法,在方法内部我们就可以调用组件的repaint()方法,完成组件重绘。

案例2——弹球小游戏:

package Package1;import javax.swing.*;import java.awt.*;import java.awt.event.*;public class GraphicsDemo {//创建窗口对象private Frame frame = new Frame("这是一个窗口容器Frame");//设置桌面宽度和高度private final int TABLE_WIDTH = 300;private final int TABLE_HEIGHT = 400;//设置球拍的宽度和高度private final int RACKET_WIDTH = 60;private final int RACKET_HEIGHT = 20;//定义变量,记录球拍的坐标private int racketX = 120;private final int racketY = 340;//设置小球的大小private final int BALL_SIZE = 16;//定义变量,记录小球的坐标private int ballX = 120;private int ballY = 20;//定义变量,记录小球在x和y方向上分别移动的速度private int speedX = 5;private int speedY = 0;//定义变量,表示当前游戏是否已结束private boolean isOver = false;//声明一个定时器private Timer timer;//自定义一个类继承Canvas充当画布private class MyCanvas extends Canvas {@Overridepublic void paint(Graphics g) {//在这里绘制内容if (isOver) {//游戏结束g.setColor(Color.BLUE);g.setFont(new Font("Times", Font.BOLD, 30));g.drawString("游戏结束!", 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);}}}//创建绘画区域MyCanvas myCanvas = new MyCanvas();//组装视图以及游戏逻辑的控制public void init() {//完成球拍坐标的变化KeyListener listener = new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {//获取当前按下的键int keyCode = e.getKeyCode();if (keyCode == KeyEvent.VK_LEFT) {//<- 应该向左移动if (racketX > 0) {racketX -= 10;}}if (keyCode == KeyEvent.VK_RIGHT) {//-> 应该向右移动if (racketX < TABLE_WIDTH - RACKET_WIDTH) {racketX += 10;}}}};MouseMotionListener mouseMotionListener = new MouseMotionAdapter() {@Overridepublic void mouseMoved(MouseEvent e) {//获取当前鼠标位置int mouseX = e.getX();if (mouseX < (RACKET_WIDTH / 2)) {//设置球拍的位置racketX = 0;} else if (mouseX > (TABLE_WIDTH - RACKET_WIDTH / 2)) {racketX = TABLE_WIDTH - RACKET_WIDTH;} else {racketX = mouseX - (RACKET_WIDTH / 2);}}};//给frame和myCanvas注册监听器frame.addKeyListener(listener);myCanvas.addKeyListener(listener);myCanvas.addMouseMotionListener(mouseMotionListener);frame.addMouseMotionListener(mouseMotionListener);//完成小球坐标的变化ActionListener task = new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//更新小球的坐标speedY += 1;ballX += speedX;ballY += speedY;//根据边界范围,修正速度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))) {//当小球超出了球拍的范围,游戏结束//停止定时器timer.stop();//修改游戏是否结束的标记isOver = true;}//重绘界面myCanvas.repaint();}};timer = new Timer(30, task);timer.start();//myCanvas.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT));frame.add(myCanvas);//通过pack()方法设置最佳大小frame.pack();//设置Frame可见frame.setVisible(true);}public static void main(String[] args) {new GraphicsDemo().init();}}

8.3、处理位图

如果仅仅绘制一些简单的几何图形,程序的图形效果依然比较单调。AWT也允许在组件上绘制位图,Graphics提供了drawImage(Image image)方法用于绘制位图,该方法需要一个Image参数代表位图,通过该方法就可以绘制出指定的位图。

位图使用步骤:

创建Image的子类对象BufferedImage(int width, int height, int ImageType),创建时需要指定位图的宽高及类型属性;此时相当于在内存中生成了一张图片;调用BufferedImage对象的getGraphics()方法获取画笔,此时就可以往内存中的这张图片上绘图了,绘图的方法和之前学习的一模一样;调用组件paint方法中提供的Graphics对象的drawImage()方法,一次性地将内存中地图片BufferedImage绘制到特定的组件上。

使用位图绘制组件的好处:

使用位图来绘制组件,相当于实现类图的缓冲区,此时绘图时没有直接把图形绘制到组件上,而是先绘制到内存中的BufferedImage上,等全部绘制完毕,再一次性地将图像显示到组件上即可,这样用户的体验会好一些。

代码演示:

package Package1;import java.awt.*;import java.awt.event.*;import java.awt.image.BufferedImage;public class ImageDemo {//定义窗口对象Frame frame = new Frame("这是一个窗口容器Frame");//定义画图区的宽高private final int AREA_WIDTH = 500;private final int AREA_HEIGHT = 400;//定义一个右键菜单,用于设置画笔的颜色private PopupMenu colorMenu = new PopupMenu();private MenuItem redItem = new MenuItem("红色");private MenuItem greenItem = new MenuItem("绿色");private MenuItem blueItem = new MenuItem("蓝色");//定义一个变量,记录当前画笔的颜色,默认为黑色private Color forceColor = Color.BLACK;//创建一个BufferedImage位图对象BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_RGB);//通过位图,获取关联的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();//定义变量,记录鼠标拖动过程中,上一次所处的坐标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设置给绘图区域myCanvasmyCanvas.add(colorMenu);myCanvas.addMouseListener(new MouseAdapter() {@Override//当鼠标键抬起时被调用public void mouseReleased(MouseEvent e) {boolean popupTrigger = e.isPopupTrigger();if (popupTrigger) {colorMenu.show(myCanvas, e.getX(), e.getY());}//重置preX和preYpreX = -1;preY = -1;}});//设置位图的背景为白色g.setColor(Color.WHITE);g.fillRect(0, 0, AREA_WIDTH, AREA_HEIGHT);//通过监听鼠标的移动,完成绘制myCanvas.addMouseMotionListener(new MouseMotionAdapter() {@Override//该方法,当鼠标左键按下,并进行拖动时,会被调用public void mouseDragged(MouseEvent e) {if (preX > 0 && preY > 0) {g.setColor(forceColor);//画线条,需要两组坐标,分别代表线条的起点和终点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的使用

在实际生活中,很多软件都支持打开本地磁盘已经存在的图片,然后进行编辑,编辑完毕后,再重新保存到本地磁盘。如果使用AWT要文成这样的功能,那么需要使用到ImageIO这个类,可以操作本地磁盘的图片文件。

代码演示:

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对象,记录本地读取到内存中的图片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);//获取用户设置的保存路径以及文件名称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()方法设置最佳大小frame.pack();//设置Frame的位置和大小frame.setBounds(400,200,500,300);//设置Frame可见frame.setVisible(true);}public static void main(String[] args) {new LASImage().init();}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。