51、深入探索GUI应用开发:从基础到高级技巧

深入探索GUI应用开发:从基础到高级技巧

1. GUI应用开发常见错误避免

在GUI应用开发过程中,有一些常见错误需要我们特别注意并避免,以下是详细介绍:
1. 导入语句拼写错误 :在导入 javax.swing 包时,不要忘记 java 后面的字母 x ,正确的导入语句应该包含 javax.swing
2. 未指定关闭按钮操作 :默认情况下,点击 JFrame 的关闭按钮只会隐藏窗口,而不会终止应用程序。如果希望点击关闭按钮时退出应用,需要调用 setDefaultCloseOperation 方法,并传入 JFrame.EXIT_ON_CLOSE 作为参数。示例代码如下:

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  1. 遗漏事件监听器 :若应用程序要响应某个事件,必须编写实现相应接口的事件监听器,并将其注册到产生该事件的组件上。
  2. 未注册事件监听器 :即使编写了事件监听器,若未将其注册到正确的组件上,它也不会执行。
  3. 方法头不匹配 :编写接口要求的事件监听器方法时,方法头必须与接口指定的一致。例如, actionPerformed 方法的头必须与 ActionListener 接口指定的一致。
  4. 组件布局问题
    • 当使用 BorderLayout 管理器,且不希望组件被调整大小或想在每个区域添加多个组件时,不要直接将组件放入容器的区域中,应先将组件放入 JPanel ,再将 JPanel 添加到区域。
    • 当使用 GridLayout 管理器,且不希望组件被调整大小或想在每个单元格添加多个组件时,不要直接将组件放入容器的单元格中,应先将组件放入 JPanel ,再将 JPanel 添加到单元格。
  5. 未添加到按钮组 :要使 JRadioButton 组件之间形成互斥关系,必须将它们添加到 ButtonGroup 对象中。示例代码如下:
ButtonGroup group = new ButtonGroup();
JRadioButton radio1 = new JRadioButton("Option 1");
JRadioButton radio2 = new JRadioButton("Option 2");
group.add(radio1);
group.add(radio2);

2. 复习问题与练习

2.1 选择题与判断题

以下是一系列选择题和判断题,涵盖了GUI开发的基础知识:
| 题目 | 选项 | 答案 |
| — | — | — |
| 用Swing创建框架使用哪个类? | a. Frame
b. SwingFrame
c. JFrame
d. JavaFrame | c |
| JFrame 对象中用于容纳添加的组件的部分是? | a. content pane
b. viewing area
c. component array
d. object collection | a |
| AWT类与什么通信,以指示操作系统绘制其内置的用户界面组件? | a. classes
b. interfaces
c. peer classes
d. packages | c |
| 连接事件监听器对象与GUI组件的过程是? | a. Registering the event listener
b. Firing the event listener
c. Decorating the event listener
d. Framing the event listener | a |
| 显示器的分辨率以什么来衡量,即构成屏幕显示的小点? | a. pixels
b. frames
c. windows
d. area | a |
| 实现 ActionListener 接口必须导入哪个包? | a. java.awt.event
b. javax.swing
c. java.util
d. java.math | a |
| BorderLayout 管理器中哪些区域的组件会垂直调整大小以填充整个区域? | a. north and south
b. east and west
c. center only
d. north, south, east, and west | a |
| BorderLayout 管理器中哪些区域的组件会水平和垂直调整大小以填充整个区域? | a. north and south
b. east and west
c. center only
d. north, south, east, and west | c |
| 为 JButton 组件编写动作监听器类时,必须满足什么条件? | a. have a method named buttonClicked
b. implement the ActionLIstener interface
c. have a method named actionPerformed which must take an argument of the ActionEvent type
d. both b and c | d |
| 将单选按钮组件添加到哪种对象可以创建它们之间的互斥关系? | a. MutualExclude
b. RadioGroup
c. LogicalGroup
d. ButtonGroup | d |
| 哪种边框具有3D外观,给人一种沉入周围背景的错觉? | a. etched border
b. lowered bevel border
c. compound border
d. matte border | b |
| 判断题:面板不能单独显示。 | | True |
| 判断题:可以在 GridLayout 单元格中放置多个组件。 | | True |
| 判断题:可以在 BorderLayout 区域中放置多个组件。 | | True |
| 判断题:可以在由 FlowLayout 管理器管理的容器中放置多个组件。 | | True |
| 判断题:可以在由 BorderLayout 管理器管理的区域中放置面板。 | | True |
| 判断题:放置在 GridLayout 管理器单元格中的组件不会调整大小以填充单元格中的额外空间。 | | False |
| 判断题:通常将 JCheckBox 组件添加到 ButtonGroup 对象中。 | | False |
| 判断题:同一容器中的所有 JRadioButton 组件会自动创建互斥关系。 | | False |
| 判断题:与Swing相比,AWT组件非常可定制,因为程序员可以轻松更改它们的属性。 | | False |

