<Java>15 图形界面设计

本文最后更新于:2023年6月27日 上午

15 图形界面设计

图形用户界面(Graphical User Interface,简称 GUI)是大多数程序不可缺少的部分。

Java 的图形界面由各种组件组成。在 java.awt 和 java.swing 包中定义了多种用于创建图形用户界面的组件类。

Swing 组件和 AWT 组件最大的不同是 Swing 组件实现时不包含任何本地代码,因此不受硬件平台的限制,而具有更多的功能,并且在任何平台上运行效果都是相同的。不包含本地代码的 Swing 组件被称为 “轻量级” 组件,而 AWT 被称为 “重量级” 组件。两种组件一同使用的场合,AWT 总是显示在上面。

设计用户界面是一般有 3 个步骤:

  1. 选取组件
  2. 设计布局
  3. 响应事件

15.1 容器

组件分为容器组件和非容器组件。容器组件即可以包含其他组件的组件。非容器组件必须包含在容器组件中。

容器组件分为:顶层容器、一般用途容器

15.1.1 顶层容器

Swing 中提供了 4 种顶层容器:

  • JFrame:带有标题行和控制按钮(最小化、恢复/最大化、关闭)的独立窗口。有时称为框架。创建程序时要使用 JFream
  • JApplet:创建小应用程序时要使用 JApplet。其被包含在浏览器窗口中
  • JDialog:创建对话框时使用 JDialog
  • JWindow:一个不带有标题行和控制按钮的窗口。一般很少使用

构造方法:

  • new JFrame():构造一个初始不可见,无标题的新框架窗体
  • new JFrame("Title"):构造一个初始不可见,具有指定标题的新框架窗体

常用方法:

  • void setBounds(int x, int y, int width, int height):移动并调整框架大小。框架左上角位置为(x, y),框架大小为 width × height

  • void setSize(int width, int height):设置窗口大小

  • void setBackground(Color bg):设置框架背景色

    void setForeground(Color fg):设置框架前景色

  • void setVisible(boolean aFlag):设置可见性

  • void pack():自适应框架大小,以符合子组件的首选大小和布局

  • void setTitle(String title):设置标题

  • Container getContentPane():返回此框架窗体的内容窗格对象

    Container 类是所有容器类的父类,包含容器的共有操作

    void setContentPane(Container contentPane):把指定内容窗格设置为此框架的内容窗格对象

  • void setLayout(LayoutManager manager):设置布局管理器

—— 哦我的上帝啊,如果有什么名词是你不懂的,为什么不试着继续看下去呢?

15.1.2 内容窗格

4 个顶层容器每个都有 1 个内容窗格。除菜单外,顶层容器的所有组件都放在这个内容窗格内。

  • 直接添加组件至内容窗格

    Container contentPane = jframe.getContentPane();		//[1] 获取内容窗格对象
    contentPane.add(button, BorderLayout.CENTER);			//[2] 将组件添加到内容窗格
    1. 使用顶层容器的 getContentPane() 方法获得其内容窗格对象。

    2. 将组件添加到内容窗格。

      其中 button 是一个按钮控件,BorderLayout.CENTER 代表位置在中间

      向顶层容器内容窗格添加组件时,也可以直接调用顶层容器的 add() 方法

  • 以新的内容窗格代替原有内容窗格

    JPanel contentPane = new JPanel();					//[1] 创建 JPanel 实例
    contentPane.setLayout(new BorderLayout());			//[2] 创建布局管理器
    contentPane.add(button, BorderLayout.CENTER);		//[3] 添加组件
    jfream.setContentPane(contentPane);					//[4] 添加内容窗格
    1. 创建 JPanel(面板)实例。JPanel 是 Container 的子类。

    2. 顶层容器默认的布局管理器是 BorderLayout,而 JPanel 的默认布局管理器是 FlowLayout

    3. 通过 setContentPane(contentPane) 方法为 jfream 设置新的内容窗格

15.1.3 面板

普通面板(JPanel)和滚动面板(JScrollPanel)都是用途广泛的容器。面板与顶层容器不同,不能独立存在,而必须添加到其他容器内部。面板可以嵌套,由此可以设计出复杂的图形用户界面。

#15.1.3.1 JPanel

构造方法:

  • new JPanel():创建具有 FlowLayout 布局的新面板
  • new JPanel(LayoutManager layout):创建指定布局的新面板

常用方法:

  • Component add(Compinent comp):将指定组件添加至面板

#15.1.3.2 JScrollPanel

JScrollPanel 是一个带有滚动条的面板,但只能添加一个组件。添加多个组件的场合,先将那些组件添加入 JPanel 对象,再将该 JPanel 对象添加进 JScrollPanel 对象中

构造方法:

  • new JScrollPanel():创建一个空的 JScrollPanel。水平、垂直滚动条都能显示
  • new JScrollPanel(Component view):创建指定组件内容的 JScrollPanel

常用方法:

  • void setHorizontalScrollBarPolicy(int policy):确定水平滚动条何时显示

    其中 policy 的可选值是以下三种:

    • ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED:需要时可见
    • ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER:永远不可见
    • ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS:永远可见
  • void setVerticalScrollBarPolicy(int policy):确定垂直滚动条何时显示

    其中 policy 的可选值是以下三种:

    • ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED:需要时可见
    • ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER:永远不可见
    • ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS:永远可见

#15.1.3.3 Scrollbar

AWT 中还有一个滚动条组件,提供了允许用户在一定范围的值中进行选择的便捷方式

构造器:

  • new Scrollbar():构造一个新的滚动条

  • new Scrollbar(int orientation):构造一个有指定方向的滚动条

    其中 orientation 的可选值是:

    • Scrollbar.HORIZONTAL:水平滚动条
    • Scrollbar.VERTICAL:垂直滚动条
  • new Scrollbar(int orientation, int value, int visible, int minimum, int maximun):构造一个有初始方向、初始值、可视量、最小/最大值的滚动条

