【10-AWT编程】
|
AWT编程 图形用户界面
•作为一个程序设计者,必须优先考虑用户的感受,一定要让用户感到“爽”,我们的程序才会被需要、 被使用,这样的程序才有价值。
•当JDK1.0发布时,Sun提供了一个基本的GUI类库,这个GUI类库希望可以在所有平台下都能运 行,这套基本类库被称为“抽象窗口工具集(Abstract Window Toolkit)”,它为Java应用程序提 供了基本的图形组件。 AWT简介
•当JDK1.0发布时,Sun提供了一个基本的GUI类库,这个GUI类库希望可以在所有平台下都能运 行,这套基本类库被称为“抽象窗口工具集(Abstract Window Toolkit)”,它为Java应用程序提 供了基本的图形组件。
•AWT (Abstract Window Tools):抽象窗口工具
AWT的问题
•使用AWT作出的图形用户界面在所有平台上都显得很丑陋,功能也非常有限。
•AWT为了迎合所有主流操作系统的界面设计,AWT组件只能使用这些操作系统上图形界面组件的交 集,所以不能使用特定操作系统上复杂的图形界面组件,最多只能使用四种字体。
•AWT用的是非常笨拙的,非面向对象的编程模式。
Swing组件
•Swing为绝大部分的界面组件都提供了实现。这些界面组件都是直接绘制空白区域上。 •Swing自己实现了这些界面组件,因此Swing无需使用各操作系统上界面组件的交集。 •由于Swing不再需要调用操作系统上相应的界面组件,Swing的UI界面更加统一。 java.awt包 在这个包中,提供了基本的java程序GUI设计工具: –Component/MenuComponent –Container –LayoutManager
Container(容器)
•容器(Container)实际上是Component的子类,因此容器类对象本身也是一个组件,具有组件的所 有性质,另外还具有容纳其它组件和容器的功能。 •容器类对象可使用方法add()添加组件 •两种主要的容器类型 –Window:可独立存在的顶级窗口 –Panel:可作为容器容纳其它组件,但不能独立存在,必须被添加到其它容器中(如Window 或 Applet) Container层次关系图
Container常用方法
•add() •setLocation():设置位置。 •setSize():设置大小 •setBoundes():同时设置大小、位置。 •setVisible() •pack() 组件定制
•组件的大小和位置由布局管理器(LayoutManager)决定。
•不使用布局管理器则可以定制组件的大小和位置,但必须在容器中使用组件的setLocation(), setSize(), setBounds()方法确定大小位置
Frame类
•代表一个窗口。 •是Window类的子类 •有标题,可通过拖拉改变大小 •初始化时为不可见,可用setVisible(true)使其显示出来 •使用BorderLayout作为其缺省布局管理器 •使用setLayout方法改变布局管理器
Panel
•为放置组件提供空间 •允许使用自己的布局管理器 •不能单独存在,必须放置到其他容器中 Container的布局管理器
•为了使我们生成的图形用户界面具有良好的平台无关性,Java语言中,提供了布局管理器这个工具 来管理组件在容器中的布局,而不使用 直接设置组件位置和大小的方式。
•AWT中的布局管理器有:
–FlowLayout
–BorderLayout
–GridLayout
–CardLayout
–GridBagLayout
FlowLayout
•GUI Component从左到右按顺序配置在Container中,若到达右边界,则会折回到下一行中 •FlowLayout是Panel和Applet的默认管理器 •FlowLayout()/ FlowLayout(int align)/ FlowLayout(int align,int hgap,int vgap) •FlowLayout.LEFT/ FlowLayout.CENTER/ FlowLayout.RIGHT •默认为靠中对齐 •使用组件的理想尺寸 BorderLayout
•BorderLayout将Container分为EAST、SOUTH、WEST、NORTH、CENTER五个区域, Component可以放置在这五个区域的任何一个
•BorderLayout是Frame、Dialog的默认管理器 •每个区域只能放一个组件。如果在一个区域中放入多个Component,后放入的Component会把前 面的覆盖
•BorderLayout()/ BorderLayout(int hgap,int vgap)
• BorderLayout.EAST、BorderLayout.SOUTH、BorderLayout.WEST、 BorderLayout.SOUTH、BorderLayout.CENTER
•BorderLayout布局格式:当改变容器大小时
–当某个区域没有组件时,它的空间会被自动占满。
–North, South和Center区域水平调整
–East, West和Center区域垂直调整
GridLayout
•GridLayout将Component配置在纵横格线分割的格子中,从左到右,从上到下;
•构造器:GridLayout()/ GridLayout(int rows,int cols)/ GridLayout(int rows,int cols,int hgap,int vgap)
GridBagLayout
•GridBagLayout布局管理器是功能最强大,但也是最复杂的布局管理器,与GridLayout布局管理 器不同的是:在GridBagLayout布局管理器中,一个组件可以跨越一个或多个网格,并可以设置各网 格的大小互不相同,从而增加了布局的灵活性。当窗口的大小发生变化时,GridBagLayout布局管理 也可以准确地控制窗口各部分的反应。
•为了处理GridBagLayout中GUI组件的大小、跨越性,Java提供了GridBagConstraints对象, 该对象与特定的GUI组件关联,用于控制该GUI组件的大小、跨越性。
CardLayout
•将加入到Container中的Component看成一叠卡片,只有最上面的那个Componet才可见 •构造器:CardLayout()/ CardLayout(int hgap,int vgap) •控制组件可见的方法:first(Container target) / last(Container target) /previous(Container target) /next(Container target) /show(Container target,String name)
绝对定位
•Java也提供了那种拖控件的方式,即Java也可以对GUI组件进行绝对定位。在Java容器中采用绝对 定位的步骤如下: –(1)将Container的布局管理器设成null:setLayout(null)。 –(2)往容器上加组件的时候,先调用setBounds()或setSize()方法来先设置组件的大小、位 置。或者直接创建GUI组件时通过构造参数指定该组件的大小、位置,然后将该组件添加到容器 中。
BoxLayout布局管理器
•GridBagLayout布局管理器虽然功能强大,但它实在太复杂了,以Swing引入了一个新的布局管理 器:BoxLayout。它保留了GridBagLayout的很多优点,但是却没那么复杂。BoxLayout可以在垂 直和水平两个方向上摆放GUI组件,BoxLayout提供了一个如下的简单构造器:
•BoxLayout(Container target, int axis):指定创建基于target容器的BoxLayout布局管理 器,该布局管理器里组件按axis方向排列。其中axis有BoxLayout.X_AXIS(横向)和 BoxLayout.Y_AXIS(纵向)两个方向。
基本组件
•Button:按钮,可接收单击操作。 •Canvas:用于绘图的画布。 •Checkbox:复选框组件(也可变成单选框组件)。 •CheckboxGroup:用于将多个Checkbox组件组合成一组,一组Checkbox组件将只有一个可以被选中,即全部变成单选框组件。 •Choice:下拉式选择框组件。 •Frame:窗口,在GUI程序里通过该类创建窗口。 •Label:标签类,用于放置提示性文本。 •List。列表框组件,可以添加多项条目。 •Panel:不能单独存在基本容器类,必须放到其他容器中。 •Scrollbar:滑动条组件。如果需要用户输入位于某个范围的值,就可以使用滑动条组件。如调色板中设置RGB的三个值所用的滑动条。当创建一个滑动条时,必须指定它的方向、初始值、滑块的大小、最小值和最大值。 •ScrollPane:带水平及垂直滚动条的容器组件。 •TextArea:多行文本域。 •TextField:单行文本框。 对话框
•对话框是Window类的子类,是一个容器类,属于特殊组件。对话框也是可以独立存在的顶级窗口,因此用法与普通窗口用法几乎完全一样。但对话框有两点需要注意: –对话框必须依赖于其他窗口,就是必须有一个parent窗口。 –对话框有非模式(non-modal)和模式(modal)两种,当某个模式对话框被打开之后,该模式对话框总是位于它依赖的窗口之上;在模式对话框被关闭之前,它依赖的窗口无法获得焦点。 •对话框有多个重载的构造器,它的构造器可能有如下三个参数: –owner:指定该对话框所依赖的窗口,既可以是窗口,也可以是对话框。 –title:指定该对话框的窗口标题。 –modal:指定该对话框是否是模式的,可以是true或false。
FileDialog
•Dialog类还有一个子类:FileDialog,它代表一个文件对话框,用于打开、或者保存文件, FileDialog也提供了几个构造器,分别可支持parent、title和mode三个构造参数,其中parent、 title指定文件对话框的所属父窗口和标题,而mode用于指定该窗口用于打开文件、或保存文件,该参 数支持如下两个参数值:FileDialog.LOAD、FileDialog.SAVE。
事件处理
•事件(Event) – 一个对象,它描述了发生什么事情 •事件源(Event source) – 产生事件的组件 •事件处理方法(Event handler) – 能够接收、解析和处理事件类对象、实现和用户交互的方法 AWT的事件处理方式
•委派式事件处理(delegation)----个别的组件将整个事件处理委托给特定的对象,当该组件发生 指定的事件时,就通知所委托的对象,有这个对象来处理这个事件。这个受委托处理事件的对象称为事 件倾听对象(event listener)
•每个组件均可以针对特定的事件指定一个或多个事件倾听对象,由这些事件倾听对象负责处理事件
AWT事件分类
窗口事件
•当一个窗口被激活、撤销激活、打开、关闭、最大化、最小化时,发生窗口事件。 •从WindowEvent类中创建的对象表示窗口事件。
不同事件类型的接口和方法
事件适配器(Adapter)
•为简化编程,针对大多数事件监听器接口定义了相应的实现类----事件适配器类,在适配器类中,实现了相应监听器接口中所有的方法,但不做任何事情。 •在定义监听器类时就可以继承事件适配器类,并只重写所需要的方法。 事件处理类的形式
•利用内部类来处理事件 •用匿名内部类处理事件 •定义一个事件监听器类 •直接在当前类中处理
创建菜单
•创建一个菜单步骤: –创建一个MenuBar对象,将其放置到菜单容器中(如Frame) –创建若干个Menu对象,将其放置到MenuBar对象中 –创建若干个MenuItem对象,将其放置到Menu对象中 •MenuItem包括 –MenuItem:普通的菜单项 –CheckboxMenuItem:可以选择的菜单项
右键菜单
•右键菜单使用PopupMenu对象表示,创建右键菜单的步骤如下: •(1)创建PopupMenu的实例。 •(2)创建多个MenuItem实例,依次将这些实例加入PopupMenu中。 •(3)将PopupMenu加入到目标组件之中。 •(4)为需要出现上下文菜单的组件编写鼠标监听器,当用户释放鼠标右键时弹出右键菜单。
在AWT中画图
•通常,创建Canvas类或Panel的子类,并覆盖paint方法 •每当组件出现时调用paint方法 •每个组件都有一个Graphics对象 •Graphics类实现了很多绘图方法 AWT中的坐标
Graphics类
•Graphics是一个抽象的画笔对象,Graphics可以在组件上绘制丰富多彩的几何图形和位图,Graphics类提供了如下几个方法用于绘制几何图形和位图: –drawLine:绘制直线。 –drawString:绘制字符串。 –drawRect:绘制矩形。 –drawRoundRect:绘制圆角矩形。 –drawOval:绘制椭圆形状。 –drawPolygon:绘制多边形边框。 –drawArc:绘制一段圆弧(可能是椭圆的圆弧)。 –drawPolyline:绘制折线。 –fillRect:填充一个矩形区域。 –fillRoundRect:填充一个圆角矩形区域。 –fillOval:填充椭圆区域。 –fillPolygon:填充一个多边形区域。 –fillArc:填充圆弧和圆弧两个端点到中心连线所包围的区域。 –drawImage:绘制位图。
BufferedImage实现类
•Image类代表了位图,但它是一个抽象类,无法直接创建Image对象,为此Java为它提供了一个 BufferedImage实现类,它是一个可访问图像数据缓冲区的Image实现类。该类提供了一个简单的 构造器,用于创建一个BufferedImage对象:
–BufferedImage(int width, int height, int imageType):创建指定大小、指定图象类型的 BufferedImage对象,其中imageType可以是BufferedImage.TYPE_INT_RGB、 BufferedImage.TYPE_BYTE_GRAY等值。
•除此之外,BufferedImage还提供了一个getGraphics()方法返回该对象的Graphics对象,从而 允许通过该Graphics对象向Image中添加图形。
•借助于BufferedImage的帮助,我们可以在AWT中实现缓冲技术:当我们需要向GUI组件上绘制 图形时,不要直接绘制到该GUI组件上,而是先将图形绘制到BufferedImage对象中,然后再调用 组件的drawImage一次性地将BufferedImage对象绘制到特定组件上。
ImageIO输入/输出位图
•ImageIO类并不能支持读写全部格式的图形文件,程序可以通过ImageIO类的如下几个静态方法来访问该类所支持读写的图形文件格式: –getReaderFileSuffixes():返回一个 String 数组,该数组列出ImageIO所有能读的图形文件的文件后缀。 –getReaderFormatNames():返回一个 String 数组,该数组列出ImageIO所有能读的图形文件的非正式格式名称。 –static String[] getWriterFileSuffixes()::返回一个 String 数组,该数组列出ImageIO所有能写的图形文件的文件后缀。 –static String[] getWriterFormatNames():返回一个 String 数组,该数组列出ImageIO所有能写的图形文件的非正式格式名称。
剪贴板
•AWT支持两种剪贴板:系统剪贴板和本地剪贴板,如果在同一个虚拟机的不同窗口之间进行数据传 递,则无需使用本地剪贴板,使用系统剪贴板就可以了。系统剪贴板则与运行平台无关,可以传输任意 格式的数据。
使用系统剪贴板
•Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
•传递文本是最简单的情形,因为AWT已经提供了一个StringSelection用于传输文本字符串。
•传递图片需要自己实现Transferable 对象。Transferable接口代表了可以放入剪贴板的传输对 象,所以如果我们希望将图像放如剪贴板内,必须提供一个Transferable接口的实现类,该实现类其 实很简单,它封装一个image对象,并且向外表现为imageFlavor的内容。
使用本地剪贴板
•本地剪贴板可以保存任何类型的Java对象。为了将任意类型的对象保存到剪贴板中,DataFlavor里 提供了提供了一个javaJVMLocalObjectMimeType的常量将Java对象放入本地剪贴板必须使用该 MIME类型,该MIME类型表示仅将对象引用复制到剪贴板中,对象引用只有在同一个虚拟机中才有 效,所以只能使用本地剪贴板。
•创建本地剪贴板的代码如下: –Clipboard clipboard = new Clipboard("cp"); •Java并没有提供封装对象引用的Transferable实现类,因此我们必须自己实现该接口,实现该接口 与前面的ImageSelect 基本相似,一样要实现该接口的三个方法,并持有某个对象的引用。
使用系统剪贴板传递Java对象
•系统剪贴板不仅支持传输文本、图像的基本内容,也可以传输支持序列化的Java对象和远程对象,复 制到剪贴板中序列化Java对象和远程对象可以使用另一个Java程序(不在同一个虚拟机内的程序)来 读取。DataFlavor中提供了javaSerializedObjectMimeType、 javaRemoteObjectMimeType两个字符串常量来表示序列化Java对象和远程对象的MIME类型, 这两种MIME类型提供了复制对象、读取对象所包含的复杂操作,程序只需创建对应的Tranferable 实现类即可。
•使用系统剪贴板传递Java对象需要实现SerialSelection类,该类与前面的ImageSelection、 LocalSelection实现类相似,都需要实现Tranferable接口,实现该接口的三个方法,并持有一个可 序列化的对象。
现在贴出代码:
public class FrameTest { public static void main(String[] args) { Frame f = new Frame("测试窗口"); // 设置窗口的大小、位置 f.setBounds(30, 30, 250, 200); // 将窗口显示出来(Frame对象默认处于隐藏状态) f.setVisible(true); } }
public class PanelTest { public static void main(String[] args) { Frame f = new Frame("测试窗口"); // 创建一个Panel容器 Panel p = new Panel(); // 向Panel容器中添加两个组件 p.add(new TextField(20)); p.add(new Button("单击我")); // 将Panel容器添加到Frame窗口中 f.add(p); // 设置窗口的大小、位置 f.setBounds(30, 30, 250, 120); // 将窗口显示出来(Frame对象默认处于隐藏状态) f.setVisible(true); } }
public class ScrollPaneTest { public static void main(String[] args) { Frame f = new Frame("测试窗口"); // 创建一个ScrollPane容器,指定总是具有滚动条 ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); // 向ScrollPane容器中添加两个组件 sp.add(new TextField(20)); sp.add(new Button("单击我")); // 将ScrollPane容器添加到Frame对象中 f.add(sp); // 设置窗口的大小、位置 f.setBounds(30, 30, 250, 120); // 将窗口显示出来(Frame对象默认处于隐藏状态) f.setVisible(true); } }
public class BorderLayoutTest { public static void main(String[] args) { Frame f = new Frame("测试窗口"); // 设置Frame容器使用BorderLayout布局管理器 f.setLayout(new BorderLayout(30, 5)); f.add(new Button("南"), SOUTH); f.add(new Button("北"), NORTH); // 默认添加到中间 f.add(new Button("中")); f.add(new Button("东"), EAST); f.add(new Button("西"), WEST); // 设置窗口为最佳大小 f.pack(); // 将窗口显示出来(Frame对象默认处于隐藏状态) f.setVisible(true); } }
public class BorderLayoutTest2 { public static void main(String[] args) { Frame f = new Frame("测试窗口"); // 设置Frame容器使用BorderLayout布局管理器 f.setLayout(new BorderLayout(30, 5)); f.add(new Button("南"), SOUTH); f.add(new Button("北"), NORTH); // 创建一个Panel对象 Panel p = new Panel(); // 向Panel对象中添加两个组件 p.add(new TextField(20)); p.add(new Button("单击我")); // 默认添加到中间,向中间添加一个Panel容器 f.add(p); f.add(new Button("东"), EAST); // 设置窗口为最佳大小 f.pack(); // 将窗口显示出来(Frame对象默认处于隐藏状态) f.setVisible(true); } }
public class BoxLayoutTest { private Frame f = new Frame("测试"); public void init() { f.setLayout(new BoxLayout(f, BoxLayout.Y_AXIS)); // 下面按钮将会垂直排列 f.add(new Button("第一个按钮")); f.add(new Button("按钮二")); f.pack(); f.setVisible(true); } public static void main(String[] args) { new BoxLayoutTest().init(); } }
public class BoxSpaceTest { private Frame f = new Frame("测试"); // 定义水平摆放组件的Box对象 private Box horizontal = Box.createHorizontalBox(); // 定义垂直摆放组件的Box对象 private Box vertical = Box.createVerticalBox(); public void init() { horizontal.add(new Button("水平按钮一")); horizontal.add(Box.createHorizontalGlue()); horizontal.add(new Button("水平按钮二")); // 水平方向不可拉伸的间距,其宽度为10px horizontal.add(Box.createHorizontalStrut(10)); horizontal.add(new Button("水平按钮三")); vertical.add(new Button("垂直按钮一")); vertical.add(Box.createVerticalGlue()); vertical.add(new Button("垂直按钮二")); // 垂直方向不可拉伸的间距,其高度为10px vertical.add(Box.createVerticalStrut(10)); vertical.add(new Button("垂直按钮三")); f.add(horizontal, BorderLayout.NORTH); f.add(vertical); f.pack(); f.setVisible(true); } public static void main(String[] args) { new BoxSpaceTest().init(); } }
public class BoxTest { private Frame f = new Frame("测试"); // 定义水平摆放组件的Box对象 private Box horizontal = Box.createHorizontalBox(); // 定义垂直摆放组件的Box对象 private Box vertical = Box.createVerticalBox(); public void init() { horizontal.add(new Button("水平按钮一")); horizontal.add(new Button("水平按钮二")); vertical.add(new Button("垂直按钮一")); vertical.add(new Button("垂直按钮二")); f.add(horizontal, BorderLayout.NORTH); f.add(vertical); f.pack(); f.setVisible(true); } public static void main(String[] args) { new BoxTest().init(); } }
public class CardLayoutTest { Frame f = new Frame("测试窗口"); String[] names = { "第一张", "第二张", "第三张", "第四张", "第五张" }; Panel pl = new Panel(); public void init() { final CardLayout c = new CardLayout(); pl.setLayout(c); for (int i = 0 ; i < names.length ; i++) { pl.add(names[i] , new Button(names[i])); } Panel p = new Panel(); ActionListener listener = e -> { switch(e.getActionCommand()) { case "上一张": c.previous(pl); break; case "下一张": c.next(pl); break; case "第一张": c.first(pl); break; case "最后一张": c.last(pl); break; case "第三张": c.show(pl , "第三张"); break; } }; // 控制显示上一张的按钮 Button previous = new Button("上一张"); previous.addActionListener(listener); // 控制显示下一张的按钮 Button next = new Button("下一张"); next.addActionListener(listener); // 控制显示第一张的按钮 Button first = new Button("第一张"); first.addActionListener(listener); // 控制显示最后一张的按钮 Button last = new Button("最后一张"); last.addActionListener(listener); // 控制根据Card名显示的按钮 Button third = new Button("第三张"); third.addActionListener(listener); p.add(previous); p.add(next); p.add(first); p.add(last); p.add(third); f.add(pl); f.add(p , BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public static void main(String[] args) { new CardLayoutTest().init(); } }
public class CardLayoutTest { Frame f = new Frame("测试窗口"); String[] names = { "第一张", "第二张", "第三张", "第四张", "第五张" }; Panel pl = new Panel(); public void init() { final CardLayout c = new CardLayout(); pl.setLayout(c); for (int i = 0 ; i < names.length ; i++) { pl.add(names[i] , new Button(names[i])); } Panel p = new Panel(); ActionListener listener = e -> { switch(e.getActionCommand()) { case "上一张": c.previous(pl); break; case "下一张": c.next(pl); break; case "第一张": c.first(pl); break; case "最后一张": c.last(pl); break; case "第三张": c.show(pl , "第三张"); break; } }; // 控制显示上一张的按钮 Button previous = new Button("上一张"); previous.addActionListener(listener); // 控制显示下一张的按钮 Button next = new Button("下一张"); next.addActionListener(listener); // 控制显示第一张的按钮 Button first = new Button("第一张"); first.addActionListener(listener); // 控制显示最后一张的按钮 Button last = new Button("最后一张"); last.addActionListener(listener); // 控制根据Card名显示的按钮 Button third = new Button("第三张"); third.addActionListener(listener); p.add(previous); p.add(next); p.add(first); p.add(last); p.add(third); f.add(pl); f.add(p , BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public static void main(String[] args) { new CardLayoutTest().init(); } }
public class FlowLayoutTest { public static void main(String[] args) { Frame f = new Frame("测试窗口"); // 设置Frame容器使用FlowLayout布局管理器 f.setLayout(new FlowLayout(FlowLayout.LEFT, 20, 5)); // 向窗口中添加10个按钮 for (int i = 0; i < 10; i++) { f.add(new Button("按钮" + i)); } // 设置窗口为最佳大小 f.pack(); // 将窗口显示出来(Frame对象默认处于隐藏状态) f.setVisible(true); } }
public class GridBagTest { private Frame f = new Frame("测试窗口"); private GridBagLayout gb = new GridBagLayout(); private GridBagConstraints gbc = new GridBagConstraints(); private Button[] bs = new Button[10]; public void init() { f.setLayout(gb); for (int i = 0; i < bs.length; i++) { bs[i] = new Button("按钮" + i); } // 所有组件都可以横向、纵向上扩大 gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 1; addButton(bs[0]); addButton(bs[1]); addButton(bs[2]); // 该GridBagConstraints控制的GUI组件将会成为横向最后一个元素 gbc.gridwidth = GridBagConstraints.REMAINDER; addButton(bs[3]); // 该GridBagConstraints控制的GUI组件将横向上不会扩大 gbc.weightx = 0; addButton(bs[4]); // 该GridBagConstraints控制的GUI组件将横跨两个网格 gbc.gridwidth = 2; addButton(bs[5]); // 该GridBagConstraints控制的GUI组件将横跨一个网格 gbc.gridwidth = 1; // 该GridBagConstraints控制的GUI组件将纵向跨两个网格 gbc.gridheight = 2; // 该GridBagConstraints控制的GUI组件将会成为横向最后一个元素 gbc.gridwidth = GridBagConstraints.REMAINDER; addButton(bs[6]); // 该GridBagConstraints控制的GUI组件将横向跨越一个网格,纵向跨越2个网格。 gbc.gridwidth = 1; gbc.gridheight = 2; // 该GridBagConstraints控制的GUI组件纵向扩大的权重是1 gbc.weighty = 1; addButton(bs[7]); // 设置下面的按钮在纵向上不会扩大 gbc.weighty = 0; // 该GridBagConstraints控制的GUI组件将会成为横向最后一个元素 gbc.gridwidth = GridBagConstraints.REMAINDER; // 该GridBagConstraints控制的GUI组件将纵向上横跨一个网格 gbc.gridheight = 1; addButton(bs[8]); addButton(bs[9]); f.pack(); f.setVisible(true); } private void addButton(Button button) { gb.setConstraints(button, gbc); f.add(button); } public static void main(String[] args) { new GridBagTest().init(); } }
public class GridLayoutTest { public static void main(String[] args) { Frame f = new Frame("计算器"); Panel p1 = new Panel(); p1.add(new TextField(30)); f.add(p1, NORTH); Panel p2 = new Panel(); // 设置Panel使用GridLayout布局管理器 p2.setLayout(new GridLayout(3, 5, 4, 4)); String[] name = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", "*", "/", "." }; // 向Panel中依次添加15个按钮 for (int i = 0; i < name.length; i++) { p2.add(new Button(name[i])); } // 默认将Panel对象添加Frame窗口的中间 f.add(p2); // 设置窗口为最佳大小 f.pack(); // 将窗口显示出来(Frame对象默认处于隐藏状态) f.setVisible(true); } }
public class NullLayoutTest { Frame f = new Frame("测试窗口"); Button b1 = new Button("第一个按钮"); Button b2 = new Button("第二个按钮"); public void init() { // 设置使用null布局管理器 f.setLayout(null); // 下面强制设置每个按钮的大小、位置 b1.setBounds(20, 30, 90, 28); f.add(b1); b2.setBounds(50, 45, 120, 35); f.add(b2); f.setBounds(50, 50, 200, 100); f.setVisible(true); } public static void main(String[] args) { new NullLayoutTest().init(); } }
public class CommonComponent { Frame f = new Frame("测试"); // 定义一个按钮 Button ok = new Button("确认"); CheckboxGroup cbg = new CheckboxGroup(); // 定义一个单选框(处于cbg组),初始处于被选中状态 Checkbox male = new Checkbox("男", cbg, true); // 定义一个单选框(处于cbg组),初始处于没有选中状态 Checkbox female = new Checkbox("女", cbg, false); // 定义一个复选框,初始处于没有选中状态 Checkbox married = new Checkbox("是否已婚?", false); // 定义一个下拉选择框 Choice colorChooser = new Choice(); // 定义一个列表选择框 List colorList = new List(6, true); // 定义一个5行、20列的多行文本域 TextArea ta = new TextArea(5, 20); // 定义一个50列的单行文本域 TextField name = new TextField(50); public void init() { colorChooser.add("红色"); colorChooser.add("绿色"); colorChooser.add("蓝色"); colorList.add("红色"); colorList.add("绿色"); colorList.add("蓝色"); // 创建一个装载了文本框、按钮的Panel Panel bottom = new Panel(); bottom.add(name); bottom.add(ok); f.add(bottom, BorderLayout.SOUTH); // 创建一个装载了下拉选择框、三个Checkbox的Panel Panel checkPanel = new Panel(); checkPanel.add(colorChooser); checkPanel.add(male); checkPanel.add(female); checkPanel.add(married); // 创建一个垂直排列组件的Box,盛装多行文本域、Panel Box topLeft = Box.createVerticalBox(); topLeft.add(ta); topLeft.add(checkPanel); // 创建一个水平排列组件的Box,盛装topLeft、colorList Box top = Box.createHorizontalBox(); top.add(topLeft); top.add(colorList); // 将top Box容器添加到窗口的中间 f.add(top); f.pack(); f.setVisible(true); } public static void main(String[] args) { new CommonComponent().init(); } }
public class DialogTest { Frame f = new Frame("测试"); Dialog d1 = new Dialog(f, "模式对话框", true); Dialog d2 = new Dialog(f, "非模式对话框", false); Button b1 = new Button("打开模式对话框"); Button b2 = new Button("打开非模式对话框"); public void init() { d1.setBounds(20 , 30 , 300, 400); d2.setBounds(20 , 30 , 300, 400); b1.addActionListener(e -> d1.setVisible(true)); b2.addActionListener(e -> d2.setVisible(true)); f.add(b1); f.add(b2 , BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public static void main(String[] args) { new DialogTest().init(); } }
public class FileDialogTest { Frame f = new Frame("测试"); // 创建两个文件对话框 FileDialog d1 = new FileDialog(f, "选择需要打开文件", FileDialog.LOAD); FileDialog d2 = new FileDialog(f, "选择保存文件的路径", FileDialog.SAVE); Button b1 = new Button("打开文件"); Button b2 = new Button("保存文件"); public void init() { b1.addActionListener(e -> { d1.setVisible(true); // 打印出用户选择的文件路径和文件名 System.out.println(d1.getDirectory() + d1.getFile()); }); b2.addActionListener(e -> { d2.setVisible(true); // 打印出用户选择的文件路径和文件名 System.out.println(d2.getDirectory() + d2.getFile()); }); f.add(b1); f.add(b2 , BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public static void main(String[] args) { new FileDialogTest().init(); } }
public class AnonymousEventHandler { private Frame f = new Frame("测试"); private TextArea ta = new TextArea(6, 40); public void init() { // 以匿名内部类的形式来创建事件监听器对象 f.addWindowListener(new WindowAdapter() { // 实现事件处理方法 public void windowClosing(WindowEvent e) { System.out.println("用户试图关闭窗口!\n"); System.exit(0); } }); f.add(ta); f.pack(); f.setVisible(true); } public static void main(String[] args) { new AnonymousEventHandler().init(); } }
public class EventQs { private Frame f = new Frame("测试事件"); private Button ok = new Button("确定"); private TextField tf = new TextField(30); public void init() { // 注册事件监听器 ok.addActionListener(new OkListener()); // ① f.add(tf); f.add(ok, BorderLayout.SOUTH); f.pack(); f.setVisible(true); } // 定义事件监听器类 class OkListener implements ActionListener // ② { // 下面定义的方法就是事件处理器,用于响应特定的事件 public void actionPerformed(ActionEvent e) // ③ { System.out.println("用户单击了ok按钮"); tf.setText("Hello World"); } } public static void main(String[] args) { new EventQs().init(); } }
public class MailerListener implements ActionListener { // 该TextField文本框用于输入发送邮件的地址 private TextField mailAddress; public MailerListener() { } public MailerListener(TextField mailAddress) { this.mailAddress = mailAddress; } public void setMailAddress(TextField mailAddress) { this.mailAddress = mailAddress; } // 实现发送邮件 public void actionPerformed(ActionEvent e) { System.out.println("程序向“" + mailAddress.getText() + "”发送邮件..."); // 发送邮件的真实实现 } }
public class MultiListener { private Frame f = new Frame("测试"); private TextArea ta = new TextArea(6, 40); private Button b1 = new Button("按钮一"); private Button b2 = new Button("按钮二"); public void init() { // 创建FirstListener监听器的实例 FirstListener fl = new FirstListener(); // 给b1按钮注册两个事件监听器 b1.addActionListener(fl); b1.addActionListener(new SecondListener()); // 将f1事件监听器注册给b2按钮 b2.addActionListener(fl); f.add(ta); Panel p = new Panel(); p.add(b1); p.add(b2); f.add(p, BorderLayout.SOUTH); f.pack(); f.setVisible(true); } class FirstListener implements ActionListener { public void actionPerformed(ActionEvent e) { ta.append("第一个事件监听器被触发,事件源是:" + e.getActionCommand() + "\n"); } } class SecondListener implements ActionListener { public void actionPerformed(ActionEvent e) { ta.append("单击了“" + e.getActionCommand() + "”按钮\n"); } } public static void main(String[] args) { new MultiListener().init(); } }
public class SendMailer { private Frame f = new Frame("测试"); private TextField tf = new TextField(40); private Button send = new Button("发送"); public void init() { // 使用MailerListener对象作为事件监听器 send.addActionListener(new MailerListener(tf)); f.add(tf); f.add(send, BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public static void main(String[] args) { new SendMailer().init(); } }
// GUI界面类继承WindowAdapter作为事件监听器类 public class SimpleEventHandler extends WindowAdapter { private Frame f = new Frame("测试"); private TextArea ta = new TextArea(6, 40); public void init() { // 将该类的默认对象作为事件监听器对象 f.addWindowListener(this); f.add(ta); f.pack(); f.setVisible(true); } // GUI界面类直接包含事件处理器方法 public void windowClosing(WindowEvent e) { System.out.println("用户关闭窗口!\n"); System.exit(0); } public static void main(String[] args) { new SimpleEventHandler().init(); } }
public class WindowAdapterTest { private Frame f = new Frame("测试"); private TextArea ta = new TextArea(6, 40); public void init() { f.addWindowListener(new MyListener()); f.add(ta); f.pack(); f.setVisible(true); } class MyListener extends WindowAdapter { public void windowClosing(WindowEvent e) { System.out.println("用户关闭窗口!\n"); System.exit(0); } } public static void main(String[] args) { new WindowAdapterTest().init(); } }
public class WindowListenerTest { private Frame f = new Frame("测试"); private TextArea ta = new TextArea(6, 40); public void init() { // 为窗口添加窗口事件监听器 f.addWindowListener(new MyListener()); f.add(ta); f.pack(); f.setVisible(true); } // 实现一个窗口监听器类 class MyListener implements WindowListener { public void windowActivated(WindowEvent e) { ta.append("窗口被激活!\n"); } public void windowClosed(WindowEvent e) { ta.append("窗口被成功关闭!\n"); } public void windowClosing(WindowEvent e) { ta.append("用户关闭窗口!\n"); System.exit(0); } public void windowDeactivated(WindowEvent e) { ta.append("窗口失去焦点!\n"); } public void windowDeiconified(WindowEvent e) { ta.append("窗口被恢复!\n"); } public void windowIconified(WindowEvent e) { ta.append("窗口被最小化!\n"); } public void windowOpened(WindowEvent e) { ta.append("窗口初次被打开!\n"); } } public static void main(String[] args) { new WindowListenerTest().init(); } }
public class PopupMenuTest { private TextArea ta = new TextArea(4, 30); private Frame f = new Frame("测试"); PopupMenu pop = new PopupMenu(); CheckboxMenuItem autoWrap = new CheckboxMenuItem("自动换行"); MenuItem copyItem = new MenuItem("复制"); MenuItem pasteItem = new MenuItem("粘贴"); Menu format = new Menu("格式"); // 创建commentItem菜单项,指定使用 Ctrl+Shift+/ 快捷键 MenuItem commentItem = new MenuItem("注释", new MenuShortcut( KeyEvent.VK_SLASH, true)); MenuItem cancelItem = new MenuItem("取消注释"); public void init() { // 以Lambda表达式创建菜单事件监听器 ActionListener menuListener = e -> { String cmd = e.getActionCommand(); ta.append("单击“" + cmd + "”菜单" + "\n"); if (cmd.equals("退出")) { System.exit(0); } }; // 为commentItem菜单项添加了事件监听器。 commentItem.addActionListener(menuListener); // 为pop菜单添加菜单项 pop.add(autoWrap); // 使用addSeparator方法来添加菜单分隔线 pop.addSeparator(); pop.add(copyItem); pop.add(pasteItem); // 为format菜单添加菜单项 format.add(commentItem); format.add(cancelItem); // 使用添加new MenuItem("-")的方式添加菜单分隔线 pop.add(new MenuItem("-")); // 将format菜单组合到pop菜单中,从而形成二级菜单 pop.add(format); final Panel p = new Panel(); p.setPreferredSize(new Dimension(300, 160)); // 向p窗口中添加PopupMenu对象 p.add(pop); // 添加鼠标事件监听器 p.addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent e) { // 如果释放的是鼠标右键 if (e.isPopupTrigger()) { pop.show(p , e.getX() , e.getY()); } } }); f.add(p); f.add(ta , BorderLayout.NORTH); // 以匿名内部类的形式来创建事件监听器对象 f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.pack(); f.setVisible(true); } public static void main(String[] args) { new PopupMenuTest().init(); } }
public class SimpleMenu { private Frame f = new Frame("测试"); private MenuBar mb = new MenuBar(); Menu file = new Menu("文件"); Menu edit = new Menu("编辑"); MenuItem newItem = new MenuItem("新建"); MenuItem saveItem = new MenuItem("保存"); // 创建exitItem菜单项,指定使用 Ctrl+X 快捷键 MenuItem exitItem = new MenuItem("退出", new MenuShortcut(KeyEvent.VK_X)); CheckboxMenuItem autoWrap = new CheckboxMenuItem("自动换行"); MenuItem copyItem = new MenuItem("复制"); MenuItem pasteItem = new MenuItem("粘贴"); Menu format = new Menu("格式"); // 创建commentItem菜单项,指定使用 Ctrl+Shift+/ 快捷键 MenuItem commentItem = new MenuItem("注释", new MenuShortcut( KeyEvent.VK_SLASH, true)); MenuItem cancelItem = new MenuItem("取消注释"); private TextArea ta = new TextArea(6, 40); public void init() { // 以Lambda表达式创建菜单事件监听器 ActionListener menuListener = e -> { String cmd = e.getActionCommand(); ta.append("单击“" + cmd + "”菜单" + "\n"); if (cmd.equals("退出")) { System.exit(0); } }; // 为commentItem菜单项添加事件监听器 commentItem.addActionListener(menuListener); exitItem.addActionListener(menuListener); // 为file菜单添加菜单项 file.add(newItem); file.add(saveItem); file.add(exitItem); // 为edit菜单添加菜单项 edit.add(autoWrap); // 使用addSeparator方法来添加菜单分隔线 edit.addSeparator(); edit.add(copyItem); edit.add(pasteItem); // 为format菜单添加菜单项 format.add(commentItem); format.add(cancelItem); // 使用添加new MenuItem("-")的方式添加菜单分隔线 edit.add(new MenuItem("-")); // 将format菜单组合到edit菜单中,从而形成二级菜单 edit.add(format); // 将file、edit菜单添加到mb菜单条中 mb.add(file); mb.add(edit); // 为f窗口设置菜单条 f.setMenuBar(mb); // 以匿名内部类的形式来创建事件监听器对象 f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.add(ta); f.pack(); f.setVisible(true); } public static void main(String[] args) { new SimpleMenu().init(); } }
public class SimpleDraw { private final String RECT_SHAPE = "rect"; private final String OVAL_SHAPE = "oval"; private Frame f = new Frame("简单绘图"); private Button rect = new Button("绘制矩形"); private Button oval = new Button("绘制圆形"); private MyCanvas drawArea = new MyCanvas(); // 用于保存需要绘制什么图形的变量 private String shape = ""; public void init() { Panel p = new Panel(); rect.addActionListener(e -> { // 设置shape变量为RECT_SHAPE shape = RECT_SHAPE; // 重画MyCanvas对象,即调用它的repaint()方法 drawArea.repaint(); }); oval.addActionListener(e -> { // 设置shape变量为OVAL_SHAPE shape = OVAL_SHAPE; // 重画MyCanvas对象,即调用它的repaint()方法 drawArea.repaint(); }); p.add(rect); p.add(oval); drawArea.setPreferredSize(new Dimension(250 , 180)); f.add(drawArea); f.add(p , BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public static void main(String[] args) { new SimpleDraw().init(); } class MyCanvas extends Canvas { // 重写Canvas的paint方法,实现绘画 public void paint(Graphics g) { Random rand = new Random(); if (shape.equals(RECT_SHAPE)) { // 设置画笔颜色 g.setColor(new Color(220, 100, 80)); // 随机地绘制一个矩形框 g.drawRect(rand.nextInt(200), rand.nextInt(120), 40, 60); } if (shape.equals(OVAL_SHAPE)) { // 设置画笔颜色 g.setColor(new Color(80, 100, 200)); // 随机地填充一个实心圆形 g.fillOval(rand.nextInt(200), rand.nextInt(120), 50, 40); } } } }
public class PinBall { // 桌面的宽度 private final int TABLE_WIDTH = 300; // 桌面的高度 private final int TABLE_HEIGHT = 400; // 球拍的垂直位置 private final int RACKET_Y = 340; // 下面定义球拍的高度和宽度 private final int RACKET_HEIGHT = 20; private final int RACKET_WIDTH = 60; // 小球的大小 private final int BALL_SIZE = 16; private Frame f = new Frame("弹球游戏"); Random rand = new Random(); // 小球纵向的运行速度 private int ySpeed = 10; // 返回一个-0.5~0.5的比率,用于控制小球的运行方向。 private double xyRate = rand.nextDouble() - 0.5; // 小球横向的运行速度 private int xSpeed = (int) (ySpeed * xyRate * 2); // ballX和ballY代表小球的坐标 private int ballX = rand.nextInt(200) + 20; private int ballY = rand.nextInt(10) + 20; // racketX代表球拍的水平位置 private int racketX = rand.nextInt(200); private MyCanvas tableArea = new MyCanvas(); Timer timer; // 游戏是否结束的旗标 private boolean isLose = false; public void init() { // 设置桌面区域的最佳大小 tableArea.setPreferredSize( new Dimension(TABLE_WIDTH , TABLE_HEIGHT)); f.add(tableArea); // 定义键盘监听器 KeyAdapter keyProcessor = new KeyAdapter() { public void keyPressed(KeyEvent ke) { // 按下向左、向右键时,球拍水平坐标分别减少、增加 if (ke.getKeyCode() == KeyEvent.VK_LEFT) { if (racketX > 0) racketX -= 10; } if (ke.getKeyCode() == KeyEvent.VK_RIGHT) { if (racketX < TABLE_WIDTH - RACKET_WIDTH) racketX += 10; } } }; // 为窗口和tableArea对象分别添加键盘监听器 f.addKeyListener(keyProcessor); tableArea.addKeyListener(keyProcessor); // 定义每0.1秒执行一次的事件监听器。 ActionListener taskPerformer = evt -> { // 如果小球碰到左边边框 if (ballX <= 0 || ballX >= TABLE_WIDTH - BALL_SIZE) { xSpeed = -xSpeed; } // 如果小球高度超出了球拍位置,且横向不在球拍范围之内,游戏结束。 if (ballY >= RACKET_Y - BALL_SIZE && (ballX < racketX || ballX > racketX + RACKET_WIDTH)) { timer.stop(); // 设置游戏是否结束的旗标为true。 isLose = true; tableArea.repaint(); } // 如果小球位于球拍之内,且到达球拍位置,小球反弹 else if (ballY <= 0 || (ballY >= RACKET_Y - BALL_SIZE && ballX > racketX && ballX <= racketX + RACKET_WIDTH)) { ySpeed = -ySpeed; } // 小球坐标增加 ballY += ySpeed; ballX += xSpeed; tableArea.repaint(); }; timer = new Timer(100, taskPerformer); timer.start(); f.pack(); f.setVisible(true); } public static void main(String[] args) { new PinBall().init(); } class MyCanvas extends Canvas { // 重写Canvas的paint方法,实现绘画 public void paint(Graphics g) { // 如果游戏已经结束 if (isLose) { g.setColor(new Color(255, 0, 0)); g.setFont(new Font("Times", Font.BOLD, 30)); g.drawString("游戏已结束!", 50, 200); } // 如果游戏还未结束 else { // 设置颜色,并绘制小球 g.setColor(new Color(240, 240, 80)); g.fillOval(ballX, ballY, BALL_SIZE, BALL_SIZE); // 设置颜色,并绘制球拍 g.setColor(new Color(80, 80, 200)); g.fillRect(racketX, RACKET_Y, RACKET_WIDTH, RACKET_HEIGHT); } } } }
public class Gobang { // 下面三个位图分别代表棋盘、黑子、白子 BufferedImage table; BufferedImage black; BufferedImage white; // 当鼠标移动时候的选择框 BufferedImage selected; // 定义棋盘的大小 private static int BOARD_SIZE = 15; // 定义棋盘宽、高多少个像素 private final int TABLE_WIDTH = 535; private final int TABLE_HETGHT = 536; // 定义棋盘坐标的像素值和棋盘数组之间的比率。 private final int RATE = TABLE_WIDTH / BOARD_SIZE; // 定义棋盘坐标的像素值和棋盘数组之间的偏移距。 private final int X_OFFSET = 5; private final int Y_OFFSET = 6; // 定义一个二维数组来充当棋盘 private String[][] board = new String[BOARD_SIZE][BOARD_SIZE]; // 五子棋游戏的窗口 JFrame f = new JFrame("五子棋游戏"); // 五子棋游戏棋盘对应的Canvas组件 ChessBoard chessBoard = new ChessBoard(); // 当前选中点的坐标 private int selectedX = -1; private int selectedY = -1; public void init() throws Exception { table = ImageIO.read(new File("image/board.jpg")); black = ImageIO.read(new File("image/black.gif")); white = ImageIO.read(new File("image/white.gif")); selected = ImageIO.read(new File("image/selected.gif")); // 把每个元素赋为"╋","╋"代表没有棋子 for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { board[i][j] = "╋"; } } chessBoard.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HETGHT)); chessBoard.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { // 将用户鼠标事件的坐标转换成棋子数组的坐标。 int xPos = (int) ((e.getX() - X_OFFSET) / RATE); int yPos = (int) ((e.getY() - Y_OFFSET) / RATE); board[xPos][yPos] = "●"; /* * 电脑随机生成两个整数,作为电脑下棋的坐标,赋给board数组。 还涉及: 1.如果下棋的点已经有棋子,不能重复下棋。 * 2.每次下棋后,需要扫描谁赢了 */ chessBoard.repaint(); } // 当鼠标退出棋盘区后,复位选中点坐标 public void mouseExited(MouseEvent e) { selectedX = -1; selectedY = -1; chessBoard.repaint(); } }); chessBoard.addMouseMotionListener(new MouseMotionAdapter() { // 当鼠标移动时,改变选中点的坐标 public void mouseMoved(MouseEvent e) { selectedX = (e.getX() - X_OFFSET) / RATE; selectedY = (e.getY() - Y_OFFSET) / RATE; chessBoard.repaint(); } }); f.add(chessBoard); f.pack(); f.setVisible(true); } public static void main(String[] args) throws Exception { Gobang gb = new Gobang(); gb.init(); } class ChessBoard extends JPanel { // 重写JPanel的paint方法,实现绘画 public void paint(Graphics g) { // 将绘制五子棋棋盘 g.drawImage(table, 0, 0, null); // 绘制选中点的红框 if (selectedX >= 0 && selectedY >= 0) g.drawImage(selected, selectedX * RATE + X_OFFSET, selectedY * RATE + Y_OFFSET, null); // 遍历数组,绘制棋子。 for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { // 绘制黑棋 if (board[i][j].equals("●")) { g.drawImage(black, i * RATE + X_OFFSET, j * RATE + Y_OFFSET, null); } // 绘制白棋 if (board[i][j].equals("○")) { g.drawImage(white, i * RATE + X_OFFSET, j * RATE + Y_OFFSET, null); } } } } } }
public class HandDraw { // 画图区的宽度 private final int AREA_WIDTH = 500; // 画图区的高度 private final int AREA_HEIGHT = 400; // 下面的preX、preY保存了上一次鼠标拖动事件的鼠标坐标 private int preX = -1; private int preY = -1; // 定义一个右键菜单用于设置画笔颜色 PopupMenu pop = new PopupMenu(); MenuItem redItem = new MenuItem("红色"); MenuItem greenItem = new MenuItem("绿色"); MenuItem blueItem = new MenuItem("蓝色"); // 定义一个BufferedImage对象 BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_RGB); // 获取image对象的Graphics Graphics g = image.getGraphics(); private Frame f = new Frame("简单手绘程序"); private DrawCanvas drawArea = new DrawCanvas(); // 用于保存画笔颜色 private Color foreColor = new Color(255, 0, 0); public void init() { // 定义右键菜单的事件监听器。 ActionListener menuListener = e -> { if (e.getActionCommand().equals("绿色")) { foreColor = new Color(0 , 255 , 0); } if (e.getActionCommand().equals("红色")) { foreColor = new Color(255 , 0 , 0); } if (e.getActionCommand().equals("蓝色")) { foreColor = new Color(0 , 0 , 255); } }; // 为三个菜单添加事件监听器 redItem.addActionListener(menuListener); greenItem.addActionListener(menuListener); blueItem.addActionListener(menuListener); // 将菜单项组合成右键菜单 pop.add(redItem); pop.add(greenItem); pop.add(blueItem); // 将右键菜单添加到drawArea对象中 drawArea.add(pop); // 将image对象的背景色填充成白色 g.fillRect(0 , 0 ,AREA_WIDTH , AREA_HEIGHT); drawArea.setPreferredSize(new Dimension(AREA_WIDTH , AREA_HEIGHT)); // 监听鼠标移动动作 drawArea.addMouseMotionListener(new MouseMotionAdapter() { // 实现按下鼠标键并拖动的事件处理器 public void mouseDragged(MouseEvent e) { // 如果preX和preY大于0 if (preX > 0 && preY > 0) { // 设置当前颜色 g.setColor(foreColor); // 绘制从上一次鼠标拖动事件点到本次鼠标拖动事件点的线段 g.drawLine(preX , preY , e.getX() , e.getY()); } // 将当前鼠标事件点的X、Y坐标保存起来 preX = e.getX(); preY = e.getY(); // 重绘drawArea对象 drawArea.repaint(); } }); // 监听鼠标事件 drawArea.addMouseListener(new MouseAdapter() { // 实现鼠标松开的事件处理器 public void mouseReleased(MouseEvent e) { // 弹出右键菜单 if (e.isPopupTrigger()) { pop.show(drawArea , e.getX() , e.getY()); } // 松开鼠标键时,把上一次鼠标拖动事件的X、Y坐标设为-1。 preX = -1; preY = -1; } }); f.add(drawArea); f.pack(); f.setVisible(true); } public static void main(String[] args) { new HandDraw().init(); } class DrawCanvas extends Canvas { // 重写Canvas的paint方法,实现绘画 public void paint(Graphics g) { // 将image绘制到该组件上 g.drawImage(image, 0, 0, null); } } }
public class ImageIOTest { public static void main(String[] args) { String[] readFormat = ImageIO.getReaderFormatNames(); System.out.println("-----Image能读的所有图形文件格式-----"); for (String tmp : readFormat) { System.out.println(tmp); } String[] writeFormat = ImageIO.getWriterFormatNames(); System.out.println("-----Image能写的所有图形文件格式-----"); for (String tmp : writeFormat) { System.out.println(tmp); } } }
public class ZoomImage { // 下面两个常量设置缩小后图片的大小 private final int WIDTH = 80; private final int HEIGHT = 60; // 定义个BuffedImage对象,用于保存缩小后的位图 BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); public void zoom() throws Exception { // 读取原始位图 Image srcImage = ImageIO.read(new File("image/board.jpg")); // 将原始位图缩小后绘制到image图像中 g.drawImage(srcImage, 0, 0, WIDTH, HEIGHT, null); // 将image图像文件输出到磁盘文件中。 ImageIO.write(image, "jpeg", new File(System.currentTimeMillis() + ".jpg")); } public static void main(String[] args) throws Exception { new ZoomImage().zoom(); } }
public class CopyImage { // 系统剪贴板 private Clipboard clipboard = Toolkit.getDefaultToolkit() .getSystemClipboard(); // 使用ArrayList来保存所有粘贴进来的Image——就是当成图层处理 java.util.List<Image> imageList = new ArrayList<>(); // 下面代码与前面HandDraw程序中控制绘图的代码一样,省略这部分代码。 // 画图区的宽度 private final int AREA_WIDTH = 500; // 画图区的高度 private final int AREA_HEIGHT = 400; // 下面的preX、preY保存了上一次鼠标拖动事件的鼠标坐标 private int preX = -1; private int preY = -1; // 定义一个右键菜单用于设置画笔颜色 PopupMenu pop = new PopupMenu(); MenuItem redItem = new MenuItem("红色"); MenuItem greenItem = new MenuItem("绿色"); MenuItem blueItem = new MenuItem("蓝色"); // 定义一个BufferedImage对象 BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_RGB); // 获取image对象的Graphics Graphics g = image.getGraphics(); private Frame f = new Frame("简单手绘程序"); private DrawCanvas drawArea = new DrawCanvas(); // 用于保存画笔颜色 private Color foreColor = new Color(255, 0, 0); public void init() { // 定义右键菜单的事件监听器。 ActionListener menuListener = e -> { if (e.getActionCommand().equals("绿色")) { foreColor = new Color(0 , 255 , 0); } if (e.getActionCommand().equals("红色")) { foreColor = new Color(255 , 0 , 0); } if (e.getActionCommand().equals("蓝色")) { foreColor = new Color(0 , 0 , 255); } }; // 为三个菜单添加事件监听器 redItem.addActionListener(menuListener); greenItem.addActionListener(menuListener); blueItem.addActionListener(menuListener); // 将菜单项组合成右键菜单 pop.add(redItem); pop.add(greenItem); pop.add(blueItem); // 将右键菜单添加到drawArea对象中 drawArea.add(pop); // 将image对象的背景色填充成白色 g.fillRect(0 , 0 ,AREA_WIDTH , AREA_HEIGHT); drawArea.setPreferredSize(new Dimension(AREA_WIDTH , AREA_HEIGHT)); // 监听鼠标移动动作 drawArea.addMouseMotionListener(new MouseMotionAdapter() { // 实现按下鼠标键并拖动的事件处理器 public void mouseDragged(MouseEvent e) { // 如果preX和preY大于0 if (preX > 0 && preY > 0) { // 设置当前颜色 g.setColor(foreColor); // 绘制从上一次鼠标拖动事件点到本次鼠标拖动事件点的线段 g.drawLine(preX , preY , e.getX() , e.getY()); } // 将当前鼠标事件点的X、Y坐标保存起来 preX = e.getX(); preY = e.getY(); // 重绘drawArea对象 drawArea.repaint(); } }); // 监听鼠标事件 drawArea.addMouseListener(new MouseAdapter() { // 实现鼠标松开的事件处理器 public void mouseReleased(MouseEvent e) { // 弹出右键菜单 if (e.isPopupTrigger()) { pop.show(drawArea , e.getX() , e.getY()); } // 松开鼠标键时,把上一次鼠标拖动事件的X、Y坐标设为-1。 preX = -1; preY = -1; } }); f.add(drawArea); Panel p = new Panel(); Button copy = new Button("复制"); Button paste = new Button("粘贴"); copy.addActionListener(event -> { // 将image对象封装成ImageSelection对象 ImageSelection contents = new ImageSelection(image); // 将ImageSelection对象放入剪贴板 clipboard.setContents(contents, null); }); paste.addActionListener(event -> { // 如果剪贴板中包含imageFlavor内容 if (clipboard.isDataFlavorAvailable(DataFlavor.imageFlavor)) { try { // 取出剪贴板中imageFlavor内容,并将其添加到List集合中 imageList.add((Image)clipboard .getData(DataFlavor.imageFlavor)); drawArea.repaint(); } catch (Exception e) { e.printStackTrace(); } } }); p.add(copy); p.add(paste); f.add(p , BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public static void main(String[] args) { new CopyImage().init(); } class DrawCanvas extends Canvas { // 重写Canvas的paint方法,实现绘画 public void paint(Graphics g) { // 将image绘制到该组件上 g.drawImage(image, 0, 0, null); // 将List里的所有Image对象都绘制出来。 for (Image img : imageList) { g.drawImage(img, 0, 0, null); } } } }
class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // age的setter和getter方法 public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public String toString() { return "Person[ name=" + name + " , age=" + age + " ]"; } } public class CopyPerson { Frame f = new Frame("复制对象"); Button copy = new Button("复制"); Button paste = new Button("粘贴"); TextField name = new TextField(15); TextField age = new TextField(15); TextArea ta = new TextArea(3, 30); // 创建本地的剪贴板 Clipboard clipboard = new Clipboard("cp"); public void init() { Panel p = new Panel(); p.add(new Label("姓名")); p.add(name); p.add(new Label("年龄")); p.add(age); f.add(p , BorderLayout.NORTH); f.add(ta); Panel bp = new Panel(); // 为“复制”按钮添加事件监听器 copy.addActionListener(e -> copyPerson()); // 为“粘贴”按钮添加事件监听器 paste.addActionListener(e -> { try { readPerson(); } catch (Exception ee) { ee.printStackTrace(); } }); bp.add(copy); bp.add(paste); f.add(bp , BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public void copyPerson() { // 以name,age文本框的内容创建Person对象 Person p = new Person(name.getText(), Integer.parseInt(age.getText())); // 将Person对象封装成LocalObjectSelection对象 LocalObjectSelection ls = new LocalObjectSelection(p); // 将LocalObjectSelection对象放入本地剪贴板 clipboard.setContents(ls, null); } public void readPerson() throws Exception { // 创建保存Person对象引用的DataFlavor对象 DataFlavor peronFlavor = new DataFlavor( "application/x-java-jvm-local-objectref;class=Person"); // 取出本地剪贴板内的内容 if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) { Person p = (Person) clipboard.getData(peronFlavor); ta.setText(p.toString()); } } public static void main(String[] args) { new CopyPerson().init(); } }
class Dog implements Serializable { private String name; private int age; public Dog() { } public Dog(String name, int age) { this.name = name; this.age = age; } // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // age的setter和getter方法 public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public String toString() { return "Dog [ name=" + name + " , age=" + age + " ]"; } } public class CopySerializable { Frame f = new Frame("复制对象"); Button copy = new Button("复制"); Button paste = new Button("粘贴"); TextField name = new TextField(15); TextField age = new TextField(15); TextArea ta = new TextArea(3, 30); // 创建系统剪贴板 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); public void init() { Panel p = new Panel(); p.add(new Label("姓名")); p.add(name); p.add(new Label("年龄")); p.add(age); f.add(p , BorderLayout.NORTH); f.add(ta); Panel bp = new Panel(); copy.addActionListener(e -> copyDog()); paste.addActionListener(e -> { try { readDog(); } catch (Exception ee) { ee.printStackTrace(); } }); bp.add(copy); bp.add(paste); f.add(bp , BorderLayout.SOUTH); f.pack(); f.setVisible(true); } public void copyDog() { Dog d = new Dog(name.getText(), Integer.parseInt(age.getText())); // 把dog实例封装成SerialSelection对象 SerialSelection ls = new SerialSelection(d); // 把SerialSelection对象放入系统剪贴板中 clipboard.setContents(ls, null); } public void readDog() throws Exception { DataFlavor peronFlavor = new DataFlavor( DataFlavor.javaSerializedObjectMimeType + ";class=Dog"); if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) { // 从系统剪贴板中读取数据 Dog d = (Dog) clipboard.getData(peronFlavor); ta.setText(d.toString()); } } public static void main(String[] args) { new CopySerializable().init(); } }
public class ImageSelection implements Transferable { private Image image; // 构造器,负责持有一个Image对象 public ImageSelection(Image image) { this.image = image; } // 返回该Transferable对象所支持的所有DataFlavor public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[] { DataFlavor.imageFlavor }; } // 取出该Transferable对象里实际的数据 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { if (flavor.equals(DataFlavor.imageFlavor)) { return image; } else { throw new UnsupportedFlavorException(flavor); } } // 返回该Transferable对象是否支持指定的DataFlavor public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor.equals(DataFlavor.imageFlavor); } }
public class LocalObjectSelection implements Transferable { // 持有一个对象的引用 private Object obj; public LocalObjectSelection(Object obj) { this.obj = obj; } // 返回该Transferable对象支持的DataFlavor public DataFlavor[] getTransferDataFlavors() { DataFlavor[] flavors = new DataFlavor[2]; // 获取被封装对象的类型 Class clazz = obj.getClass(); String mimeType = "application/x-java-jvm-local-objectref;" + "class=" + clazz.getName(); try { flavors[0] = new DataFlavor(mimeType); flavors[1] = DataFlavor.stringFlavor; return flavors; } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } } // 取出该Transferable对象封装的数据 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { if (!isDataFlavorSupported(flavor)) { throw new UnsupportedFlavorException(flavor); } if (flavor.equals(DataFlavor.stringFlavor)) { return obj.toString(); } return obj; } public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor.equals(DataFlavor.stringFlavor) || flavor.getPrimaryType().equals("application") && flavor.getSubType().equals("x-java-jvm-local-objectref") && flavor.getRepresentationClass().isAssignableFrom( obj.getClass()); } }
public class SerialSelection implements Transferable { // 持有一个可序列化的对象 private Serializable obj; // 创建该类的对象时传入被持有的对象 public SerialSelection(Serializable obj) { this.obj = obj; } public DataFlavor[] getTransferDataFlavors() { DataFlavor[] flavors = new DataFlavor[2]; // 获取被封装对象的类型 Class clazz = obj.getClass(); try { flavors[0] = new DataFlavor(DataFlavor.javaSerializedObjectMimeType + ";class=" + clazz.getName()); flavors[1] = DataFlavor.stringFlavor; return flavors; } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { if (!isDataFlavorSupported(flavor)) { throw new UnsupportedFlavorException(flavor); } if (flavor.equals(DataFlavor.stringFlavor)) { return obj.toString(); } return obj; } public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor.equals(DataFlavor.stringFlavor) || flavor.getPrimaryType().equals("application") && flavor.getSubType().equals("x-java-serialized-object") && flavor.getRepresentationClass().isAssignableFrom( obj.getClass()); } }
public class SimpleClipboard { private Frame f = new Frame("简单的剪贴板程序"); // 获取系统剪贴板 private Clipboard clipboard = Toolkit.getDefaultToolkit() .getSystemClipboard(); // 下面是创建本地剪贴板的代码 // Clipboard clipboard = new Clipboard("cb"); // ① // 用于复制文本的文本框 private TextArea jtaCopyTo = new TextArea(5, 20); // 用于粘贴文本的文本框 private TextArea jtaPaste = new TextArea(5, 20); private Button btCopy = new Button("复制"); // 复制按钮 private Button btPaste = new Button("粘贴"); // 粘贴按钮 public void init() { Panel p = new Panel(); p.add(btCopy); p.add(btPaste); btCopy.addActionListener(event -> { // 将一个多行文本域里的字符串封装成StringSelection对象 StringSelection contents = new StringSelection(jtaCopyTo.getText()); // 将StringSelection对象放入剪贴板 clipboard.setContents(contents, null); }); btPaste.addActionListener(event -> { // 如果剪贴板中包含stringFlavor内容 if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) { try { // 取出剪贴板中stringFlavor内容 String content = (String)clipboard .getData(DataFlavor.stringFlavor); jtaPaste.append(content); } catch (Exception e) { e.printStackTrace(); } } }); // 创建一个水平排列的Box容器 Box box = new Box(BoxLayout.X_AXIS); // 将两个多行文本域放在Box容器中 box.add(jtaCopyTo); box.add(jtaPaste); // 将按钮所在Panel、Box容器添加到Frame窗口中 f.add(p,BorderLayout.SOUTH); f.add(box,BorderLayout.CENTER); f.pack(); f.setVisible(true); } public static void main(String[] args) { new SimpleClipboard().init(); } }
public class DragSourceTest { JFrame jf = new JFrame("Swing的拖放支持"); JLabel srcLabel = new JLabel("Swing的拖放支持.\n" + "将该文本域的内容拖入其他程序.\n"); public void init() { DragSource dragSource = DragSource.getDefaultDragSource(); // 将srcLabel转换成拖放源,它能接受复制、移动两种操作 dragSource.createDefaultDragGestureRecognizer(srcLabel , DnDConstants.ACTION_COPY_OR_MOVE , event -> { // 将JLabel里的文本信息包装成Transferable对象 String txt = srcLabel.getText(); Transferable transferable = new StringSelection(txt); // 继续拖放操作,拖放过程中使用手状光标 event.startDrag(Cursor.getPredefinedCursor(Cursor .HAND_CURSOR), transferable); }); jf.add(new JScrollPane(srcLabel)); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new DragSourceTest().init(); } }
public class DropTargetTest { final int DESKTOP_WIDTH = 480; final int DESKTOP_HEIGHT = 360; final int FRAME_DISTANCE = 30; JFrame jf = new JFrame("测试拖放目标——把图片文件拖入该窗口"); // 定义一个虚拟桌面 private JDesktopPane desktop = new JDesktopPane(); // 保存下一个内部窗口的坐标点 private int nextFrameX; private int nextFrameY; // 定义内部窗口为虚拟桌面的1/2大小 private int width = DESKTOP_WIDTH / 2; private int height = DESKTOP_HEIGHT / 2; public void init() { desktop.setPreferredSize(new Dimension(DESKTOP_WIDTH, DESKTOP_HEIGHT)); // 将当前窗口创建成拖放目标 new DropTarget(jf, DnDConstants.ACTION_COPY, new ImageDropTargetListener()); jf.add(desktop); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } class ImageDropTargetListener extends DropTargetAdapter { public void drop(DropTargetDropEvent event) { // 接受复制操作 event.acceptDrop(DnDConstants.ACTION_COPY); // 获取拖放的内容 Transferable transferable = event.getTransferable(); DataFlavor[] flavors = transferable.getTransferDataFlavors(); // 遍历拖放内容里的所有数据格式 for (int i = 0; i < flavors.length; i++) { DataFlavor d = flavors[i]; try { // 如果拖放内容的数据格式是文件列表 if (d.equals(DataFlavor.javaFileListFlavor)) { // 取出拖放操作里的文件列表 List fileList = (List) transferable.getTransferData(d); for (Object f : fileList) { // 显示每个文件 showImage((File) f, event); } } } catch (Exception e) { e.printStackTrace(); } // 强制拖放操作结束,停止阻塞拖放目标 event.dropComplete(true); // ① } } // 显示每个文件的工具方法 private void showImage(File f, DropTargetDropEvent event) throws IOException { Image image = ImageIO.read(f); if (image == null) { // 强制拖放操作结束,停止阻塞拖放目标 event.dropComplete(true); // ② JOptionPane.showInternalMessageDialog(desktop, "系统不支持这种类型的文件"); // 方法返回,不会继续操作 return; } ImageIcon icon = new ImageIcon(image); // 创建内部窗口显示该图片 JInternalFrame iframe = new JInternalFrame(f.getName(), true, true, true, true); JLabel imageLabel = new JLabel(icon); iframe.add(new JScrollPane(imageLabel)); desktop.add(iframe); // 设置内部窗口的原始位置(内部窗口默认大小是0X0,放在0,0位置) iframe.reshape(nextFrameX, nextFrameY, width, height); // 使该窗口可见,并尝试选中它 iframe.show(); // 计算下一个内部窗口的位置 nextFrameX += FRAME_DISTANCE; nextFrameY += FRAME_DISTANCE; if (nextFrameX + width > desktop.getWidth()) nextFrameX = 0; if (nextFrameY + height > desktop.getHeight()) nextFrameY = 0; } } public static void main(String[] args) { new DropTargetTest().init(); } }
|








浙公网安备 33010602011771号