[Java][图形程序设计Swing][学习笔记]
【摘要】 很多人印象中Java编写的程序都是通过键盘接收输入,在控制台屏幕上显示结果。其实Java还可以编写使用图形用户界面(GUI) 的程序,今天就为大家介绍一下Java的图形界面-Swing。 1,Swing 概述在 Java 1.0 刚刚出现的时候,包含了一个用于基本 GUI 程序设计的类库,Sun将它称为抽象窗口工具箱( Abstract Window Toolkit, AWT)。基本AWT库...
很多人印象中Java编写的程序都是通过键盘接收输入,在控制台屏幕上显示结果。其实Java还可以编写使用图形用户界面(GUI) 的程序,今天就为大家介绍一下Java的图形界面-Swing。
1,Swing 概述
- 在 Java 1.0 刚刚出现的时候,包含了一个用于基本 GUI 程序设计的类库,Sun将它称为抽象窗口工具箱( Abstract Window Toolkit, AWT)。基本AWT库采用将处理用户界面元素的任务委派给每个目标平台( Windows、Solaris、 Macintosh 等)的本地 GUI 工具箱的方式,由本地 GUI 工具箱负责用户界面元素的创建和动作。因此,Sun 公司的口号是“ 一次编写,随处使用”。
- 但此方法在不同平台上,操作会存在差异。要想给予用户一致的、 可预见性的界面操作方式是相当困难的。在不同平台上的 AWT 用户界面库中存在着不同的 bug。研发人员必须在每一个平号上测试应用程序, 因此人们嘲弄地将 AWT 称为“ 一次编写, 随处调试”。
- 在 1996 年,Netscape 创建了一种称为 IFC ( Internet Foundation Class) 的 GUI 库, 它采用了与 AWT 完全不同的工作方式。它将按钮、菜单这样的用户界面元素绘制在空白窗口上,而对等体只需要创建和绘制窗口。因此,Netscape 的 IFC 组件在程序运行的所有平台上的外观和动作都一样。Sun 与 Netscape 合作完善了这种方式, 创建了一个名为 Swing 的用户界面库。
- 注意:Swing 没有完全替代 AWT, 而是基于 AWT 架构之上。Swing 仅仅提供了能力更加强大的用户界面组件。 尤其在采用 Swing 编写的程序中,还需要使用基本的 AWT 处理事件。可以理解为:Swing 是指 “ 被绘制的” 用户界面类;AWT 是指像事件处理这样的窗口工具箱的底层机制。
- Swing的优势主要有:
- Swing 拥有一个丰富、 便捷的用户界面元素集合。
- Swing 对底层平台依赖的很少,因此与平台相关的 bug 很少。
- Swing 给予不同平台的用户一致的感觉。
2,创建框架
- 在 Java 中,顶层窗口(就是没有包含在其他窗口中的窗口)被称为框架(frame)。在 AWT 库中有一个称为 Frame 的类, 用于描述顶层窗口。这个类的 Swing 版本名为 JFrame,它扩展于 Frame 类。JFrame是极少数几个不绘制在画布上的Swing组件之一。因此,它的修改部件(按钮、标题栏、图标等)由用户的窗口系统绘制,而不是由Swing绘制。
- 本节中将介绍有关Swing的JFrame的常用方法。以下例子是给出了一个在屏幕中显示一个空框架的简单程序。
import javax.swing.*;
import java.awt.*;
public class SimpleFrameTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(() ->
{
SimpleFrame frame = new SimpleFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
class SimpleFrame extends JFrame
{
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
public SimpleFrame()
{
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
}
- Swing类位于javax.swing包中。包名javax表示这是一个Java扩展包,而不是核心包。
- 默认情况下,框架的大小为0×0像素,这种框架没有什么实际意义。这里定义了一个子类SimpleFrame,它的构造器将框架大小设置为300×200像素。这是SimpleFrame和JFrame之间唯一的差别。
- 在SimpleFrameTest类的main方法,我们构造了一个SimpleFrame对象使它可见。
- 在每个Swing程序中,有两个技术问题需要强调
- 1,所有的Swing组件必须由事件分派线程(event dispatch thread)进行配置,线程将鼠标点击和按钮控制转移到用户接口组件。下面的代码片段是事件分派线程中的执行代码:
EventQueue.invokeLater(()->
{
statements
});
- 2,定义一个用户关闭这个框架时的响应动作。对于这个程序而言,只让程序简单退出即可。选择这个响应动作的语句是:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
,在包含多个框架的程序中,不能在用户关闭其中的一个框架时就让程序退出。在默认情况下,用户关闭窗口时只是将框架隐藏起来,而程序并没有终止。框架起初是不可见的,为了显示框架,main方法需要调用框架的setVisible()方法。 - 在初始化语句结束后,main方法退出。需要注意,退出main并没有终止程序,终止的只是主线程。事件分派线程保持程序处于激活状态,知道关闭框架或调用System.exit方法终止程序。
3,框架定位
-
JFrame类本身只包含若干个改变框架外观的方法。当然,通过继承,从JFrame的各个超类中继承了许多用于处理框架大小和位置的方法。其中最重要的有下面几个:
- setLocation和setBounds方法用于设置框架的位置。
- setIconImage用于告诉窗口系统在标题栏、任务切换窗口等位置显示哪个图标。
- setTitle用于改变标题栏的文字。
- setResizable利用一个boolean值确定框架的大小是否允许用户改变。
-
AWT和Swing中框架和组件类的继承层次
3.1,框架属性
- 组件类的很多方法是以获取/设置方法对形式出现的,这样的一个获取/设置方法对被称为一种属性。属性包含属性名和类型。将get或set之后的第一个字母改为小写字母就可以得到相应的属性名。
- 针对get/set约定有一个例外:对于类型为boolean的属性,获取方法由is开头。
3.2,确定合适的框架大小
- 要记住:如果没有明确地指定框架的大小,所有框架的默认值为0×0像素。
API:java.awt.Component 1.0
boolean isVisible()
void setVisible(boolean b)
- 获取或设置visible属性。组件最初是可见的,但JFrame这样的顶层组件例外。
void setSize(int width,int height) 1.1
- 使用给定的宽度和高度,重新设置组件的大小。
void setLocation(int x,int y) 1.1
- 将组件移到一个新的位置上。如果这个组件不是顶层组件,x和y左边(或者p.x和p.y)是容器坐标;否则是屏幕坐标(例如:JFrame)
void setBounds(int x,int y,int width,int height) 1.1
- 移动并重新设置组件的大小
Dimension getSize() 1.1
void setSize(Dimension d) 1.1
- 获取或设置当前组件的size属性
API:java.awt.Window 1.0
void toFront()
- 将这个窗口显示在其他窗口前面 —
void toBack()
- 将这个窗口移到桌面窗口栈的后面,并相应地重新排列所有的可见窗口。
- 将这个窗口显示在其他窗口前面 —
boolean isLocationByPlatform() 5.0
void setLocationByPlatform(boolean b) 5.0
- 获取或设置locationByPlatform属性。这个属性在窗口显示之前被设置,由平台选择一个合适的位置。
API:java.awt.Frame 1.0
boolean isResizable()
void setResizable(boolean b)
- 获取或设置resizable属性。这个属性设置后,用户可以重新设置框架的大小。
String getTitle()
void setTitle(String s)
- 获取或设置title属性,这个属性确定框架标题栏中的文字
Image getIconImage()
void setIconImage(Image image)
- 获取或设置iconImage属性,这个属性确定框架的图标。窗口系统可能会将图标作为框架装饰或其他部位的一部分显示。
boolean isUndecorated() 1.4
void setUndecorated(boolean b) 1.4
- 获取或设置undecorated属性。这个属性设置后,框架显示中将没有标题栏或关闭按钮这样的装饰。在框架显示之前,必须调用这个方法。
int getExtendedState() 1.4
void setExtendedState(int state) 1.4
- 获取或设置窗口状态。状态是下列值之一。
Frame.NORMAL
Frame.ICONIFIED
Frame.MAXIMINZED_HORIZ
Frame.MAXIMIZED_VERT
Frame.MAXIMIZED_BOTH
API:java.awt.Toolkit 1.0
static Toolkit getDefaultToolkit()
- 返回默认的工具箱
Dimension getScreenSize()
- 返回用户屏幕的尺寸
API:javax.swing.ImageIcon 1.2
ImageIcon(String filename)
- 构造一个图标,其图像存储在一个文件中
Image getImage()
- 获得该图标的图像
6,使用颜色
-
Color类用于定义颜色。在java.awt.Color类中提供了13个预定义的常量,它们分别表示13种标准颜色
- BLACK,BLUE,CYAN,DARK_GRAY,GRAY,GREEN,LIGHT_GRAY,MAGENTA,ORANGE,PINK,RED,WHITE,YELLOW
-
可以通过提供红、绿、蓝三色成分创建一个Color对象,以达到定制颜色的目的。三种颜色都是用0-255(也就是一个字节)之间的整型数值表示,调用Color的构造器格式为:
Color(int redness,int greenness,int blueness)
API:java.awt.Color 1.0
Color(int r,int g,int b)
- 创建一个颜色对象
- 参数:r 红色值(0-255)
- 参数:g 绿色值(0-255)
- 参数:b 蓝色值(0-255)
API:java.awt.Graphics 1.0
Color getColor()
void setColor(Color c)
- 获取或改变当前的颜色。所有后续的绘图操作都使用这个新颜色
- 参数:c 新颜色
API:java.awt.Graphics2D 1.2
Paint getPaint()
void setPaint(Paint p)
- 获取或设置这个图形环境的绘制属性。Color类实现了Paint接口。因此,可以使用这个方法将绘制属性设置为纯色。
void fill(Shape s)
- 用当前的颜料填充该图形
API:java.awt.Component 1.0
Color getBackground()
void setBackground(Color c)
- 获取或设置背景颜色
- 参数:c 新背景颜色
Color getForeground()
void setForeground(Color c)
- 获取或设置前景颜色
- 参数:c 新背景颜色
7,文本使用特殊字体
- 如果经常选用不同的字体显示文本。人们可以通过字体名(font face name)指定一种字体。字体名由"Helvetica"这样的字体家族名(font family name)和一个可选的"Bold"后缀组成。例如:"Helvetica"和"Helvetica Bold"属于"Helvetica"家族的字体。
- 想知道某台计算机上允许使用的字体,需要调用GraphicsEnvironment类中的getAvailableFontFamilyNames方法。这个方法将返回一个字符型数组,其中包含了所有可用的字体名。
import java.awt.*;
public class ListFonts
{
public static void main(String[] args)
{
String[] fontNames = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames();
for (String fontName : fontNames)
{
System.out.println(fontName);
}
}
}
API:java.awt.Font 1.0
Font(String name,int style,int size)
- 创建一个新字体对象
- 参数:name 字体名。不是字体名(例如,“Helvetica Bold”),就是逻辑字体名(例如,“Serif”,“SansSerif”)
- 参数:style 字体风格(Font.PLAIN,Font.BOLD,Font.ITALIC或Font.BOLD+Font.ITALIC)
- 参数:size 字体大小
String getFontName()
- 返回字体名,例如,“Helvetica Bold”
String getFamily()
- 返回字体家族名,例如,“Helvetica”
String getName()
- 如果采用逻辑字体名创建字体,将返回逻辑字体,例如,“SansSerif”;否则,返回字体名。
Font deriveFont(int style) 1.2
Font deriveFont(float size) 1.2
Font deriveFont(int style,float size) 1.2
- 返回一个新字体,除给定大小和字体风格外,其余与原字体一样
API:java.awt.font.LineMetrics 1.2
float getLeading()
- 返回字体的行间距-从一行文本底端到下一行文本顶端之间的空隙
float getHeight()
- 返回字体的总高度-两条文本基线之间的距离(下坡度+行间距+上坡度)
API:java.awt.Graphics 1.0
Font getFont()
void setFont(Font font)
- 获取或设置当前的字体。这种字体将被应用与后续的文本绘制操作中。
- 参数:font 一种字体
void drawString(String str,int x,int y)
- 采用当前字体和颜色绘制一个字符串
- 参数:str 将要绘制的字符串
- 参数:x 字符串开始的x坐标
- 参数:y 字符串开始的y坐标
8,显示图像
- 对于照片这样的复杂图像来说,通常都是由扫描仪或特殊的图像处理软件生成的。
- 一旦图像保存在本地或网络上,就可以将它们读到Java应用程序中,并在Graphic对象上进行显示。
- 以下例子:在一个窗口中平铺显示了一幅图像。这里采用paintComponent方法来实现平铺显示。它的基本过程为:先在左上角显示图像的一个拷贝,然后使用copyArea将其拷贝到整个窗口。
import javax.swing.*;
import java.awt.*;
public class ImageTest
{
public static void main(String[] args)
{
JFrame frame = new ImageFrame();
frame.setTitle("ImageTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
/*
* A frame with an image component
* */
class ImageFrame extends JFrame
{
public ImageFrame()
{
add(new ImageComponent());
pack();
}
}
/*
* A component that displays a tiled image
* */
class ImageComponent extends JComponent
{
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
private Image image;
public ImageComponent()
{
image = new ImageIcon("blue-ball.gif").getImage();
}
public void paintComponent(Graphics g)
{
if (image == null)
{
return;
}
int imageWidth = image.getWidth(this);
int imageHeight = image.getHeight(this);
//draw the image in the upper-left corner
g.drawImage(image, 0, 0, null);
//tile the image across the component
for (int i = 0; i * imageWidth <= getWidth(); i++)
{
for (int j = 0; j * imageHeight <= getHeight(); j++)
{
if (i + j > 0)
{
g.copyArea(0, 0, imageWidth, imageHeight, i * imageWidth, j * imageHeight);
}
}
}
}
public Dimension getPreferredSize()
{
return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)