2.2 查找错误

以下是一些代码示例,其中存在错误,需要找出并改正:
1. 错误代码

getContentPane().setColor(Bacground.BLUE);

错误原因 Bacground 拼写错误,应为 Color setColor 方法不存在,应为 setBackground
改正后代码

getContentPane().setBackground(Color.BLUE);
  1. 错误代码
private class ButtonListener implements ActionListener
{
   public void actionPerformed()
   {
      // Code appears here.
   }
}

错误原因 actionPerformed 方法缺少 ActionEvent 类型的参数。
改正后代码

private class ButtonListener implements ActionListener
{
   public void actionPerformed(ActionEvent e)
   {
      // Code appears here.
   }
}
  1. 错误代码
panel.setLayout(new GridLayout(10, 5));

错误原因 GridLayout 构造函数参数顺序错误,第一个参数是行数,第二个参数是列数。
改正后代码

panel.setLayout(new GridLayout(5, 10));
  1. 错误代码
panel.add(button, NORTH);

错误原因 NORTH 未定义,应使用 BorderLayout.NORTH
改正后代码

panel.add(button, BorderLayout.NORTH);
  1. 错误代码
panel.setBorder(new BorderFactory("Choices"));

错误原因 BorderFactory 是一个工厂类,不能直接实例化,应使用其静态方法。
改正后代码

panel.setBorder(BorderFactory.createTitledBorder("Choices"));

2.3 算法工作台

以下是一些算法相关的编程问题及示例代码:
1. 创建一个 JFrame 对象,设置窗口大小为110像素宽和200像素高,并显示窗口标题为“My Window”

JFrame frame = new JFrame("My Window");
frame.setSize(110, 200);
frame.setVisible(true);
  1. 使应用程序在用户点击 JFrame 对象的关闭按钮时结束
myWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  1. 显示 JFrame 对象的窗口
myWindow.setVisible(true);
  1. 创建一个显示文本“Submit”的 JButton ,设置背景颜色为绿色,前景颜色为白色
JButton button = new JButton("Submit");
button.setBackground(Color.GREEN);
button.setForeground(Color.WHITE);
  1. 假设一个类继承自 JFrame 类,在类构造函数中为内容窗格设置 FlowLayout 管理器,组件应与每行的左边缘对齐
import javax.swing.*;
import java.awt.*;

public class MyFrame extends JFrame {
    public MyFrame() {
        getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
    }
}
  1. 假设一个类继承自 JFrame 类,在类构造函数中为内容窗格设置 GridLayout 管理器,有五行十列
import javax.swing.*;
import java.awt.*;

public class MyFrame extends JFrame {
    public MyFrame() {
        getContentPane().setLayout(new GridLayout(5, 10));
    }
}
  1. JButton 对象添加到由 BorderLayout 管理器管理的 JPanel 对象的西部区域
panel.add(button, BorderLayout.WEST);
  1. 创建三个单选按钮,文本分别为“Option 1”、“Option 2”和“Option 3”,初始选择显示文本“Option 1”的单选按钮,并确保这些组件分组以形成互斥关系
import javax.swing.*;
import java.awt.*;

public class RadioButtonExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        ButtonGroup group = new ButtonGroup();
        JRadioButton radio1 = new JRadioButton("Option 1");
        JRadioButton radio2 = new JRadioButton("Option 2");
        JRadioButton radio3 = new JRadioButton("Option 3");
        radio1.setSelected(true);
        group.add(radio1);
        group.add(radio2);
        group.add(radio3);
        frame.getContentPane().add(radio1);
        frame.getContentPane().add(radio2);
        frame.getContentPane().add(radio3);
        frame.setLayout(new FlowLayout());
        frame.setSize(300, 200);
        frame.setVisible(true);
    }
}
  1. JPanel 对象创建一个两像素厚的蓝色线条边框