15.2 标签和按钮

15.2.1 标签

标签(JLable)是最简单的 Swing 组件,通常用于显示提示性的文本信息或图标。其不可被编辑

构造器:

  • new JLable():构造一个不显示文本或图标的空标签

  • new JLable(Icon image):构造一个显示图标的标签

  • new JLable(String text):构造一个显示文本的标签

  • new JLable(Icon image, int horizontalAlignment):构造一个显示图标的标签,并指定水平对齐方式

    其中 horizontalAlignment 的取值可以是:

    • JLable.LEFT:左对齐
    • JLable.RIGHT:右对齐
    • JLable.CENTER:居中对齐
  • new JLable(String text, int horizontalAlignment):构造一个显示文本的标签,并指定水平对齐方式

  • new JLable(String text, Icon image, int horizontalAlignment):构造一个同时显示文本和图标的标签,并指定水平对齐方式

15.2.2 按钮

按钮(JButton)是 Java 图形用户界面的基本组件之一。

经常用到的按钮有 4 种形式:按钮(JButton)、切换按钮(JToggleButton)、复选按钮(JCheckButton)、单选按钮(JRadioButton)

这些按钮类均是 AbstractButton 的子类或间接子类

#15.2.2.1 JButton

构造器:

  • new JButton():构造一个既没有文本也没有图标的按钮
  • new JButton(Icon icon):构造一个有图标的按钮
  • new JButton(String text):构造一个有文本的按钮
  • new JButton(String text, Icon icon):构造一个有文本也有图标的按钮

常用方法:

  • void setMnemonic(int mnemonic):设置当前按钮的键盘助记符

  • void setText(String text):设置按钮的文本

    void setIcon(Icon icon):设置按钮图标

  • void setEnabled(boolean mod):是否启用按钮

  • String getText():返回按钮的文本

  • void setToolTipText():设置提示文本

  • void addActionListener(ActionListener l):为按钮添加事件监听程序

    void removeActionListener(ActionListener l):移除事件监听程序

#15.2.2.2 JToggleButton、JCheckButton、JRadioButton

JToggleButton 是有两种状态(选中状态、未选中状态)的按钮。通过点击切换这两种状态

JCheckButton、JRadioButton 是 JToggleButton 的子类,构造方法与 JToggleButton 相同。

构造器:

  • new JToggleButton():构造一个没有文本也没有图标的切换按钮

  • new JToggleButton(Icon icon):构造一个有图标的切换按钮

    new JToggleButton(Icon icon, boolean selected):构造一个有图标的切换按钮,设置其初始状态

  • new JToggleButton(String text):构造一个有文本的切换按钮

    new JToggleButton(String text, boolean selected)

  • new JToggleButton(String text, Icon icon):构造一个有文本也有图标的切换按钮

    new JToggleButton(String text, Icon icon, boolean selected)

常用方法(除 JButton 方法外):

  • boolean isSeleced():获取按钮的当前状态

  • void addItemListener(ItemListener l):为按钮添加事件侦听程序

    void removeItemListener(ItemListener l):移除事件侦听程序

15.3 布局管理器

容器中包含了组件。组件的布局,包括其位置和大小,通常由布局管理器负责安排。每个容器都有一个默认的布局管理器。

15.3.1 FlowLayout 流布局管理器

FlowLayout 定义在 java.awt 包中。

构造器:

  • new FlowLayout():创建默认的 FlowLayout 布局管理器。

    居中对齐。默认水平、垂直间距是 5 像素

  • new FlowLayout(int align):创建一个 FlowLayout 布局管理器。

    指定对齐方式。默认水平、垂直间距是 5 像素

    align 的可选值有这些:

    • FlowLayout.LEFT:左对齐
    • FlowLayout.RIGHT:右对齐
    • FlowLayout.CENTER:居中对齐
  • new FlowLayout(int align, int hgap, int vgap):创建一个 FlowLayout 布局管理器。

    指定对齐方式。指定水平、垂直间距

使用说明:

  1. FlowLayout 对容器中组件进行布局的方式是将组件逐个放置在容器中的一行上。一行满后,另起一行。
  2. 与其他布局管理器不同。FlowLayout 不会强行设定组件的大小,而是通过每个组件的 getPreferredSize() 方法获取其各自的期望大小

15.3.2 BorderLayout 边界布局管理器

BorderLayout 定义在 java.awt 包中,是顶层容器的默认布局管理器。它提供了一种较为复杂的组件布局管理方案。

构造方法:

  • new BorderLayout():一个组件间没有间距的布局管理器
  • new BorderLayout(int hgap, int vgap):定义水平、垂直间距的布局管理器

使用说明:

  1. 每个由 BorderLayout 管理的容器被划分成 5 个区域,分别是容器的 上部(BorderLayout.NORTH)、下部(BorderLayout.SOUTH)、左部(BorderLayout.WEST)、右部(BorderLayout.EAST)、中部(BorderLayout.CENTER)
  2. 在 BorderLayout 布局管理器的管理下,组件必须通过 add() 方法加入容器的指定区域。不指定的场合,默认加入中部区域
  3. 容器的每个区域仅能加入一个组件。加入了多个组件的场合,只有最后一个生效
  4. 对于中部以外的 4 个边界区域,没有使用的区域的大小将变为零。此时,中部区域会扩展并占据该未用区域的位置。如果 4 个边界区域都没有使用,中部区域会占据整个窗口。
  5. 窗口大小改变时,按钮的相对位置不会变化。但按钮的大小会改变

15.3.3 GridLayout 网格布局管理器

GridLayout 定义在 java.awt 包中,是一种网格式的布局管理器。

构造器:

  • new GridLayout():创建一个一行的网格。列数根据实际需要决定

  • new GridLayout(int rows, int cols):指定行数、列数的网格布局

    rows 和 cols 中,最多有一个可以是 0,但不能都为 0。那个为 0 的场合,根据实际需要决定数量

  • new GridLayout(int rows, int cols, int hgap, int vgap):指定行数、列数,也指定水平、垂直间距的网格

