高级 GUI 应用程序开发全解析
1. 更改 GUI 外观与感觉
在 Java 中,我们可以通过代码来更改 GUI 应用程序的外观和感觉。以下是将外观和感觉更改为 Motif 风格的代码示例:
try
{
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.motif.MotifLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null, "Error setting " +
"the look and feel.");
System.exit(0);
}
若要将外观和感觉更改为 Windows 风格,代码如下:
try
{
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null, "Error setting " +
"the look and feel.");
System.exit(0);
}
操作步骤:
1. 使用 UIManager.setLookAndFeel 方法设置所需的外观和感觉类名。
2. 调用 SwingUtilities.updateComponentTreeUI 方法更新组件树的 UI。
3. 捕获可能出现的异常,并在出现错误时显示消息框并退出程序。
2. 常见错误避免
在开发 GUI 应用程序时,有许多常见错误需要避免,以下是详细介绍:
- 列表组件多选问题 :当列表组件中选择了多个项目时, getSelectedValue 方法仅返回第一个选中的项目, getSelectedIndex 方法仅返回第一个选中项目的索引。应使用 getSelectedValues 或 getSelectedIndices 方法。
- 索引起始问题 :列表或组合框的索引从 0 开始,而不是 1。
- 滚动面板问题 : JList 和 JTextArea 组件不会自动显示滚动条,必须将这些组件添加到滚动面板对象中才能显示滚动条。并且要使用 JScrollPane 构造函数添加组件,而不是 add 方法。如果将组件添加到滚动面板后,要将其添加到另一个容器(如面板),应添加滚动面板而不是组件,否则滚动条不会显示。
- 组合框可编辑问题 :默认情况下,组合框是按钮和列表的组合。要使其成为文本字段和列表的组合,必须调用 setEditable 方法并传入 true 作为参数。
- 图像文件类型问题 :目前, ImageIcon 对象可以打开 JPEG、GIF 或 PNG 格式的图像文件。
- JLabel 图像加载问题 :如果没有显式设置 JLabel 组件的首选大小,当加载图像时它会自动调整大小,但包含该 JLabel 的 JFrame 不会自动调整大小,必须调用 JFrame 对象的 pack 方法或 setPreferredSize 方法来调整大小。
- 助记符问题 :如果为窗口中的多个组件分配相同的助记符,它仅对第一个分配的组件有效。
- 菜单组件添加问题 :创建菜单项后,必须将其添加到 JMenu 组件中才能在菜单上显示; JMenu 组件必须添加到 JMenuBar 组件中才能在菜单栏上显示。并且要调用 JFrame 对象的 setJMenuBar 方法来放置菜单栏。
- 单选按钮菜单项分组问题 :与常规单选按钮组件一样,必须将单选按钮菜单项分组在一个按钮组中,以创建它们之间的互斥关系。
3. 复习问题与练习
3.1 选择题与判断题
| 题目 | 选项 | 答案 |
|---|---|---|
| 可以使用此方法使文本字段只读。 | a. setReadOnly b. setChangeable c. setUneditable d. setEditable | d |
ListSelectionModel 类提供的以下哪些常量用作 setSelectionMode 方法的参数? | a. ListSelectionModel.SINGLE_SELECTION b. ListSelectionModel.SINGLE_INTERVAL_SELECTION c. ListSelectionModel.MULTIPLE_INTERVAL_SELECTION d. all of the above | d |
要为 JList 组件显示滚动条,必须 _ ___。 | a. 不做任何操作;如果需要, JList 会自动显示滚动条 b. 将 JList 组件添加到 JScrollPane 组件中 c. 调用 setScrollBar 方法 d. 以上都不是;不能为 JList 组件显示滚动条 | b |
这是 JList 组件的默认选择模式。 | a. 单选 b. 单间隔选择 c. 多选 d. 多间隔选择 | d |
| 在 Java 中, _ ____ 类创建滚动面板对象。 | a. JScrollPane b. JPanel c. JCombobox d. Jframe | a |
ListSelectionListener 接口在这个包中。 | a. java.awt b. java.awt.event c. javax.swing.event d. javax.event | c |
如果列表中没有选择任何项目,此 JList 方法返回 -1。 | a. getSelectedValue b. getSelectedItem c. getSelectedIndex d. getSelection | c |
| 这种 _ ____ 组合框将按钮与列表组合在一起,只允许用户从其列表中选择项目。 | a. 不可编辑 b. 可编辑 c. JCombobox d. list | a |
如果要在标签中显示图像,可以将此类的实例传递给 JLabel 构造函数。 | a. ImageFile b. ImageIcon c. JLabelImage d. JImageFile | b |
| 用于向组件添加工具提示。 | a. the setToolTipText method b. the addToolTipText method c. the toolTipText method d. the appendToolTipText method | a |
| 当用户将鼠标光标悬停在组件上时,会在一个小框中显示的文本。 | a. 助记符 b. 即时消息 c. 工具提示 d. 弹出助记符 | c |
| 这是一个键,就像用户用鼠标单击一样激活组件。 | a. 助记符 b. 键激活器 c. 工具提示 d. 点击模拟器 | a |
| 要显示打开文件或保存文件对话框,使用此类。 | a. JFileChooser b. JOpenSaveDialog c. JFileDialog d. JFileOptionPane | a |
| 要显示允许用户选择颜色的对话框,使用此类。 | a. JColor b. JColorDialog c. JColorChooser d. JColorOptionPane | c |
此方法强制 JFrame 自动调整大小。 | a. pack b. setIcon c. setText d. setIntervals | a |
| 使用此类创建单选按钮菜单项。 | a. JMenuItem b. JRadioButton c. JRadioButtonItem d. JRadioButtonMenuItem | d |
setMnemonic 方法(为组件分配助记符)继承自 _ ______ 类。 | a. AbstractButton b. ImageIcon c. JPanel d. JLabel | a |
setPreferredSize 方法接受此作为其参数。 | a. 一个 Size 对象 b. 两个 int 值 c. 一个 Dimension 对象 d. 一个 int 值 | c |
| 此类的组件是多行文本字段。 | a. JMultiLineTextField b. JTextArea c. JTextField d. JEditField | b |
| 这是用于在菜单中分隔项目组的水平条。它是用户无法选择的视觉辅助工具。 | a. 分隔条 b. 子菜单 c. 菜单栏 d. 复选框菜单项 | a |
此方法设置 JSlider 组件上显示主要刻度标记的间隔。 | a. setMajorTickSpacing b. setMajorTickIntervals c. setTickSpacing d. setIntervals | a |
| 判断题:列表或组合框的索引必须从 1 开始。 | True/False | False |
判断题: JList 组件会自动显示围绕它绘制的线条边框。 | True/False | False |
判断题:在单间隔选择模式下,用户可以从 JList 组件中选择多个项目。 | True/False | True |
| 判断题:使用可编辑组合框,用户只能输入出现在组件列表中的值。 | True/False | False |
判断题:可以在 JLabel 对象中存储文本或图像,但不能同时存储两者。 | True/False | False |
判断题:可以在 JLabel 组件中存储大图像和小图像。 | True/False | True |
| 判断题:助记符对擅长使用键盘的用户很有用。 | True/False | True |
判断题: JMenuBar 对象充当 JMenu 组件的容器。 | True/False | True |
判断题: JMenu 对象不能包含其他 JMenu 对象。 | True/False | False |
判断题: JTextArea 组件不会自动显示滚动条。 | True/False | True |
判断题:默认情况下, JTextArea 组件不执行换行。 | True/False | True |
判断题:当滑块旋钮移动时, JSlider 组件会生成动作事件。 | True/False | True |
判断题:默认情况下, JSlider 组件显示标签和刻度标记。 | True/False | False |
判断题:当在 JSlider 组件上显示标签时,它们显示在主要刻度标记上。 | True/False | True |
3.2 查找错误
以下是一些代码示例及其错误分析:
// Create an editable combo box
String[] names = { "Bill", "Geri", "Greg", "Jean",
"Kirk", "Phillip", "Susan" };
JComboBox nameBox = new JComboBox(names);
nameBox.setEditable(false);
错误:要创建可编辑组合框,应将 setEditable 方法的参数设置为 true ,而不是 false 。
// Create a black 1-pixel border around list, a JList component.
list.setBorder(Color.BLACK, 1);
错误: setBorder 方法的使用不正确,应使用 BorderFactory 来创建边框。
// Create a JList and add it to a scroll pane.
// Assume that array already exists.
JList list = new JList(array);
JScrollPane scrollPane = new JScrollPane();
scrollPane.add(list);
错误:应使用 JScrollPane 构造函数添加组件,而不是 add 方法。
// Assume that nameBox is a combo box and is properly set up
// with a list of names to choose from.
// Get value of the selected item.
String selectedName = nameBox.getSelectedIndex();
错误: getSelectedIndex 方法返回的是索引,而不是选中项目的值,应使用 getSelectedItem 方法。
JLabel label = new JLabel("Have a nice day!");
label.setImage(image);
错误: JLabel 没有 setImage 方法,应使用 setIcon 方法。
// Add a menu to the menu bar.
JMenuBar menuBar = new JMenuBar(menuItem);
错误: JMenuBar 构造函数不接受 menuItem 作为参数,应先创建 JMenuBar 对象,再添加 JMenu 组件。
// Create a text area with 20 columns and 5 rows.
JTextArea textArea = new JTextArea (20, 5);
此代码没有错误。
3.3 算法工作台
以下是一些算法问题及对应的代码示例:
1. 更改内容面板背景颜色为绿色
getContentPane().setBackground(Color.GREEN);
- 创建包含周一到周日的列表
String[] days = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
JList dayList = new JList(days);
- 为上述列表添加滚动条
JScrollPane scrollPane = new JScrollPane(dayList);
- 将
JList组件中选中的项目赋值给selection变量
String selection = (String) myList.getSelectedValue();
- 将不可编辑组合框中选中项目的索引赋值给
selectionIndex变量
int selectionIndex = myComboBox.getSelectedIndex();
- 创建一个单选按钮并分配助记符
JRadioButton radioButton = new JRadioButton("Option");
radioButton.setMnemonic(KeyEvent.VK_O);
- 将
picture.gif文件中的图像存储在JLabel中
ImageIcon image = new ImageIcon("picture.gif");
label.setIcon(image);
- 创建一个带有 “Open File” 文本的按钮,分配
O键作为助记符,并分配 “This button opens a file” 作为组件的工具提示
JButton button = new JButton("Open File");
button.setMnemonic(KeyEvent.VK_O);
button.setToolTipText("This button opens a file");
- 使滚动面板的组件显示垂直滚动条,但确保不显示水平滚动条
JScrollPane scrollPane = new JScrollPane(component, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- 创建一个显示 10 行 15 列的文本区域,必要时能够显示滚动条,并执行单词样式的换行
JTextArea textArea = new JTextArea(10, 15);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(textArea);
- 创建一个带有一个名为 “File” 的菜单的菜单栏,为 “File” 菜单分配
F键作为助记符,该菜单有三个菜单项:“Open”、“Print” 和 “Exit”,为每个菜单项分配助记符,并为每个菜单项注册动作监听器
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
JMenuItem openItem = new JMenuItem("Open");
openItem.setMnemonic(KeyEvent.VK_O);
openItem.addActionListener(new OpenListener());
JMenuItem printItem = new JMenuItem("Print");
printItem.setMnemonic(KeyEvent.VK_P);
printItem.addActionListener(new PrintListener());
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.setMnemonic(KeyEvent.VK_E);
exitItem.addActionListener(new ExitListener());
fileMenu.add(openItem);
fileMenu.add(printItem);
fileMenu.add(exitItem);
menuBar.add(fileMenu);
frame.setJMenuBar(menuBar);
- 创建一个水平方向的
JSlider组件,范围从 0 到 1000,显示标签和刻度标记,主要刻度标记每 100 个数字出现一次,次要刻度标记每 25 个数字出现一次,滑块的初始值设置为 500
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 1000, 500);
slider.setMajorTickSpacing(100);
slider.setMinorTickSpacing(25);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
4. 简答题
-
JList的单选择模式和单间隔选择模式有什么区别?
单选择模式下,用户只能选择一个项目;单间隔选择模式下,用户可以选择一个连续的项目区间。 -
如果要提供 20 个项目供用户选择,哪个组件占用空间更少,
JList还是JComboBox?
JComboBox占用空间更少,因为它在未展开时只显示一个按钮和当前选中的项目。 -
子菜单和菜单有什么区别?
菜单是主菜单栏上的选项组,子菜单是菜单中的下拉选项组。 -
描述如何在
JLabel组件中同时存储图像和文本?
可以使用JLabel的构造函数或setIcon和setText方法来同时设置图像和文本。 -
当为多个组件分配相同的助记符时会发生什么?
助记符仅对第一个分配的组件有效。 -
当为组件分配的助记符是组件文本中出现的字母时会发生什么?
该字母会被下划线标记,用户可以通过按下该字母和 Alt 键来激活组件。 -
什么是工具提示?它的目的是什么?
工具提示是当用户将鼠标光标悬停在组件上时显示的文本,用于提供关于组件的额外信息。 -
如何使一组单选按钮菜单项一次只能选择一个?
将它们分组在一个ButtonGroup对象中。 -
当选中的菜单项旁边显示复选标记时,用户点击它会发生什么?
复选标记会消失,表示该菜单项未被选中。 -
如果使用
getSelectedValue方法从列表组件中选择多个项目会发生什么?
该方法仅返回第一个选中的项目。 -
为什么当希望用户输入一个数字,但要确保该数字在某个范围内时,
JSlider组件是理想的选择?
JSlider组件可以直观地显示范围,用户可以通过拖动滑块来选择范围内的数字。 -
Java 中可用的标准 GUI 外观和感觉有哪些?
Motif、Windows 等。
5. 编程挑战
以下是一些编程挑战的描述:
1. 体积转换 :创建一个应用程序,允许用户输入升的体积,然后显示转换为加仑的值。使用滑块在 0 升到 100 升之间调整升的体积。
2. 图像查看器 :编写一个应用程序,允许用户查看图像文件。应用程序应使用按钮或菜单项显示文件选择器。当用户选择图像文件时,应加载并显示该文件。
3. 宿舍和膳食计划计算器 :大学有不同的宿舍和膳食计划,创建一个应用程序,让用户选择宿舍和膳食计划,显示学期的总费用。
4. 滑板设计师 :创建一个应用程序,允许用户从列表组件或组合框中选择一个滑板甲板、一个卡车组件和一组轮子,还可以选择多个杂项产品。应用程序应显示小计、销售税(6%)和订单总额。
5. 购物车系统 :创建一个类似书店购物车系统的应用程序,从文件中读取书籍信息,用户可以选择书籍添加到购物车,结算时显示小计、销售税和总额。
6. 手机套餐 :编写一个应用程序,显示菜单系统,用户可以选择一个套餐、一部手机和所需的选项,应用程序应显示所选项目的价格。
7. 遮阳帘设计师 :创建一个应用程序,允许用户从列表或组合框中选择遮阳帘的样式、尺寸、颜色和数量,显示总费用。
8. 会议注册系统 :计算会议注册费用,用户可以选择注册类型、可选的开幕晚宴和主题演讲,以及多个会前研讨会,显示总费用。
9. 骰子模拟器 :编写一个 GUI 应用程序,模拟一对骰子,每次点击按钮时,应用程序应掷骰子,使用随机数确定每个骰子的值。
10. 纸牌发牌器 :编写一个 GUI 应用程序,随机从一副扑克牌中选择一张牌并显示,每次选择后将牌从牌堆中移除,当牌堆中没有牌时显示消息。
11. 井字棋模拟器 :创建一个 GUI 应用程序,模拟井字棋游戏,使用二维数组模拟游戏板,显示游戏结果。
高级 GUI 应用程序开发全解析
6. 编程挑战详细分析
6.1 体积转换
- 功能概述 :该应用程序允许用户输入升的体积,然后将其转换为加仑并显示结果。使用滑块在 0 升到 100 升之间调整升的体积。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加一个
JSlider用于调整升的体积,设置其范围为 0 到 100。 - 添加一个
JLabel用于显示升的体积和转换后的加仑值。 - 为
JSlider添加监听器,当滑块值改变时,将升转换为加仑并更新JLabel的显示内容。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class VolumeConverter extends JFrame {
private JSlider slider;
private JLabel resultLabel;
public VolumeConverter() {
setTitle("Volume Converter");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 0);
slider.setMajorTickSpacing(10);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
add(slider);
resultLabel = new JLabel();
updateResult();
add(resultLabel);
slider.addChangeListener(e -> updateResult());
setVisible(true);
}
private void updateResult() {
double liters = slider.getValue();
double gallons = liters * 0.264172;
resultLabel.setText(liters + " liters = " + gallons + " gallons");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(VolumeConverter::new);
}
}
6.2 图像查看器
- 功能概述 :此应用程序允许用户通过按钮或菜单项打开文件选择器,选择图像文件后加载并显示该图像。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加一个
JButton或菜单项,点击时显示文件选择器。 - 使用
JFileChooser让用户选择图像文件。 - 选择文件后,使用
ImageIcon加载图像并显示在JLabel中。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
public class ImageViewer extends JFrame {
private JButton openButton;
private JLabel imageLabel;
public ImageViewer() {
setTitle("Image Viewer");
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
openButton = new JButton("Open Image");
add(openButton);
imageLabel = new JLabel();
add(imageLabel);
openButton.addActionListener(e -> {
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(this);
if (result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
ImageIcon image = new ImageIcon(selectedFile.getAbsolutePath());
imageLabel.setIcon(image);
}
});
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ImageViewer::new);
}
}
6.3 宿舍和膳食计划计算器
- 功能概述 :该应用程序提供两个组合框,分别用于选择宿舍和膳食计划,用户选择后显示学期的总费用。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加两个
JComboBox,一个用于选择宿舍,另一个用于选择膳食计划。 - 为每个组合框设置选项和对应的费用。
- 添加一个
JLabel用于显示总费用。 - 为组合框添加监听器,当选择改变时,计算总费用并更新
JLabel的显示内容。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class DormMealCalculator extends JFrame {
private JComboBox<String> dormBox;
private JComboBox<String> mealBox;
private JLabel resultLabel;
private static final String[] DORMS = {"Allen Hall", "Pike Hall", "Farthing Hall", "University Suites"};
private static final int[] DORM_FEES = {1500, 1600, 1200, 1800};
private static final String[] MEALS = {"7 meals per week", "14 meals per week", "Unlimited meals"};
private static final int[] MEAL_FEES = {560, 1095, 1500};
public DormMealCalculator() {
setTitle("Dorm and Meal Plan Calculator");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
dormBox = new JComboBox<>(DORMS);
add(dormBox);
mealBox = new JComboBox<>(MEALS);
add(mealBox);
resultLabel = new JLabel();
updateResult();
add(resultLabel);
dormBox.addActionListener(e -> updateResult());
mealBox.addActionListener(e -> updateResult());
setVisible(true);
}
private void updateResult() {
int dormIndex = dormBox.getSelectedIndex();
int mealIndex = mealBox.getSelectedIndex();
int total = DORM_FEES[dormIndex] + MEAL_FEES[mealIndex];
resultLabel.setText("Total charges: $" + total);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(DormMealCalculator::new);
}
}
6.4 滑板设计师
- 功能概述 :该应用程序允许用户从列表组件或组合框中选择一个滑板甲板、一个卡车组件和一组轮子,还可以选择多个杂项产品,最后显示小计、销售税(6%)和订单总额。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加三个
JComboBox分别用于选择滑板甲板、卡车组件和轮子。 - 添加一个
JList用于选择多个杂项产品。 - 添加一个
JLabel用于显示小计、销售税和订单总额。 - 为组合框和列表添加监听器,当选择改变时,计算小计、销售税和订单总额并更新
JLabel的显示内容。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
public class SkateboardDesigner extends JFrame {
private JComboBox<String> deckBox;
private JComboBox<String> truckBox;
private JComboBox<String> wheelBox;
private JList<String> miscList;
private JLabel resultLabel;
private static final String[] DECKS = {"The Master Thrasher", "The Dictator", "The Street King"};
private static final int[] DECK_PRICES = {60, 45, 50};
private static final String[] TRUCKS = {"7.75 inch axle", "8 inch axle", "8.5 inch axle"};
private static final int[] TRUCK_PRICES = {35, 40, 45};
private static final String[] WHEELS = {"51 mm", "55 mm", "58 mm", "61 mm"};
private static final int[] WHEEL_PRICES = {20, 22, 24, 28};
private static final String[] MISC = {"Grip tape", "Bearings", "Riser pads", "Nuts & bolts kit"};
private static final int[] MISC_PRICES = {10, 30, 2, 3};
public SkateboardDesigner() {
setTitle("Skateboard Designer");
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
deckBox = new JComboBox<>(DECKS);
add(deckBox);
truckBox = new JComboBox<>(TRUCKS);
add(truckBox);
wheelBox = new JComboBox<>(WHEELS);
add(wheelBox);
miscList = new JList<>(MISC);
miscList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
JScrollPane scrollPane = new JScrollPane(miscList);
add(scrollPane);
resultLabel = new JLabel();
updateResult();
add(resultLabel);
deckBox.addActionListener(e -> updateResult());
truckBox.addActionListener(e -> updateResult());
wheelBox.addActionListener(e -> updateResult());
miscList.addListSelectionListener(e -> updateResult());
setVisible(true);
}
private void updateResult() {
int deckIndex = deckBox.getSelectedIndex();
int truckIndex = truckBox.getSelectedIndex();
int wheelIndex = wheelBox.getSelectedIndex();
List<Integer> miscIndices = miscList.getSelectedIndicesList();
int subtotal = DECK_PRICES[deckIndex] + TRUCK_PRICES[truckIndex] + WHEEL_PRICES[wheelIndex];
for (int index : miscIndices) {
subtotal += MISC_PRICES[index];
}
double tax = subtotal * 0.06;
double total = subtotal + tax;
resultLabel.setText("Subtotal: $" + subtotal + ", Tax: $" + tax + ", Total: $" + total);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(SkateboardDesigner::new);
}
}
6.5 购物车系统
- 功能概述 :该应用程序从文件中读取书籍信息,用户可以选择书籍添加到购物车,结算时显示小计、销售税(6%)和总额。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 从文件中读取书籍信息并存储在
JList中。 - 添加一个
JList作为购物车,用户可以将书籍从书籍列表添加到购物车。 - 添加按钮或菜单项用于移除购物车中的项目、清空购物车和结算。
- 为按钮或菜单项添加监听器,实现相应的功能。
- 结算时,计算小计、销售税和总额并显示。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ShoppingCartSystem extends JFrame {
private JList<String> bookList;
private JList<String> cartList;
private JButton addButton;
private JButton removeButton;
private JButton clearButton;
private JButton checkoutButton;
private JLabel resultLabel;
private DefaultListModel<String> bookModel;
private DefaultListModel<String> cartModel;
private List<Double> bookPrices;
public ShoppingCartSystem() {
setTitle("Shopping Cart System");
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
bookModel = new DefaultListModel<>();
cartModel = new DefaultListModel<>();
bookPrices = new ArrayList<>();
try {
BufferedReader reader = new BufferedReader(new FileReader("BookPrices.txt"));
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(",");
String title = parts[0].trim();
double price = Double.parseDouble(parts[1].trim());
bookModel.addElement(title);
bookPrices.add(price);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
bookList = new JList<>(bookModel);
cartList = new JList<>(cartModel);
addButton = new JButton("Add to Cart");
removeButton = new JButton("Remove from Cart");
clearButton = new JButton("Clear Cart");
checkoutButton = new JButton("Checkout");
resultLabel = new JLabel();
JPanel buttonPanel = new JPanel();
buttonPanel.add(addButton);
buttonPanel.add(removeButton);
buttonPanel.add(clearButton);
buttonPanel.add(checkoutButton);
add(new JScrollPane(bookList), BorderLayout.WEST);
add(new JScrollPane(cartList), BorderLayout.EAST);
add(buttonPanel, BorderLayout.SOUTH);
add(resultLabel, BorderLayout.NORTH);
addButton.addActionListener(e -> {
int selectedIndex = bookList.getSelectedIndex();
if (selectedIndex != -1) {
String book = bookModel.getElementAt(selectedIndex);
cartModel.addElement(book);
}
});
removeButton.addActionListener(e -> {
int selectedIndex = cartList.getSelectedIndex();
if (selectedIndex != -1) {
cartModel.remove(selectedIndex);
}
});
clearButton.addActionListener(e -> cartModel.clear());
checkoutButton.addActionListener(e -> {
double subtotal = 0;
for (int i = 0; i < cartModel.size(); i++) {
String book = cartModel.getElementAt(i);
int index = bookModel.indexOf(book);
subtotal += bookPrices.get(index);
}
double tax = subtotal * 0.06;
double total = subtotal + tax;
resultLabel.setText("Subtotal: $" + subtotal + ", Tax: $" + tax + ", Total: $" + total);
});
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ShoppingCartSystem::new);
}
}
6.6 手机套餐
- 功能概述 :该应用程序显示菜单系统,用户可以选择一个套餐、一部手机和所需的选项,应用程序显示所选项目的价格。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加三个
JComboBox分别用于选择套餐、手机和选项。 - 添加一个
JLabel用于显示所选项目的价格。 - 为组合框添加监听器,当选择改变时,计算所选项目的价格并更新
JLabel的显示内容。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CellPhonePackages extends JFrame {
private JComboBox<String> packageBox;
private JComboBox<String> phoneBox;
private JComboBox<String> optionBox;
private JLabel resultLabel;
private static final String[] PACKAGES = {"300 minutes per month", "800 minutes per month", "1500 minutes per month"};
private static final double[] PACKAGE_PRICES = {45.00, 65.00, 99.00};
private static final String[] PHONES = {"Model 100", "Model 110", "Model 200"};
private static final double[] PHONE_PRICES = {29.95, 49.95, 99.95};
private static final String[] OPTIONS = {"Voice mail", "Text messaging"};
private static final double[] OPTION_PRICES = {5.00, 10.00};
public CellPhonePackages() {
setTitle("Cell Phone Packages");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
packageBox = new JComboBox<>(PACKAGES);
add(packageBox);
phoneBox = new JComboBox<>(PHONES);
add(phoneBox);
optionBox = new JComboBox<>(OPTIONS);
add(optionBox);
resultLabel = new JLabel();
updateResult();
add(resultLabel);
packageBox.addActionListener(e -> updateResult());
phoneBox.addActionListener(e -> updateResult());
optionBox.addActionListener(e -> updateResult());
setVisible(true);
}
private void updateResult() {
int packageIndex = packageBox.getSelectedIndex();
int phoneIndex = phoneBox.getSelectedIndex();
int optionIndex = optionBox.getSelectedIndex();
double packagePrice = PACKAGE_PRICES[packageIndex];
double phonePrice = PHONE_PRICES[phoneIndex];
double optionPrice = OPTION_PRICES[optionIndex];
double phoneTax = phonePrice * 0.06;
double total = packagePrice + phonePrice + phoneTax + optionPrice;
resultLabel.setText("Package: $" + packagePrice + ", Phone: $" + phonePrice + ", Tax: $" + phoneTax + ", Option: $" + optionPrice + ", Total: $" + total);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(CellPhonePackages::new);
}
}
6.7 遮阳帘设计师
- 功能概述 :该应用程序允许用户从列表或组合框中选择遮阳帘的样式、尺寸、颜色和数量,显示总费用。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加四个
JComboBox分别用于选择样式、尺寸、颜色和数量。 - 添加一个
JLabel用于显示总费用。 - 为组合框添加监听器,当选择改变时,计算总费用并更新
JLabel的显示内容。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ShadeDesigner extends JFrame {
private JComboBox<String> styleBox;
private JComboBox<String> sizeBox;
private JComboBox<String> colorBox;
private JComboBox<String> quantityBox;
private JLabel resultLabel;
private static final String[] STYLES = {"Regular shades", "Folding shades", "Roman shades"};
private static final int[] STYLE_PRICES = {0, 10, 15};
private static final String[] SIZES = {"25 inches wide", "27 inches wide", "32 inches wide", "40 inches wide"};
private static final int[] SIZE_PRICES = {0, 2, 4, 6};
private static final String[] COLORS = {"Natural", "Blue", "Teal", "Red", "Green"};
private static final int[] COLOR_PRICES = {5, 0, 0, 0, 0};
private static final String[] QUANTITIES = {"1", "2", "3", "4", "5"};
public ShadeDesigner() {
setTitle("Shade Designer");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
styleBox = new JComboBox<>(STYLES);
add(styleBox);
sizeBox = new JComboBox<>(SIZES);
add(sizeBox);
colorBox = new JComboBox<>(COLORS);
add(colorBox);
quantityBox = new JComboBox<>(QUANTITIES);
add(quantityBox);
resultLabel = new JLabel();
updateResult();
add(resultLabel);
styleBox.addActionListener(e -> updateResult());
sizeBox.addActionListener(e -> updateResult());
colorBox.addActionListener(e -> updateResult());
quantityBox.addActionListener(e -> updateResult());
setVisible(true);
}
private void updateResult() {
int styleIndex = styleBox.getSelectedIndex();
int sizeIndex = sizeBox.getSelectedIndex();
int colorIndex = colorBox.getSelectedIndex();
int quantity = Integer.parseInt((String) quantityBox.getSelectedItem());
int baseFee = 50;
int styleFee = STYLE_PRICES[styleIndex];
int sizeFee = SIZE_PRICES[sizeIndex];
int colorFee = COLOR_PRICES[colorIndex];
int total = (baseFee + styleFee + sizeFee + colorFee) * quantity;
resultLabel.setText("Total charges: $" + total);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ShadeDesigner::new);
}
}
6.8 会议注册系统
- 功能概述 :该应用程序计算会议注册费用,用户可以选择注册类型、可选的开幕晚宴和主题演讲,以及多个会前研讨会,显示总费用。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加一个
JComboBox用于选择注册类型。 - 添加
JCheckBox用于选择开幕晚宴和主题演讲以及多个会前研讨会。 - 添加一个
JLabel用于显示总费用。 - 为组合框和复选框添加监听器,当选择改变时,计算总费用并更新
JLabel的显示内容。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ConferenceRegistrationSystem extends JFrame {
private JComboBox<String> registrationBox;
private JCheckBox dinnerBox;
private JList<String> workshopList;
private JLabel resultLabel;
private static final String[] REGISTRATIONS = {"General", "Student"};
private static final int[] REGISTRATION_FEES = {895, 495};
private static final String[] WORKSHOPS = {"Introduction to E-commerce", "The Future of the Web", "Advanced Java Programming", "Network Security"};
private static final int[] WORKSHOP_FEES = {295, 295, 395, 395};
private static final int DINNER_FEE = 30;
public ConferenceRegistrationSystem() {
setTitle("Conference Registration System");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
registrationBox = new JComboBox<>(REGISTRATIONS);
add(registrationBox);
dinnerBox = new JCheckBox("Opening night dinner and keynote speech");
add(dinnerBox);
workshopList = new JList<>(WORKSHOPS);
workshopList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
JScrollPane scrollPane = new JScrollPane(workshopList);
add(scrollPane);
resultLabel = new JLabel();
updateResult();
add(resultLabel);
registrationBox.addActionListener(e -> updateResult());
dinnerBox.addActionListener(e -> updateResult());
workshopList.addListSelectionListener(e -> updateResult());
setVisible(true);
}
private void updateResult() {
int registrationIndex = registrationBox.getSelectedIndex();
boolean dinnerSelected = dinnerBox.isSelected();
int[] workshopIndices = workshopList.getSelectedIndices();
int registrationFee = REGISTRATION_FEES[registrationIndex];
int dinnerFee = dinnerSelected ? DINNER_FEE : 0;
int workshopFee = 0;
for (int index : workshopIndices) {
workshopFee += WORKSHOP_FEES[index];
}
int total = registrationFee + dinnerFee + workshopFee;
resultLabel.setText("Total cost: $" + total);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ConferenceRegistrationSystem::new);
}
}
6.9 骰子模拟器
- 功能概述 :该应用程序模拟一对骰子,每次点击按钮时,使用随机数确定每个骰子的值并显示。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加一个
JButton,点击时触发骰子滚动。 - 添加两个
JLabel用于显示每个骰子的值。 - 为按钮添加监听器,点击时生成两个 1 到 6 之间的随机数,并更新
JLabel的显示内容。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class DiceSimulator extends JFrame {
private JButton rollButton;
private JLabel die1Label;
private JLabel die2Label;
private Random random;
public DiceSimulator() {
setTitle("Dice Simulator");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
rollButton = new JButton("Roll Dice");
add(rollButton);
die1Label = new JLabel();
add(die1Label);
die2Label = new JLabel();
add(die2Label);
random = new Random();
rollButton.addActionListener(e -> {
int die1 = random.nextInt(6) + 1;
int die2 = random.nextInt(6) + 1;
die1Label.setText("Die 1: " + die1);
die2Label.setText("Die 2: " + die2);
});
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(DiceSimulator::new);
}
}
6.10 纸牌发牌器
- 功能概述 :该应用程序随机从一副扑克牌中选择一张牌并显示,每次选择后将牌从牌堆中移除,当牌堆中没有牌时显示消息。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加一个
JButton,点击时触发选牌操作。 - 添加一个
JLabel用于显示选中的牌。 - 初始化一副扑克牌,并存储在列表中。
- 为按钮添加监听器,点击时从列表中随机选择一张牌,显示在
JLabel中,并将该牌从列表中移除。 - 当列表为空时,显示消息提示。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CardDealer extends JFrame {
private JButton dealButton;
private JLabel cardLabel;
private List<String> deck;
public CardDealer() {
setTitle("Card Dealer");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
dealButton = new JButton("Deal Card");
add(dealButton);
cardLabel = new JLabel();
add(cardLabel);
deck = new ArrayList<>();
String[] suits = {"Hearts", "Diamonds", "Clubs", "Spades"};
String[] ranks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
for (String suit : suits) {
for (String rank : ranks) {
deck.add(rank + " of " + suit);
}
}
Collections.shuffle(deck);
dealButton.addActionListener(e -> {
if (!deck.isEmpty()) {
String card = deck.remove(0);
cardLabel.setText(card);
} else {
cardLabel.setText("No more cards left in the deck.");
}
});
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(CardDealer::new);
}
}
6.11 井字棋模拟器
- 功能概述 :该应用程序模拟井字棋游戏,使用二维数组模拟游戏板,显示游戏结果。
- 实现步骤 :
- 创建一个
JFrame作为主窗口。 - 在窗口中添加九个
JLabel用于显示 X 和 O。 - 添加一个
JButton用于开始新游戏。 - 使用二维数组模拟游戏板。
- 为按钮添加监听器,点击时开始新游戏,随机填充数组并更新
JLabel的显示内容。 - 检查游戏是否有胜者或平局,并显示相应的消息。
- 创建一个
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class TicTacToeSimulator extends JFrame {
private JLabel[][] boardLabels;
private JButton newGameButton;
private JLabel resultLabel;
private int[][] board;
private Random random;
public TicTacToeSimulator() {
setTitle("Tic Tac Toe Simulator");
setSize(300, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JPanel boardPanel = new JPanel(new GridLayout(3, 3));
boardLabels = new JLabel[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
boardLabels[i][j] = new JLabel();
boardLabels[i][j].setHorizontalAlignment(JLabel.CENTER);
boardLabels[i][j].setFont(new Font("Arial", Font.BOLD, 48));
boardPanel.add(boardLabels[i][j]);
}
}
add(boardPanel, BorderLayout.CENTER);
newGameButton = new JButton("New Game");
add(newGameButton, BorderLayout.SOUTH);
resultLabel = new JLabel();
add(resultLabel, BorderLayout.NORTH);
board = new int[3][3];
random = new Random();
newGameButton.addActionListener(e -> newGame());
setVisible(true);
}
private void newGame() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = random.nextInt(2);
if (board[i][j] == 0) {
boardLabels[i][j].setText("O");
} else {
boardLabels[i][j].setText("X");
}
}
}
checkResult();
}
private void checkResult() {
// Check rows
for (int i = 0; i < 3; i++) {
if (board[i][0] == board[i][1] && board[i][1] == board[i][2]) {
if (board[i][0] == 0) {
resultLabel.setText("Player O won!");
return;
} else {
resultLabel.setText("Player X won!");
return;
}
}
}
// Check columns
for (int j = 0; j < 3; j++) {
if (board[0][j] == board[1][j] && board[1][j] == board[2][j]) {
if (board[0][j] == 0) {
resultLabel.setText("Player O won!");
return;
} else {
resultLabel.setText("Player X won!");
return;
}
}
}
// Check diagonals
if (board[0][0] == board[1][1] && board[1][1] == board[2][2]) {
if (board[0][0] == 0) {
resultLabel.setText("Player O won!");
return;
} else {
resultLabel.setText("Player X won!");
return;
}
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0]) {
if (board[0][2] == 0) {
resultLabel.setText("Player O won!");
return;
} else {
resultLabel.setText("Player X won!");
return;
}
}
resultLabel.setText("It's a tie!");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(TicTacToeSimulator::new);
}
}
总结
通过以上内容,我们全面了解了高级 GUI 应用程序开发的相关知识,包括更改 GUI 外观与感觉、避免常见错误、完成复习问题与练习、解答简答题以及实现多个编程挑战。在开发过程中,我们需要注意各种细节,如组件的使用、事件处理、布局管理等。同时,通过编程挑战的实践,我们可以进一步提高自己的编程能力和解决问题的能力。希望这些内容对大家在高级 GUI 应用程序开发方面有所帮助。
流程图示例
graph TD;
A[开始] --> B[选择编程挑战,如体积转换];
B --> C[创建 JFrame 主窗口];
C --> D[添加组件,如 JSlider、JLabel 等];
D --> E[为组件添加监听器];
E --> F[处理事件,如计算结果、更新显示];
F --> G[结束];
表格总结
| 编程挑战 | 功能概述 | 关键组件 |
|---|---|---|
| 体积转换 | 将升转换为加仑,使用滑块调整体积 | JSlider、JLabel |
| 图像查看器 | 选择并显示图像文件 | JButton、JFileChooser、JLabel |
| 宿舍和膳食计划计算器 | 选择宿舍和膳食计划,计算总费用 | JComboBox、JLabel |
| 滑板设计师 | 选择滑板组件和杂项产品,计算费用 | JComboBox、JList、JLabel |
| 购物车系统 | 选择书籍添加到购物车,结算费用 | JList、JButton、JLabel |
| 手机套餐 | 选择套餐、手机和选项,显示价格 | JComboBox、JLabel |
| 遮阳帘设计师 | 选择遮阳帘样式、尺寸、颜色和数量,计算费用 | JComboBox、JLabel |
| 会议注册系统 | 选择注册类型、晚宴和研讨会,计算费用 | JComboBox、JCheckBox、JList、JLabel |
| 骰子模拟器 | 模拟掷骰子 | JButton、JLabel |
| 纸牌发牌器 | 随机发牌,牌发完显示消息 | JButton、JLabel |
| 井字棋模拟器 | 模拟井字棋游戏,显示结果 | JLabel、JButton |
超级会员免费看

7259

被折叠的 条评论
为什么被折叠?