import javax.swing.*;
import java.awt.*;

public class BorderExample {
    public static void main(String[] args) {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));
    }
}

2.4 简答题

  1. 内容窗格和面板的区别是什么?
    内容窗格是 JFrame 的一部分,用于容纳添加到 JFrame 的组件。面板( JPanel )是一个通用的轻量级容器,可以用来组织和管理其他组件,它可以被添加到内容窗格或其他容器中。
  2. 为什么有时需要将组件放在面板中,然后将面板放在由 BorderLayout 管理器管理的容器中?
    当不希望组件被调整大小,或者想在 BorderLayout 的某个区域添加多个组件时,将组件放在面板中,再将面板添加到容器的区域,可以避免组件被自动调整大小,并且可以方便地管理多个组件。
  3. 什么是事件触发?
    事件触发是指当用户与GUI组件进行交互(如点击按钮、选择列表项等)或系统发生某些特定情况时,会产生相应的事件。这些事件会通知注册了相应事件监听器的组件,从而触发事件监听器中的代码执行。
  4. 如何创建一个专门的面板组件,用于容纳其他组件及其相关代码?
    可以创建一个继承自 JPanel 的类,在该类的构造函数中添加所需的组件,并实现相应的事件监听器。以下是一个简单的示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class SpecialPanel extends JPanel {
    public SpecialPanel() {
        JButton button = new JButton("Click me");
        JLabel label = new JLabel("Hello");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                label.setText("Button clicked");
            }
        });
        add(button);
        add(label);
    }
}

2.5 编程挑战

以下是一些编程挑战问题,涵盖了不同的应用场景:
1. 电费计算器 :创建一个GUI应用程序,用户在文本字段中输入一个月消耗的电量和每单位的价格,应用程序有一个“Generate Bill”按钮,点击后显示该月的总电费。
2. 月销售税 :创建一个GUI应用程序,允许用户在文本字段中输入该月的总销售额,应用程序应计算并显示以下内容:
- 县销售税金额
- 州销售税金额
- 总销售税(县税加州税)
- 州销售税税率为4%,县销售税税率为2%,在代码中用常量表示。
3. 财产税 :创建一个GUI应用程序,当用户输入房产的实际价值时,显示评估价值和财产税。县按房产评估价值(实际价值的60%)征收财产税,每100美元的评估价值征收0.64美元的税。
4. 旅行费用 :创建一个GUI应用程序,计算并显示商务人员旅行的总费用。用户需要提供以下信息:
- 旅行天数
- 机票费用(如果有)
- 汽车租赁费用(如果有)
- 私人车辆行驶的英里数(如果使用)
- 停车费用(如果有)
- 出租车费用(如果有)
- 会议或研讨会注册费用(如果有)
- 每晚的住宿费用
- 公司报销政策如下:
- 每天37美元的餐费
- 每天最多10美元的停车费
- 每天最多20美元的出租车费
- 每天最多95美元的住宿费
- 如果使用私人车辆,每英里0.27美元
- 应用程序应计算并显示以下内容:
- 商务人员产生的总费用
- 旅行的总允许费用
- 如果有,商务人员必须支付的超额费用
- 如果费用低于总允许费用,商务人员节省的金额
5. 剧院收入 :创建一个GUI应用程序,允许用户在文本字段中输入以下数据:
- 成人票单价
- 成人票销售数量
- 儿童票单价
- 儿童票销售数量
- 应用程序应计算并显示以下数据:
- 成人票销售的毛收入
- 成人票销售的净收入(扣除支付给电影公司的费用后剩余的金额)
- 儿童票销售的毛收入
- 儿童票销售的净收入(扣除支付给电影公司的费用后剩余的金额)
- 总毛收入
- 总净收入
- 假设剧院保留票房收入的20%,在代码中用常量表示。
6. 乔的汽车维修店 :乔的汽车维修店提供以下常规维护服务:
- 换油 - 26美元
- 润滑工作 - 18美元
- 散热器冲洗 - 30美元
- 变速箱冲洗 - 80美元
- 检查 - 15美元
- 消声器更换 - 100美元
- 轮胎旋转 - 20美元
- 乔还提供其他非常规服务,并收取零件和工时费(每小时20美元)。创建一个GUI应用程序,显示客户到店的总费用。
7. 长途电话费用 :长途电话提供商按以下费率收费:
| 费率类别 | 每分钟费率 |
| — | — |
| 白天(上午6:00到下午5:59) | 0.07美元 |
| 晚上(下午6:00到晚上11:59) | 0.12美元 |
| 非高峰时段(凌晨12:00到上午5:59) | 0.05美元 |
创建一个GUI应用程序,允许用户从一组单选按钮中选择费率类别,并在文本字段中输入通话分钟数,对话框应显示通话费用。
8. 拉丁语翻译器 :创建一个GUI应用程序,将拉丁语单词翻译成英语。窗口应有三个按钮,分别对应以下拉丁语单词及其英语含义:
| 拉丁语 | 英语 |
| — | — |
| sinister | 左 |
| dexter | 右 |
| medium | 中心 |
当用户点击按钮时,程序在标签中显示英语翻译。
9. MPG计算器 :创建一个GUI应用程序,计算汽车的每加仑英里数(MPG)。应用程序应允许用户输入汽车的汽油容量和满箱油可行驶的英里数,点击“Calculate MPG”按钮后,应用程序显示汽车每加仑汽油可行驶的英里数,使用以下公式计算MPG:
[ MPG = \frac{Miles}{Gallons} ]
10. 摄氏度到华氏度转换 :创建一个GUI应用程序,将摄氏度温度转换为华氏度温度。用户可以输入摄氏度温度,点击按钮后,显示等效的华氏度温度,使用以下公式进行转换:
[ F = \frac{9}{5}C + 32 ]
其中,$F$是华氏度温度,$C$是摄氏度温度。