使用说明:

  1. GridLayout 将容器空间划分成若干行乘若干列的网格。组件依次放入其中,每个组件占据一格

  2. 网格每列宽度相同,每行高度相同。组件放入的次序决定了其位置

  3. 想要组件间留有空白的场合,可以添加一个空白标签

  4. 网格数多于组件数的场合,那些多余的格子为空白。

    网格数少于组件数的场合,系统根据需要适当添加。

  5. 窗口大小改变时,按钮的相对位置不会变化。但按钮的大小会改变

15.3.4 CardLayout 卡片式布局管理器

CardLayout 定义在 java.awt 包中,是一种卡片式的布局管理器。

构造器:

  • new CardLayout():一个默认无间距的 CardLayout 布局管理器
  • new CardLayout(int hgap, int vgap):指定水平、垂直间距的 CardLayout 布局管理器

常用方法:

  • void first(Container parent):翻转到容器的第一张卡片

    void next(Container parent):翻转到下一张卡片。当前是最后一张的场合,翻到第一张卡片

    void previous(Container parent):翻转到前一张卡片。当前是第一张的场合,翻到最后一张卡片

    void last(Container parent):翻转到容器的最后一张卡片

  • void show(Container parent, String name):翻转到卡片集中具有指定 name 的卡片。没有该卡片的场合不执行任何操作

使用说明:

  1. CardLayout 将容器中的组件处理为一系列卡片,每一刻只显示其中一张。
  2. 容器第一次显示时,显示第一个添加的组件。

15.3.5 BoxLayout 方框布局管理器

BoxLayout 定义在 javax.swing 包中,其组件横排一行或竖排一列,但宽度(高度)可以不同。

构造器:

  • new BoxLayout(Container target, int axis):创建一个沿给定轴放置组件的布局管理器

    其中 target 表明为哪个容器设置此布局管理器,axis 指明组件排列方向

    axis 的值是:

    • BoxLayout.X_AXIS:水平方向排列
    • BoxLayout.Y_AXIS:竖直方向排列

    举个例子:

    JPanel jp = new JPanel();
    jp.setLayout(new BoxLayout(jp, BoxLayout.X_AXXIS));

使用说明:

  1. BoxLayout 将容器中的组件横排一行或竖排一列。那些组件横排一行时,可以有不同宽度;竖排一列时,可以有不同的高度。
  2. 窗口大小改变时,按钮的相对位置不会变化。

Box 类

javax.swing 中定义了一个专门使用 BoxLayout 的容器 Box 类。

  • static Box createHorizontalBox():返回一个使用水平方向的 BoxLayout 的 Box

    static Box createVerticalBox():返回一个使用竖直方向的 BoxLayout 的 Box

  • static Component createHorizontalGlue():创建一个水平方向的不可视的组件(填满剩余空间)

    static Component createVerticalGlue()

  • static Component createHorizontalStrut():创建一个水平方向的不可视的组件(指定宽高)

    static Component createVerticalStrut()

  • static Component createRigidArea():创建一个不可视的组件,不大不小,尺寸真是好极了

15.3.6 空布局

其实也能不用布局管理器的,真的

  1. 调用容器的 setLayout(null) 将容器的布局管理器置空
  2. 调用组件的 setBounds(x, y, w, h) 方法设置其位置和大小。~老东西,你的布局管理器最没用啦!~

15.4 事件处理

Java 运行时,如果用户进行某个操作,程序应当做出相应。

程 · 序 · 无 · 响 · 应(噔 噔 咚)

……总之,用户在程序界面进行的操作称为用户事件,对事件的相应称为事件处理。

15.4.1 事件处理模型

Java 事件处理是采取 “委派事件模型”。当事件发生时,产生事件类对象。这里说的事件类对象实际上就是 java.awt.event 事件类库里某个类创建的对象。操作不同的场合,事件类对象不同。

会把此事件类对象传递给事件侦听程序处理。它是实现了对应侦听程序接口的一个类。

事件只是一个对象,其只向注册的侦听程序报告

示范一个简单的事件处理:

import javax.seing.*;
import java.awt.*;													//[0]

public class Code_15_4_1 {
    public static void main(String[] args) throws InterruptedException {
        Button b = new Button("Button");
        b.addActionListener((e) -> System.out.println("Pressed"));	//[1]
        JFrame jFrame = new JFrame("Test");
        jFrame.setBounds(30, 30, 100, 100);
        jFrame.add(b);
        jFrame.setVisible(true);
    }
}
  1. 引入 java.awt.event 包

  2. 注册事件侦听程序,并实现其方法

    示例中的简写其实相当于以下代码(匿名内部类):

    b.addActionListener(new ActionListener() {
        @OverRide
        public void actionPerformed (ActionEvent e) {
            System.out.println("Pressed");
        }
    });

    —— 示例写法见 [27 Java8 新特性]

    事件侦听程序可以定义在单独的类中,也可以定义在组件类中:

    class MyButton extends JButton implements ActionListener{
        public MyButton() {
            addActionListener(this);
        }
    	                                 
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Pressed");
        }
    }

15.4.2 事件的种类

在 java.awt.event 包和 javax.swing.event 包中定义了很多其他的事件类。每种事件类有一个对应的接口,接口中声明了一个或多个抽象的事件处理方法。