3. 高级GUI应用

3.1 Swing和AWT类层次结构

在使用了一些基本的GUI组件后,我们来了解它们在类层次结构中的位置。部分Swing和AWT类层次结构包含 JFrame JPanel JLabel JTextField JButton JRadioButton JCheckBox 等类。未着色的顶部部分是AWT类,位于 java.awt 包中;着色的底部部分是Swing类,位于 javax.swing 包中。所有这些组件最终都继承自 Component 类。

3.2 只读文本字段

只读文本字段是一种特殊的文本字段,它显示的文本可以通过应用程序中的代码更改,但用户不能编辑。这不是一个新的组件,而是 JTextField 组件的一种不同用法。 JTextField 组件有一个 setEditable 方法,其一般格式如下:

setEditable(boolean editable)

默认情况下,文本字段是可编辑的,即用户可以输入数据。如果调用 setEditable 方法并传入 false 作为参数,文本字段就会变为只读。以下是创建只读文本字段的示例代码:

// Create a read-only text field for the subtotal.
JTextField subtotalField = new JTextField(10);
subtotalField.setEditable(false);
// Create a read-only text field for the sales tax.
JTextField taxField = new JTextField(10);
taxField.setEditable(false);
// Create a read-only text field for the total.
JTextField totalField = new JTextField(10);
totalField.setEditable(false);

可以使用 setText 方法在只读文本字段中显示数据:

subtotalField.setText("100.00");
taxField.setText("6.00");
totalField.setText("106.00");

3.3 列表

3.3.1 列表组件概述

列表组件用于显示一组项目,并允许用户从列表中选择一个或多个项目。Java提供了 JList 组件来创建列表。创建 JList 实例时,需要将一个对象数组传递给构造函数,一般格式如下:

JList (Object[] array)

通常我们将 String 对象数组传递给 JList 构造函数。以下是创建列表组件的示例代码:

String[] names = { "Bill", "Geri", "Greg", "Jean",
                   "Kirk", "Phillip", "Susan" };
JList nameList = new JList(names);
3.3.2 选择模式

JList 组件有以下三种选择模式:
1. 单选择模式 :一次只能选择一个项目。当选择一个项目时,当前已选择的其他项目会被取消选择。可以使用 ListSelectionModel.SINGLE_SELECTION 常量将 JList 组件设置为单选择模式,示例代码如下:

nameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  1. 单区间选择模式 :可以选择多个项目,但这些项目必须是连续的。用户通过点击区间的第一个项目,然后按住 Shift 键并点击区间的最后一个项目来选择一个区间。可以使用 ListSelectionModel.SINGLE_INTERVAL_SELECTION 常量将 JList 组件设置为单区间选择模式。
  2. 多区间选择模式 :可以选择多个项目,没有任何限制,这是默认的选择模式。可以使用 ListSelectionModel.MULTIPLE_INTERVAL_SELECTION 常量将 JList 组件设置为多区间选择模式。
3.3.3 响应列表事件

JList 对象中的项目被选择时,会生成一个列表选择事件。要处理列表选择事件,需要创建一个实现 ListSelectionListener 接口的列表选择监听器类,该类必须有一个名为 valueChanged 的方法,该方法接受一个 ListSelectionEvent 类型的参数。以下是一个示例:

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;

public class ListWindow extends JFrame {
    private JList monthList;
    private JTextField selectedMonth;

    private String[] months = { "January", "February",
            "March", "April", "May", "June", "July",
            "August", "September", "October", "November",
            "December" };

    public ListWindow() {
        // 省略部分代码
        monthList = new JList(months);
        monthList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        monthList.addListSelectionListener(new ListListener());
        // 省略部分代码
    }

    private class ListListener implements ListSelectionListener {
        public void valueChanged(ListSelectionEvent e) {
            String selection = (String) monthList.getSelectedValue();
            selectedMonth.setText(selection);
        }
    }

    public static void main(String[] args) {
        new ListWindow();
    }
}
3.3.4 检索所选项目

可以使用 getSelectedValue 方法或 getSelectedIndex 方法来确定列表中当前选择的项目。 getSelectedValue 方法返回当前选择项目的引用,如果没有选择项目,则返回 null getSelectedIndex 方法返回所选项目的索引,如果没有选择项目,则返回 -1。以下是示例代码:

int index;
String selectedName;
index = nameList.getSelectedIndex();
if (index != -1) {
    selectedName = names[index];
}
3.3.5 为列表添加边框

可以使用 setBorder 方法为 JList 组件添加边框。以下是为 monthList 组件添加黑色1像素粗线条边框的示例代码:

monthList.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
3.3.6 为列表添加滚动条

默认情况下,列表组件会显示其包含的所有项目。当列表中的项目太多无法一次显示时,通常需要为列表组件添加滚动条。步骤如下:
1. 设置列表组件的可见行数。
2. 创建一个滚动面板对象,并将列表组件添加到其中。
3. 将滚动面板对象添加到其他容器(如面板)中。

以下是为列表组件添加滚动条的示例代码:

String[] names = { "Bill", "Geri", "Greg", "Jean",
                   "Kirk", "Phillip", "Susan" };
JList nameList = new JList(names);
nameList.setVisibleRowCount(3);
JScrollPane scrollPane = new JScrollPane(nameList);
JPanel panel = new JPanel();
panel.add(scrollPane);
3.3.7 向现有JList组件添加项目

JList 类的 setListData 方法允许在现有 JList 组件中存储项目。其一般格式如下:

void setListData(Object[] data)

传递给 data 的参数是一个对象数组,这些对象将成为 JList 组件中显示的项目,组件中当前显示的任何项目都会被新的项目替换。也可以使用此方法向空列表添加项目,先创建一个空列表,然后调用 setListData 方法添加项目。示例代码如下:

JList nameList = new JList();
String[] names = { "Bill", "Geri", "Greg", "Jean",
                   "Kirk", "Phillip", "Susan" };
nameList.setListData(names);
3.3.8 多选择列表

前面的示例使用了单选择模式的 JList 组件,另外两种选择模式(单区间和多区间)允许用户选择多个项目。
- 单区间选择模式 :将 JList 组件设置为单区间选择模式,可使用 ListSelectionModel.SINGLE_INTERVAL_SELECTION 常量。在单区间选择模式下,用户可以选择单个或多个连续的项目。要选择一个区间的项目,用户先点击区间的第一个项目,然后按住 Shift 键并点击区间的最后一个项目。在单区间选择模式下, getSelectedValue 方法返回所选区间的第一个项目, getSelectedIndex 方法返回所选区间第一个项目的索引, getSelectedValues 方法返回包含所选区间所有项目的数组, getSelectedIndices 方法返回包含所选项目所有索引的整数数组。
- 多区间选择模式 :将 JList 组件设置为多区间选择模式,可使用 ListSelectionModel.MULTIPLE_INTERVAL_SELECTION 常量。在多区间选择模式下,用户可以选择单个项目或多个不连续的项目。用户按住 Ctrl 键并点击项目,可以选择项目而不取消当前已选择的项目。在多区间选择模式下, getSelectedValue 方法返回第一个选择的项目, getSelectedIndex 方法返回第一个选择项目的索引, getSelectedValues 方法返回包含所选项目的数组, getSelectedIndices 方法返回包含所有所选项目索引的整数数组。

以下是一个使用多区间选择模式的示例代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class MultipleIntervalSelection extends JFrame {
    private JList monthList;
    private JList selectedMonthList;
    private JButton button;

    private String[] months = { "January", "February",
            "March", "April", "May", "June", "July",
            "August", "September", "October", "November",
            "December" };

    public MultipleIntervalSelection() {
        // 省略部分代码
        monthList = new JList(months);
        monthList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        monthList.setVisibleRowCount(6);
        JScrollPane scrollPane1 = new JScrollPane(monthList);
        // 省略部分代码
        button = new JButton("Get Selections");
        button.addActionListener(new ButtonListener());
        // 省略部分代码
    }

    private class ButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            Object[] selections = monthList.getSelectedValues();
            selectedMonthList.setListData(selections);
        }
    }

    public static void main(String[] args) {
        new MultipleIntervalSelection();
    }
}

3.4 组合框

3.4.1 组合框概述

组合框( JComboBox )是一种允许用户从预定义的选项列表中选择一个项目的组件,它结合了文本框和下拉列表的功能。用户既可以直接在文本框中输入内容,也可以点击下拉箭头从列表中选择项目。以下是创建一个简单组合框的示例代码:

import javax.swing.*;
import java.awt.*;

public class ComboBoxExample extends JFrame {
    public ComboBoxExample() {
        String[] options = { "Option 1", "Option 2", "Option 3" };
        JComboBox<String> comboBox = new JComboBox<>(options);
        add(comboBox);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new ComboBoxExample();
    }
}
3.4.2 响应组合框事件

当用户选择组合框中的项目时,会触发一个动作事件。可以通过实现 ActionListener 接口来处理这个事件。以下是一个示例:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ComboBoxEventExample extends JFrame {
    private JComboBox<String> comboBox;
    private JLabel label;

    public ComboBoxEventExample() {
        String[] options = { "Option 1", "Option 2", "Option 3" };
        comboBox = new JComboBox<>(options);
        label = new JLabel("Selected: ");
        comboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String selected = (String) comboBox.getSelectedItem();
                label.setText("Selected: " + selected);
            }
        });
        add(comboBox);
        add(label);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new ComboBoxEventExample();
    }
}

3.5 在标签和按钮中显示图像

3.5.1 显示图像的基本步骤

在GUI应用中,可以在标签( JLabel )和按钮( JButton )中显示图像。基本步骤如下:
1. 创建 ImageIcon 对象,指定图像文件的路径。
2. 将 ImageIcon 对象设置给 JLabel JButton

以下是在标签中显示图像的示例代码:

import javax.swing.*;
import java.awt.*;

public class ImageLabelExample extends JFrame {
    public ImageLabelExample() {
        ImageIcon icon = new ImageIcon("path/to/your/image.jpg");
        JLabel label = new JLabel(icon);
        add(label);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new ImageLabelExample();
    }
}
3.5.2 在按钮中显示图像

在按钮中显示图像的方法类似,只需将 ImageIcon 对象设置给 JButton 。以下是示例代码:

import javax.swing.*;
import java.awt.*;

public class ImageButtonExample extends JFrame {
    public ImageButtonExample() {
        ImageIcon icon = new ImageIcon("path/to/your/image.jpg");
        JButton button = new JButton(icon);
        add(button);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new ImageButtonExample();
    }
}

3.6 助记符和工具提示