事件类 组件 方法及说明
ActionEvent JButton、JCheckBox、JComboBox、JMenuItem、JRaidoButton actionPerformed(e) 单击按钮、选择菜单项或在文本框中按回车时
AdjustmentEvent JScrollBar adjustmentValueChanged(e) 当改变滚动条滑块位置时
ComponentEvent JComponent 及其子类 componentMoved(e) 组件移动时;componentHidden(e) 组件隐藏时;componenetResized(e) 组件缩时;componentShown(e) 组件显示时
ContainerEvent JContainer 及其子类 containerAdded(e) 添加组件时;containerMoved(e)移除组件时
FocusEvent 同 ComponentEvent focusGained(e) 组件获得焦点时;focusLost(e) 组件失去焦点时
ItemEvent JCheckBox、JCheckboxMenuItem、JComboBox itemStateChanged(e) 选择复选框、选项框、单击列表框、选中带复选框菜单时
KeyEvent 同 ComponentEvent keyPressed(e) 键按下时;keyReleased(e) 键释放时;keyTaped(e) 击键时
MouseEvent 同 ComponentEvent mousePressed(e) 鼠标按下时;mouseEntered(e) 鼠标进入时;mouseExited(e) 鼠标离开时;mouseClicked(e) 鼠标点击时;mouseReleased(e) 鼠标释放时
MouseMotionEvent 同 ComponentEvent mouseDragged(e) 鼠标拖放时;mouseMoved(e) 鼠标移动时
TextEvent JTextField、JTextArea textValueChanged(e) 文本框、多行文本框内容修改时
WindowEvent JFrame、JWindow、JDialog windowOpened(e) 窗口打开时;windowClosing(e) 窗口关闭时;windowClosed(e) 窗口关闭后;windowActived(e) 窗口激活时;windowDeactivated(e) 窗口失去焦点时;windowIconified(e) 窗口最小化时;WindowDeiconified(e) 窗口最小化还原时

使用说明:

  1. XXXEvent 事件类的接口名就是 XXXListener。占地方太大,上面就没写

  2. 事件侦听模式允许为一个组件多次调用 addListener 方法,注册多个侦听程序。

    事件发生时,单个事件的多个侦听程序的调用顺序不确定。

  3. 调用事件处理方法时会传入一个参数。该参数就是那些事件类实例,其中包含事件有关的重要信息。

    调用这些事件类实例各自特有的方法获取这些信息。

15.4.3 事件适配器

侦听程序必须实现接口的全部抽象方法,但有时我们只关心其中的某一种方法。为了编程方便,Java 为一些声明了多个抽象方法的 Listener 接口提供了相应的适配器类。

接口名称 适配器名称
ComponentListener ComponentAdapter
ContainerListener ContainerAdapter
FocusListener FocusAdapter
KeyListener KeyAdapter
MouseListener MouseAdapter
MouseMotionListener MouseMotionAdapter
MouseInputListener MouseInputAdapter
WindowListener WindowAdapter

这些适配器实现了接口的全部抽象方法,只是方法内容为空

这样,创建新类时可以不必实现接口,而是继承适配器类,并重写需要的方法

15.5 Java 绘图技术

Java 语言约定,显示屏上一个长方形区域为程序绘图区域,坐标原点(0, 0)位于整个区域左上角。

一个坐标点(x, y)对应一个像素,其中坐标点的 x、y 必须是非负整数。x 沿水平方向从左向右递增、y 沿竖直方向从上往下递增

15.5.1

可以使用 java.awt 包中的 Color 类来定义和管理颜色。Color 类的每个对象代表一种颜色。

Color 类有 26 个常量,代表 13 种预定义颜色:

颜色 对象 ᓚᘏᗢ
黑色(#000000) Color.black Color.BLACK
蓝色(#0000FF) Color.blue Color.BLUE
青色(#00FFFF) Color.cyan Color.CYAN
灰色(#808080) Color.gray Color.GRAY
深灰色(#404040) Color.darkGary Color.DARKGARY
浅灰色(#C0C0C0) Color.lightGary Color.LIGHTGARY
绿色(#00FF00) Color.green Color.GREEN
洋红色(#FF00FF) Color.magenta Color.MAGENTA
橙色(#FFC800) Color.orange Color.ORANGE
粉红色(#FFAFAF) Color.pink Color.PINK
红色(#FF0000) Color.red Color.RED
白色(#FFFFFF) Color.write Color.WRITE
黄色(#FFFF00) Color.yellow Color.YELLOW

也可以通过绿三原色值来组合。每种颜色由三个值组成(RGB),值的范围是 [0, 256):

Color color = new Color(102, 204, 255);

这个颜色是:天依蓝(#66CCFF)

这部分笔记恐怕是所有 Java 笔记里唯一有五颜六色的地方了,真难得

15.5.2 字体

文字有 字体、样式、字号 三个要素

基本的样式有:

  • Font.PLAIN:正常(0)

  • Font.BOLD:粗体(1)

  • Font.ITALIC:斜体(2)

    样式可以组合使用,如 (Font.BOLD + Font.ITALIC) 即 粗斜体

常用的字体:Times New roman(Times New roman)、Symbol(Symbol)、宋体(宋体)、楷体(楷体)

构造器:

  • new Font(String name, int style, int size):新建字体,指定字体、样式、字号

常用方法:

  • String getName():返回其字体名称

    int getSize():返回其字号大小

    int getStyle():返回其样式

  • boolean isBold():是否是粗体

    boolean isItalic()boolean isPlain()

15.5.3 Graphics 类

java.awt 包下的 Graohics 类是所有图形处理的基础,是所有图形上下文的抽象父类。其允许应用程序在组件及屏幕图像上进行绘制。

当先后绘制的图形不同时,确定重叠部分颜色的方法称为绘图模式。

绘图模式分为两种:

  • 正常模式:setPaintMode()

    后绘制的图形覆盖先绘制的图形。

  • 异或模式:setXORMode(Color c)

    当前绘制的颜色、先前绘制的颜色 及 选定的颜色 c 之间进行某种处理后,用新的颜色绘制。

    这个模式下,如果使用同一颜色绘制 2 次,则相当于擦除之前绘制的图形,即恢复原本状态。

若要在某个组件中绘图,应重写该组件的 paint(Graphics g) 方法,并在重写的方法内进行绘图。

  • paint(Graphics g):组件被显示出来时,调用该方法

    以下情况该方法会被调用

    • 组件第一次在屏幕显示时
    • 窗口最小化/最大化
    • 窗口大小发生变化
    • repaint 函数被调用
  • repaint():重绘组件

    该方法默认情况下会调用以下方法

    • paintCompnent(Graphics g):绘制组件

      一般情况下,要在 JComponent 子类的组件中绘图,重写该方法即可

    • paintBorder(Graphics g):绘制组件边框

    • paintChildren(Graphics g):绘制组件的子组件

设置画笔:

  • setColor(Color c):设置画笔前景色

    setBackgroud(Color c):设置背景色

    每个图形环境都有一种画图时正在使用的前景色。画图所在的每个表面都有背景色

  • setFont(Font f):设置画笔字体

绘制几何图案:

  • drawArc(int x, int y, int width, int height, int startAngle, int arcAngle):绘制弧线

    该弧线是 沿着起始点为 (x, y)、宽 width、高 height 的矩形所限定的椭圆 绘制一条弧线。

    该弧线起始角度为 startAngle,弧度角度为 arcAngle

    fillArc(int x, int y, int width, int height, int startAngle, int arcAngle):填充扇形

  • drawLine(int x1, int y1, int x2, int y2):绘制线段

    该线段的两个端点是 (x1, y1) 和 (x2, y2)

  • drawOval(int x, int y, int width, int height):绘制椭圆

    一个起始点为 (x, y)、宽 width、高 height 的矩形所限定的椭圆

    fillOval(int x, int y, int width, int height):填充椭圆

  • drawPolygon(int[] xPoints, int[] tPoints, int nPoints):绘制多边形

    drawPolygon(Polygon p):也能通过传入一个 Polygon 对象来绘制多边形

    该图形的端点由传入参数确定。如果最后一个端点和第一个端点不相等,那么图形可能不闭合

    fillPolygon(int[] xPoints, int[] tPoints, int nPoints):填充多边形

    fillPolygon(Polygon p):通过传入一个 Polygon 对象来填充多边形

    低情商:这咋填充?高情商:留给读者们思考吧

  • drawRect(int x, int y, int width, int height):绘制矩形

    一个起始点为 (x, y)、宽 width、高 height 的矩形

    fillRect(int x, int y, int width, int height):填充矩形

  • drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight):圆角矩形

    一个起始点为 (x, y)、宽 width、高 height 的矩形,其圆角形状由 arcWidth、arcHeight 确定

    其实就是矩形(线段)和椭圆(圆弧)的某种拼接

    fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight):填充圆角矩形

  • drawString(String str, int x, int y):输出字符串

    在 (x, y) 处输出字符串 str,向右扩展

    drawChars(char[] chars, int offSet, int length, int x, int y):输出字符串

    从字符数组的 offSet 下标处起,在 (x, y) 处输出 length 个字符,向右扩展

    drawBytes(byte[] data, int offSet, int length, int x, int y):还不是一样?

  • draw3DRect(int x, int y, int width, int height, boolean raised):绘制 3D 矩形

    fill3DRect(int x, int y, int width, int height, boolean raised):填充 3D 矩形

    我感觉是和 PS 里的浮雕效果类似,生成了亮部和暗部。rasied 决定是凸起还是凹陷。

#15.5.3.1 Polygon 类

Polygon 对象封装了多边形的坐标。

构造方法:

  • new Polygon():构造一个空的多边形。

    无为太虚,无生一,一生二,二生三,三生万物。所以,空的多边形也是多边形。

  • new Polygon(int[] xs, int[] ys, int n):构造一个 n 点连接成的多边形

常用方法:

  • addPoint(int x, int y):将该点加入多边形中

  • boolean contains(int x, int y):如果多边形包含该点,则返回真

    boolean contains(Point p)

  • get Bounds():得到多边形的外接矩形

  • translate(int dx, int dy):偏移

    将多边形各点沿 x 轴偏移 dx,再沿 y 轴偏移 dy

15.5.4 Graphics2D 类

为了解决图形对象的局限性,Java 1.1 后 引入了 Java 2D,其包含一个继承自 Graphics 的 Graphics2D 类,增加了很多状态属性,扩展了 Java 的绘图功能

Graphics2D 拥有强大的二维图形处理能力,提供对几何形状、坐标转换、颜色管理、文字布局等更复杂的控制

#15.5.4.1 图形状态属性

通过设定和修改属性,可以指定画笔宽度和画笔连接方式、设定平移、旋转、缩放或裁剪变换图形,还能设置填充图形的颜色和图案等。

状态属性:

  • stroke 属性:

    该属性控制线宽、笔形样式、线段连接方式、短划线图案。

    使用 setStroke(Stroke s) 方法设置 stroke 属性。

    构造方法:

    • new BasicStroke(float w):指定线宽的 stroke

    • new BasicStroke(float w, int cap, int join):指定线宽、端点样式 cap、线段交汇方式 join 的 stroke

      其中,端点样式 cap 的值可以是:

      • BasicStroke.CAP_BUTT:无修饰(0)
      • BasicStroke.CAP_ROUND:半圆形末端(1)
      • BasicStroke.CAP_SQUARE:方形末端(2,默认值)

      线段交汇方式 join 的值可以是:

      • BasicStroke.JOIN_BEVEL:无修饰(2)
      • BasicStroke.JOIN_MITER:尖型末端(0,默认值)
      • BasicStroke.JOIN_ROUND:圆形末端(1)
  • paint 属性:

    该属性控制填充效果。

    使用 setPaint(Paint p) 方法设置 paint 属性

    构造方法:

    • new GradientPaint(float x1, float y1, Color c1, float x2, float y2, Color c2):构造一个简单的非周期性的 paint 对象。

      从点 (x1, y1) 至点 (x2, y2) 处,颜色由 c1 渐变至 c2

    • new GradientPaint(float x1, float y1, Color c1, float x2, float y2, Color c2, boolean cyclic):构造一个周期或非周期性的 paint 对象。

      如果希望渐变至终点又是起点的颜色,将 cyclic 设定为 true

  • transform 属性:

    该属性用来实现常用的图形平移、缩放、斜切等

    使用 setTransform(Transform t) 方法设置 transform 属性

    构造方法:

    • new AffineTransform():构造一个表示仿射变换的新的 tansform

      仿射变换:用我的话来讲,就是保持坐标点不变的情况下变换坐标系,能形成的变换

    常用方法:

    • setToRotation(double theta):旋转 theta 角度

      setToRotation(double theta, double x, double y):以 (x, y) 为旋转中心旋转

      rotate(double theta, double x, double y)

    • setToScale(double sx, double sy):拉伸变换

      x、y 方向按照 sx、yx 比例变换

      scale(double sx, double sy)

    • setToTranslation(double tx, double ty):平移变换

      translate(double tx, double ty)

    • setToShear(double shx, double shy):斜切变换

      shx、shy 分别指定 x、y 方向的斜拉度

    看得出来,出版社的人写到这里应该是到了下班的点了。内容不明不白的不说,还写错了好几处。

    我笔记上是改过来的。放心。

    就这还 ”指定教材“ 呢。垃圾,还没我笔记写得好。

  • clip 属性:

    该属性用于实现剪裁效果。

    使用 setClip(Shape clip) 方法,确定裁剪区域的 Shape。可以连续使用该方法以得到其交集区域

  • composit 属性:

    该属性设置图形重叠区域的效果

    通过 Alpha.Composite.getInstance(int rule, float alpha) 得到一个实例。其中 alpha(透明度)的范围是 [0.0f, 1.0f]

    至于 rule 是什么……我也不知道。或许不重要吧

    通过 setComposite(Composite comp) 设置混合效果

#15.5.4.2 Graphics2D 的绘图方法

Graphics2D 保留了 Graphics 的绘图方法,又增加了很多新方法

另外,在 java.awt.geom 中声明了一系列类,能用于创建各种几何图形对象,包括:Line2D 线段类、Rectangle2D 矩形类、RoundRectangle2D 圆角矩形类、Ellipse2D 椭圆类、Arc2D 圆弧类、QuadCurve2D 二次曲线类、CubicCurve2D 三次曲线类

这些类都是抽象类,但这些类包中有实现了其方法的 Double 类。

...
@OverRide
public void paintComponents(Graphics g) {
    Graphics2D g2d = (Graphics2D)g;						//[1]
    Line2D line = new Line2D.Double(5, 5, 5, 5);		//[2]
    g2d.draw(line);										//[3]
}
  1. 将 Graphics 对象强制转型为 Graphics2D 对象

  2. 创建几何图形对象

    这里的 Line2D.Double 表示 Line2D 包下的 Double 类。此处调用了 Double 类的构造器

  3. 绘制线段

#15.5.4.3 Graphics2D 中的几何图形类

  • new Line2D.Double(int x1, int y1, int x2, int y2):线段

    从 (x1, y1) 到 (x2, y2) 的线段

  • ……(略了略了。相信椭圆、矩形之类的也不用再详细说明了吧)

  • new Arc2D.Double(double x, double y, double w, double h, double start, double extent, int type):弧

    但是特别地,type 的值是以下几种:

    • Arc2D.OPEN:开弧
    • Arc2D.CHORD:弓弧
    • Arc2D.PIE:饼弧
  • new QuadCurver2D.Double(double x1, double y1, double ctrlx, double ctrly, double x2, double y2):绘制二次曲线

    绘制二次曲线需要 3 个点,分别是起始点 (x1, y1)、终点 (x2, y2)、控制点 (ctrlx, ctrly)

  • new CubicCurve2D.Double(double x1, double y1, double ctrlx1, double ctrly1, double ctrlx2, double ctrly2, double x2, double y2):绘制三次曲线

    绘制三次曲线需要 4 个点,分别是起始点、终点、两个控制点

15.6 组合框与列表

15.6.1 JComboBox 组合框

JComboBox 是一个下拉式菜单。它有两种模式:可编辑的、不可编辑的。

对于不可编辑的 JComboBox,用户只能在现有列表中进行选择

对于可编辑的 JComboBox,用户既能在现有选项中选择,也能输入新的内容

构造方法:

  • new JComboBox<E>():创建一个 E 类型(泛型)的没有任何可选项的默认组合框

  • new JComboBox<E>(E[] items):根据 items 数组创建组合框

    items 数组元素即为组合框的可选项

常用方法:

  • void setEditable(boolean aFlag):设置可编辑性

    不设置的场合,默认处于不可编辑状态

  • void addItem(E item):在末尾添加可选项

    void insertItemAt(E item, int index):在指定下标处添加可选项

  • void removeAllItems():删除所有可选项

    void removeItem(E iten):删除 item 指定的可选项

    void removeItemAt(int index):删除指定下标处的可选项

  • E getItemAt(int index):获取指定下标的可选项

  • int getItemCount():获取列表项数

  • int getSelectedIndex():获取选中项匹配的第一个选项的索引下标

    E getSelectedItem():获取选中项

15.6.2 JList 列表

JList 是可供用户选择的一系列可选项

构造方法:

  • new JList<E>():构造一个空列表
  • new JList<E>(E[] listData):构造一个列表,可选元素由 listData 指定
  • new JList<E>(Vector<E> listData):构造一个列表,使其显示指定 Vector 中的元素

常用方法:

  • addListSelectionListener(ListSelectionListener l):添加监视器

    当用户在列表上选择时,会触发 ListSelectionEvent 事件。

    在 ListSelectionListener 接口中,仅有一个方法:

    void valueChanged(ListSelectionEvent e);

    当列表的当前选项改变时,会调用该方法。

  • int getSelectedIndex():返回选中项第一次出现的下标索引

    没有选中项的场合,返回 -1

    E getSelectedValue():返回所选的第一个值

    没有选中项的场合,返回 null

  • void setVisableRowCount(int count):设置不使用滚动条可以在列表中显示的选项行数

  • void setSelectionMode(int mode):设置列表的选择模式

    其中,mode 的值可以是以下几种:

    • ListSelectionModel.SINGLE_SELECTION:仅支持单项选择(0)
    • ListSelectionModel.SINGLE_INTERVAL_SELECTION:可多选,但多个选项必须是连续的(1)
    • ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:可多选(2,默认值)

15.7 文本组件

文本组件可以提示信息和提供用户输入功能。Swing 中提供了 JTextField(文本域)、JPasswordField(口令输入域)、JTextArea(文本区)等多个文本组件。

文本组件的共同的父类是 JTextComponent,其中定义了文本组件的共有方法:

  • String getSelectedText():从文本组件中提取被选中的文本内容

  • String getText():从文本组件中提取全部文本内容

    String getText(int offs, int len):从文本组件中提取指定范围的文本内容

  • void select(inr start, int end):在文本组件中选中指定范围内容

    void selectAll():在文本组件中选中全部内容

  • void setEditable(boolean b):设置可编辑状态

  • void setText(String t):设置文本组件的文本内容

  • void setDocument(Document doc):设置文本组件的文档

  • void copy():复制选中文本至剪贴板

    void cut():剪切选中文本至剪贴板

    void paste():粘贴剪贴板内容至当前位置

另外,JComponrnt 类中有如下方法:

  • boolean requestFocusInWindow():请求当前组件获得输入焦点

15.7.1 JTextField 文本域

文本域是一个单行的文本输入框,可以用于输入少量文本

构造方法:

  • new JTextField():构造一个空文本域

  • new JTextField(int columns):构造一个指定列数的空文本域

    由于组件大小通常由布局管理器确定,因此指定的列数可能被忽略

  • new JTextField(String text):构造一个显示指定初始字符的文本域

  • new JTextField(String text, int columns):构造一个指定列数及初始字符的文本域

常用方法:

  • void addActionListener(ActionListener l):添加指定侦听器

    void removeActionListener(ActionListener l):移除指定侦听器

  • void setFont():设置当前字体

  • void setHorizontalAlignment(int alignment):设置水平对齐方式

    有效值包括:

    • JTextField.LEFT:左对齐(2)

    • JTextField.RIGHT:右对齐(4)

    • JTextField.CENTER:居中对齐(0)

    • JTextField.LEADING:领先对齐(10)

      (似乎是)识别文字前端的对齐方式……好吧,我也不太明白

    • JTextField.TRAILING:落后对齐(11)

  • int getColumns():返回文本域列数

15.7.2 JTextArea 文本区

JTextArea 是一个多行多列的文本输入框

构造方法:

  • new JTextArea():构造一个空文本区
  • new JTextArea(int rows, int columns):构造一个指定行数、列数数的空文本区
  • new JTextArea(String text):构造一个显示指定初始字符的文本区
  • new JTextArea(String text, int rows, int columns):构造一个指定行列数及初始字符的文本区

常用方法:

  • void append(String str):追加文本到文本区

  • void insert(String str, int pos):将指定文本插入到特定位置 pos 处

  • void replaceRange(String str, int start, int end):用指定文本 str 替换指定范围的文本

  • void addAncestorListener(AncestorListener listener):添加指定侦听器

    特别地,用户输入文本时,按下 Enter 键的场合只是向缓冲区输入一个字符,而不能表示输入的结束。因此,需要识别用户输入完成时,通常要在文本区旁放置一个确定按钮

15.8 菜单组件

菜单是最常用的 GUI 组件之一。Swing 包中提供了多种菜单组件。

菜单有下拉式菜单和弹出式菜单两种

15.8.1 菜单栏及菜单

JMenuBar 菜单栏是窗口主菜单,用来包容一组菜单

通过容器的 setJMenuBar(JMenuBar m) 方法将菜单栏放到窗口上

菜单栏 JMenuBar 构造方法:

  • new JMenuBar():构建一个新的菜单栏

菜单栏也能注册一些事件侦听程序,但通常情况下对于这些事件我们都不进行处理

菜单构造方法:

  • new JMenu():构造没有文本的新菜单
  • new JMenu(String str):构造有指定标签的菜单
  • new JMenu(String str, boolean b):构造有指定标签的菜单,并指示其是否可以被分离

常用方法:

  • add(JMenu m):菜单可以被加入菜单栏或另一个菜单中

  • addSeparator():为菜单各项间加入间隔线

    insertSeparator(int index):在指定位置插入间隔线

    也能通过这种方式插入间隔线:

    menu.add(new JSeparator());				//JSeparator 类即分割线类

15.8.2 JMenuItem 菜单项

JMenuItem 菜单项是菜单系统的最下一级

构造方法:

  • new JMenuItem():创建不带有设置文本或图标的菜单项

  • new JMenuItem(Icon i):创建只有图标的菜单项

  • new JMenuItem(String str):创建只有文本的菜单项

  • new JMenuItem(String str, Icon i):创建有图标和文本的菜单项

  • new JMenuItem(String str, int mnemonic):创建有文本和快捷键的菜单项

    那个快捷键的有效值是 KeyEvent 包下的各种常量

常用方法:

  • setMnemonic(int m):设置快捷键

  • setAccelerator(KeyStroke keyStroke):设置加速键

  • addActionListener(ActionListener l):加入侦听器

    菜单项被选中时,会触发 ActionEvent 事件

15.8.3 复选菜单项和单选菜单项

JCheckBoxMenuItem(复选菜单项)和 JRadioButtonMenuItem(单选菜单项)是两种特殊的菜单项。

JCheckBoxMenuItem 前有个小方框,以供提示复选

JRadioButtonMenuItem 前有个小圆圈,以供提示单选

复选菜单项构造器:

  • new JCheckBoxMenuItem():一个无文本图标,初始未选中的菜单项
  • new JCheckBoxMenuItem(Icon i):就是有图标咯
  • new JCheckBoxMenuItem(String str):就是有文本咯
  • new JCheckBoxMenuItem(String str, boolean b):就是有文本,又指定初始状态咯
  • new JCheckBoxMenuItem(String str, Icon i):就是有文本,又有图标咯
  • new JCheckBoxMenuItem(String str, Icon i, boolean b):你猜呗

单选菜单项构造器:

单选菜单项是 JRadioButtonMenuItem,剩下的都和上面的一样

15.9 对话框

对话框是一个临时的可移动窗口,其依赖于其他窗口。当期依赖的窗口消失或最小化时,对话框消失。窗口还原时对话框恢复。

对话框分为强制型和非强制型。强制型对话框在关闭前,其他窗口不能接收任何形式的输入。也就是说,该对话过程不能中断。强制型对话框也被称为模式窗口。

15.9.1 JDialog 自定义对话框

构造方法:

  • new JDialog(Dialog owner):无标题无模式对话框。指定对话框为其所有者

    new JDialog(Frame owner):指定框架为其所有者

  • new JDialog(Dialog owner, boolean model):无标题对话框,指定所有者并指示是否为有模式

  • new JDialog(Dialog owner, String title)

    new JDialog(Frame owner, String title)

    new JDialog(Dialog owner, String title, boolean model)

    new JDialog(Frame owner, String title, boolean model):这些你都懂的吧

15.9.2 JOptionalPane 标准对话框

JDialog 通常用于创建自定义对话框。此外,还有用于显示标准对话框的 JOptionalPane 类

JOptionalPane 定义了多个静态方法,分为以下 4 个类型:

  • showConfirmDialog:确认对话框。显示问题,要求用户进行确认(yes / no / cancel)

    其同名方法有以下 3 种

    • int showConfirmDialog(Component parentComponent, Object message)

    • int showConfirmDialog(Component parentComponent, Object message, String title, int optionType)

    • int showConfirmDialog(Component parentComponent, Object message, String title, int optionType, int messageType)

  • showInputDialog:输入对话框。提示用户进行输入

    同名方法有以下 6 种:

    • showInputDialog(Object message)

    • showInputDialog(Object message, Object initialValue)

    • showInputDialog(Component parentComponent, Object message)

    • showInputDialog(Component parentComponent, Object message, Object initialValue)

    • showInputDialog(Component parentComponent, Object message, String title, int messageType)

    • showInputDialog(Component parentComponent, Object message, String title, int messageType, Icon icon, Object[] options, Object initialValue)

  • showMessageDialog:信息对话框。显示信息

    同名方法有以下 3 种:

    • showMessageDialog(Component parentComponent, Object message)

    • showMessageDialog(Component parentComponent, Object message, String title, int messageType)

    • showMessageDialog(Component parentComponent, Object message, String title, int messageType, Icon icon)

  • showOptionDialog:选项对话框,显示选项,要求用户进行选择

    其只有 1 种同名方法

    • showOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue)

以上各个方法的参数分别是:

  • Component parentComponent:对话框的父窗口对象。其父窗口位置决定了对话框位置

    该值可以是 null,表示用默认的 Frame 作为父窗口。这个场合,对话框位置在屏幕正中

  • Object message:显示在对话框的描述信息。

    该参数通常是 String 对象,但也能是一个图标、组件或对象数组

  • String title:对话框标题

  • int optionType:对话框上的按钮类型。可以是以下常量:

    • JOptionalPane.DEFAULT_OPTION:默认(-1)
    • JOptionalPane.YES_NO_OPTION:一组 yes / no(0)
    • JOptionalPane.YES_NO_CANCEL_OPTION:一组 yes / no / cancel(1)
    • JOptionalPane.OK_CANCEL_OPTION:一组 ok / cancel(2)

    此外,也能通过 Object[] options 参数指定其他形式

  • Object[] options:对话框上的选项。

    在输入对话框中,通常以组合框架形式显示。在选项对话框中,则是指按钮类型。

    该参数通常是一个 String[] 数组,但也能是图标数组或组件数组

  • int messageType:对话框传递的信息类型。可以是以下常量:

    • JOptionalPane.ERROR_MESSAGE:错误信息(0)
    • JOptionalPane.INFORMATION_MESSAGE:普通信息(1)
    • JOptionalPane.WARNING_MESSAGE:警告信息(2)
    • JOptionalPane.QUESTION_MESSAGE:提问信息(3)
    • JOptionalPane.PLAIN_MESSAGE:无格式信息(-1)

    除 PLAIN_MESSAGE 外,每种类型对应于一个默认的图标

  • Object initialValue:初始选项或输入值

15.9.3 JFileChooser 文件对话框

JFileChooser 文件对话框是专门用于对文件或目录进行浏览和选择的对话框

构造方法:

  • new JFileChooser():构造一个指向客户默认目录的文件对话框
  • new JFileChooser(File currentDirectory):指向指定目录的文件对话框
  • new JFileChooser(String path):指向指定目录的文件对话框

常用方法:

  • showOpenDialog(Component parent):弹出一个 “打开” 文件对话框

    parent 是对话框的父窗口对象。其父窗口位置决定了对话框位置

    该值可以是 null,表示用默认的 Frame 作为父窗口。这个场合,对话框位置在屏幕正中

    showSaveDialog(Component parent):弹出一个 “保存” 文件对话框

  • getSelectedFile():获得用户选择的文件


<Java>15 图形界面设计
https://i-melody.github.io/2022/04/22/Java/入门阶段/15 图形界面设计/
作者
Melody
发布于
2022年4月22日
许可协议