3.6.1 助记符

助记符是一种通过键盘快捷键来激活组件的方式。在 JButton JMenuItem 等组件中可以设置助记符。设置助记符后,用户可以通过按下 Alt 键和助记符对应的字母来激活组件。以下是为按钮设置助记符的示例代码:

import javax.swing.*;
import java.awt.*;

public class MnemonicExample extends JFrame {
    public MnemonicExample() {
        JButton button = new JButton("Click me");
        button.setMnemonic('C');
        add(button);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new MnemonicExample();
    }
}
3.6.2 工具提示

工具提示是当鼠标悬停在组件上时显示的简短说明信息。可以使用 setToolTipText 方法为组件设置工具提示。以下是为按钮设置工具提示的示例代码:

import javax.swing.*;
import java.awt.*;

public class ToolTipExample extends JFrame {
    public ToolTipExample() {
        JButton button = new JButton("Click me");
        button.setToolTipText("This is a button");
        add(button);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new ToolTipExample();
    }
}

3.7 文件选择器和颜色选择器

3.7.1 文件选择器

文件选择器( JFileChooser )允许用户选择文件或目录。以下是一个简单的文件选择器示例代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class FileChooserExample extends JFrame {
    private JButton button;

    public FileChooserExample() {
        button = new JButton("Select File");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser();
                int result = fileChooser.showOpenDialog(FileChooserExample.this);
                if (result == JFileChooser.APPROVE_OPTION) {
                    java.io.File selectedFile = fileChooser.getSelectedFile();
                    JOptionPane.showMessageDialog(FileChooserExample.this, "Selected file: " + selectedFile.getAbsolutePath());
                }
            }
        });
        add(button);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new FileChooserExample();
    }
}
3.7.2 颜色选择器

颜色选择器( JColorChooser )允许用户选择颜色。以下是一个简单的颜色选择器示例代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ColorChooserExample extends JFrame {
    private JButton button;
    private JPanel panel;

    public ColorChooserExample() {
        button = new JButton("Select Color");
        panel = new JPanel();
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Color selectedColor = JColorChooser.showDialog(ColorChooserExample.this, "Select Color", Color.WHITE);
                if (selectedColor != null) {
                    panel.setBackground(selectedColor);
                }
            }
        });
        add(button);
        add(panel);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new ColorChooserExample();
    }
}

3.8 菜单

3.8.1 创建菜单的基本步骤

在GUI应用中,菜单是一种常见的用户界面元素。创建菜单的基本步骤如下:
1. 创建 JMenuBar 对象,作为菜单栏。
2. 创建 JMenu 对象,作为菜单。
3. 创建 JMenuItem 对象,作为菜单项。
4. 将菜单项添加到菜单中,将菜单添加到菜单栏中,最后将菜单栏设置给 JFrame

以下是一个简单的菜单示例代码:

import javax.swing.*;
import java.awt.*;

public class MenuExample extends JFrame {
    public MenuExample() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem openItem = new JMenuItem("Open");
        JMenuItem saveItem = new JMenuItem("Save");
        fileMenu.add(openItem);
        fileMenu.add(saveItem);
        menuBar.add(fileMenu);
        setJMenuBar(menuBar);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new MenuExample();
    }
}
3.8.2 响应菜单项事件

可以通过实现 ActionListener 接口来处理菜单项的点击事件。以下是一个示例:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MenuEventExample extends JFrame {
    private JMenuItem openItem;
    private JMenuItem saveItem;

    public MenuEventExample() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        openItem = new JMenuItem("Open");
        saveItem = new JMenuItem("Save");
        openItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(MenuEventExample.this, "Open selected");
            }
        });
        saveItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(MenuEventExample.this, "Save selected");
            }
        });
        fileMenu.add(openItem);
        fileMenu.add(saveItem);
        menuBar.add(fileMenu);
        setJMenuBar(menuBar);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new MenuEventExample();
    }
}

3.9 更多关于文本组件:文本区域和字体

3.9.1 文本区域

文本区域( JTextArea )用于显示和编辑多行文本。以下是一个简单的文本区域示例代码:

import javax.swing.*;
import java.awt.*;

public class TextAreaExample extends JFrame {
    public TextAreaExample() {
        JTextArea textArea = new JTextArea(10, 20);
        add(textArea);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new TextAreaExample();
    }
}
3.9.2 设置字体

可以使用 setFont 方法为文本组件设置字体。以下是为文本区域设置字体的示例代码:

import javax.swing.*;
import java.awt.*;

public class FontExample extends JFrame {
    public FontExample() {
        JTextArea textArea = new JTextArea(10, 20);
        Font font = new Font("Arial", Font.BOLD, 16);
        textArea.setFont(font);
        add(textArea);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new FontExample();
    }
}

3.10 滑块

3.10.1 滑块概述

滑块( JSlider )是一种允许用户通过拖动滑块来选择一个值的组件。以下是一个简单的滑块示例代码:

import javax.swing.*;
import java.awt.*;

public class SliderExample extends JFrame {
    public SliderExample() {
        JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 50);
        add(slider);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new SliderExample();
    }
}
3.10.2 响应滑块事件

当滑块的值发生变化时,会触发一个变化事件。可以通过实现 ChangeListener 接口来处理这个事件。以下是一个示例:

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;

public class SliderEventExample extends JFrame {
    private JSlider slider;
    private JLabel label;

    public SliderEventExample() {
        slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 50);
        label = new JLabel("Value: " + slider.getValue());
        slider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                int value = slider.getValue();
                label.setText("Value: " + value);
            }
        });
        add(slider);
        add(label);
        setLayout(new FlowLayout());
        setSize(300, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new SliderEventExample();
    }
}

3.11 外观和感觉

3.11.1 设置外观和感觉

Java提供了多种外观和感觉(Look and Feel),可以通过 UIManager 类来设置应用程序的外观和感觉。以下是一个设置为系统默认外观和感觉的示例代码:

import javax.swing.*;

public class LookAndFeelExample {
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Look and Feel Example");
                JButton button = new JButton("Click me");
                frame.add(button);
                frame.setLayout(new FlowLayout());
                frame.setSize(300, 200);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}

3.12 高级GUI应用开发总结

在高级GUI应用开发中,我们学习了许多强大的组件和功能,包括只读文本字段、列表、组合框、图像显示、助记符和工具提示、文件和颜色选择器、菜单、文本区域和字体、滑块以及外观和感觉的设置。这些组件和功能可以帮助我们创建更加丰富、交互性更强的GUI应用程序。

以下是对这些高级组件和功能的总结表格:
| 组件/功能 | 描述 | 关键方法 |
| — | — | — |
| 只读文本字段 | 显示文本但用户不能编辑 | setEditable(false) |
| 列表 | 显示项目列表并允许选择 | setSelectionMode addListSelectionListener |
| 组合框 | 允许用户从预定义选项中选择 | addActionListener |
| 图像显示 | 在标签和按钮中显示图像 | ImageIcon setIcon |
| 助记符和工具提示 | 提供键盘快捷键和鼠标悬停提示 | setMnemonic setToolTipText |
| 文件和颜色选择器 | 允许用户选择文件和颜色 | JFileChooser JColorChooser |
| 菜单 | 提供常见的用户界面导航 | JMenuBar JMenu JMenuItem |
| 文本区域和字体 | 显示和编辑多行文本并设置字体 | JTextArea setFont |
| 滑块 | 允许用户通过拖动选择值 | addChangeListener |
| 外观和感觉 | 设置应用程序的外观 | UIManager.setLookAndFeel |

通过合理运用这些组件和功能,结合之前学习的基础知识,我们可以开发出高质量、用户体验良好的GUI应用程序。在实际开发中,还需要不断实践和探索,以充分发挥这些组件和功能的潜力。

mermaid格式流程图展示创建一个简单GUI应用的基本流程:

graph TD;
    A[开始] --> B[创建JFrame对象];
    B --> C[设置JFrame属性];
    C --> D[创建组件];
    D --> E[设置组件属性];
    E --> F[将组件添加到JFrame];
    F --> G[设置JFrame布局];
    G --> H[显示JFrame];
    H --> I[结束];

总之,GUI应用开发是一个充满挑战和乐趣的领域,不断学习和实践将使我们能够创建出更加出色的应用程序。希望本文介绍的知识和技巧能对大家的GUI应用开发之旅有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值