201771010101 白玛次仁 《2018面向对象程序设计(Java)》第十四周学习总结
发布日期:2021-09-05 00:32:46 浏览次数:11 分类:技术文章

本文共 71328 字,大约阅读时间需要 237 分钟。

  

实验十四  Swing图形界面组件

实验时间 2018-11-29

学习总结:

Swing和MVC设计模式

(1)设计模式(Design pattern)是设计者一种流行的 思考设计问题的方法,是一套被反复使用,多数人 知晓的,经过分类编目的,代码设计经验的总结。

(2)模型-视图-控制器设计模式(Model –ViewController )是Java EE平台下创建 Web 应用程序 的重要设计模式。

(3)MVC设计模式 – Model(模型):是程序中用于处理程序数据逻 辑的部分,通常模型负责在数据库中存取数据。

– View(视图):是程序中处理数据显示的部分, 通常视图依据模型存取的数据创建。

– Controller(控制器):是程序中处理用户交互 的部分。通常控制器负责从视图读取数据,控制 用户输入,并向模型发送数据。

(4)Java组件有内容、外观、行为三个主要元素;

 布局管理器

(1)布局管理器是一组类。 – 实现 java.awt.LayoutManager 接口 – 决定容器中组件的位置和大小

Java.awt包中定义了5种布局管理类,每一种布 局管理类对应一种布局策略。

每个容器都有与之相关的默认布局管理器。

(2)5种布局管理器:(1)FlowLayout: 流布局(Applet和Panel的默认 布局管理器) (2)BorderLayout:边框布局( Window、Frame和 Dialog的默认布局管理器) (3)GridLayout: 网格布局 (4)GridBagLayout: 网格组布局 (5)CardLayout :卡片布局

3、GridLayout的构造函数如下:1、GridLayout():生成一个单行单列的网格布局

2、GridLayout(int rows,int cols):生成一个设定行数 和列数的网格布局

3、GridLayout(int rows,int columns,int hgap,int vgap): 可以设置组件之间的水平和垂直间隔

 文本输入

(1)文本域(JTextField) : 用于获取单行文本输入。

(2)文本区(JTextArea)组件可让用户输入多行文 本。生成JTextArea组件对象时,可以指定文本 区的行数和列数: textArea = new JTextArea(8, 40);

  (3)文本区与文本域的异同相同之处: 文本域和文本区组件都可用于获取文本输入。

不同之处:  文本域只能接受单行文本的输入;  文本区能够接受多行文本的输入。

(4)文本区JTextArea的常用API:Java.swing. JTextArea 1.2 – JTextArea(int rows, int cols)

构造一个rows行cols列的文本区对象 – JTextArea(String text,int rows, int cols)

用初始文本构造一个文本区对象 – void setRows(int rows)

设置文本域使用的行数 – void append(String newText)

将给定文本附加到文本区中已有文本的后面 – void setLineWrap(boolean wrap)

打开或关闭换行

(5)标签组件:标签是容纳文本的组件。它们没有任何修饰(如没有边界 ),也不响应用户输入。

 标签的常用用途之一就是标识组件,例如标识文本域。其使用步骤如下:

1. 创建一个JLabel组件

2. 将标签组件放置在距离被标识组件足够近的地方。

(6)密码域:密码域是一种特殊类型的文本域。每个输入的字 符都用回显字符实现,典型的回显字符为*。

– JPassWordField(String text, int columns) 构造一个密码域对象

(7)滚动窗格:

Swing中文本区没有滚动条,若需要滚动条。将文 本区放入一个滚动窗格中即可。

常用API—Java.swing. JScrollPane(教材340页) – JScrollPane(Component c) 在组件c上添加滚动条,返回添加后的组件。

 选择组件

复选框  单选按钮  边框  组合框  滑动条

(1)复选框构造器 1.bold = new JCheckBox("Bold"); 复选框自动地带有表示标签。

2. JCheckBox(String label,Icon icon); 构造带有标签与图标的复选框,默认初始未被选择。

3.JCheckBox(String label,boolean state); 用指定的标签和初始化选择状态构造一个复选框

(2)单选按钮的构造器(教材492页) 1.JRadioButton(String label,Icon icon); 创建一个带标签和图标的单选按钮

2.JRadioButton(String label,boolean state); 用指定的标签和初始化状态构造单选按钮

(3)按钮组:为单选按钮组构造一个ButtonGroup的对象。 然后,再将JRadioButton类型的对象添加到按钮 组中。按钮组负责在新按钮被按下的时,取消前一 个按钮的选择状态。

(4)如果在一个窗口中 有多组复选框或单选按 钮,就需要可视化的形 式指明哪些按钮属于同 一组。Swing提供了一 组很有用的边框

(5)如果有多个选择项,使用单选按钮占据的屏幕空 间太大时,就可以选择组合框。

faceCombo = new JComboBox(); faceCombo.setEditable(true);

让组合框可编辑 faceCombo.addItem("Serif"); faceCombo.insertItemAt("Monospace",0);

增加组合框选项 faceCombo.removeItem("Monospace");

faceCombo.removeItemAt(0); 删除组合框选项内容

(6)组合框的事件监听:为了判断组合框的哪个选项被选择,可通过 事件参数调用getSource方法来得到发送事件的组 合框引用,接着调用getSelectdeItem方法获取当 前选择的选项。

(7)滑动条:滑动条可以让用户从一组离散值中进行选择 ,并且它还允许进行连续值得选择。

 菜单

菜单创建  菜单项中的图标  复选框和单选按钮菜单项  弹出菜单  快捷键和加速器  启用和禁用菜单项  工具栏  工具提示

网格组布局 (GridBagLayout):GridBagLayout与GridLayout有点相似,它也是 将组件排在格子里,但是GridBagLayout在网格 的基础上提供更复杂的布局。

GridBagLayout允许单个组件在一个单元中不填 满整个单元,而只是占用最佳大小,也允许单个 组件扩展成不止一个单元,并且可以用任意顺序 加入组件。

定制布局管理器: 程序员可通过自己设计LayoutManager类来实现 特殊的布局方式。

定制布局管理器需要实现LayoutManager接口, 并覆盖以下方法。

 对话框

选项对话框   创建对话框   数据选择   文件对话框  颜色选择器

(1)对话框是一种大小不能变化、不能有菜单的容器窗口; 对话框不能作为一个应用程序的主框架,而必须包含在其 他的容器中。

(2)选项对话框:JOptionPane提供的对话框是模式对话框。当模 式对话框显示时,它不允许用户输入到程序的 其他的窗口。使用JOptionPane,可以创建和自 定义问题、信息、警告和错误等几种类型的对 话框。

(3)数据交换:输入对话框含有供用户输入文本的文本框、一个确认和取 消按钮,是有模式对话框。当输入对话框可见时,要求用户 输入一个字符串。

(4)文件对话框:专门用于对文件(或目录)进行浏览和选择的对 话框,常用的构造方法: – JFileChooser():根据用户的缺省目录创建文件对话框 – JFileChooser(File currentDirectory):根据File型参数 currentDirectory指定的目录创建文件对话框

(5)颜色对话框: javax.swing包中的JColorChooser类的静态方 法: public static Color showDialog(Component component, String title, Color initialColor)创建一个颜色对话框

(6)参数component指定对话框所依赖的组件,title 指定对话框的标题;initialColor 指定对话框返回 的初始颜色,即对话框消失后,返回的默认值。 颜色对话框可根据用户在颜色对话框中选择的颜 色返回一个颜色对象.

 

1、实验目的与要求

(1) 掌握GUI布局管理器用法;

(2) 掌握各类Java Swing组件用途及常用API;

2、实验内容和步骤

实验1: 导入第12章示例程序,测试程序并进行组内讨论。

测试程序1

l 在elipse IDE中运行教材479页程序12-1,结合运行结果理解程序;

l 掌握各种布局管理器的用法;

l 理解GUI界面中事件处理技术的用途。

l 在布局管理应用代码处添加注释;

package calculator;import java.awt.*;import java.awt.event.*;import javax.swing.*;/** * A panel with calculator buttons and a result display. */public class CalculatorPanel extends JPanel{   //属性   private JButton display;   private JPanel panel;   private double result;   private String lastCommand;   private boolean start;   //构造器   public CalculatorPanel()   {      setLayout(new BorderLayout());//设定新的边框布局管理器      result = 0;      lastCommand = "=";      start = true;      // 添加display      display = new JButton("0");//用来显示完成算式计算结果      display.setEnabled(false);//使得使能属性不能起作用      add(display, BorderLayout.NORTH);//将display添加到北部区域      //生成监听器对象      ActionListener insert = new InsertAction();      ActionListener command = new CommandAction();      // 在4 x 4网格中添加按钮      panel = new JPanel();//新建窗格组件      panel.setLayout(new GridLayout(4, 4));//设定4行4列的网格布局管理器      //生成16个事件源,数字注册的事件源是insert对象,运算符注册的事件源是command对象      addButton("7", insert);      addButton("8", insert);      addButton("9", insert);      addButton("/", command);      addButton("4", insert);      addButton("5", insert);      addButton("6", insert);      addButton("*", command);      addButton("1", insert);      addButton("2", insert);      addButton("3", insert);      addButton("-", command);      addButton("0", insert);      addButton(".", insert);      addButton("=", command);      addButton("+", command);             add(panel, BorderLayout.CENTER);//将panel添加到中部区域        }   /**    * Adds a button to the center panel.    * @param label the button label    * @param listener the button listener    */   //方法   private void addButton(String label, ActionListener listener)   {      JButton button = new JButton(label);//生成按钮对象      button.addActionListener(listener);//注册监听器对象      panel.add(button);//将其添加到窗格中   }   /**    * This action inserts the button action string to the end of the display text.    */   //内部类   private class InsertAction implements ActionListener   {      public void actionPerformed(ActionEvent event)      {         String input = event.getActionCommand();         if (start)//开始计算         {            display.setText("");            start = false;         }         display.setText(display.getText() + input);//完成多个数字的输入操作      }   }   /**    * This action executes the command that the button action string denotes.    */  //内部类   private class CommandAction implements ActionListener   {      public void actionPerformed(ActionEvent event)      {         String command = event.getActionCommand();         if (start)//开始计算还没有输入数字         {                         if (command.equals("-"))            {               display.setText(command);//显示符号               start = false;            }            else lastCommand = command;         }         else         {            calculate(Double.parseDouble(display.getText()));//将数字字符串转化为数字            lastCommand = command;            start = true;         }      }   }   /**    * Carries out the pending calculation.    * @param x the value to be accumulated with the prior result.    */   //计算方法   public void calculate(double x)   {      if (lastCommand.equals("+")) result += x;      else if (lastCommand.equals("-")) result -= x;      else if (lastCommand.equals("*")) result *= x;      else if (lastCommand.equals("/")) result /= x;      else if (lastCommand.equals("=")) result = x;      display.setText("" + result);//将数字转化为数字字符串输出   }}

  

package calculator;import java.awt.*;import javax.swing.*;/** * @version 1.34 2015-06-12 * @author Cay Horstmann */public class Calculator{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         CalculatorFrame frame = new CalculatorFrame();         frame.setTitle("Calculator");//设置标题         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭         frame.setVisible(true);//设置可见      });   }}

 

package calculator;import javax.swing.*;/** * A frame with a calculator panel. */public class CalculatorFrame extends JFrame{   public CalculatorFrame()   {      add(new CalculatorPanel());      pack();   }}

  

 

 

测试程序2

l 在elipse IDE中调试运行教材486页程序12-2,结合运行结果理解程序;

l 掌握各种文本组件的用法;

l 记录示例代码阅读理解中存在的问题与疑惑。

package text;import java.awt.BorderLayout;import java.awt.GridLayout;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JPasswordField;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;import javax.swing.SwingConstants;/** * A frame with sample text components. */public class TextComponentFrame extends JFrame{   public static final int TEXTAREA_ROWS = 8;   public static final int TEXTAREA_COLUMNS = 20;   public TextComponentFrame()   {      JTextField textField = new JTextField();      JPasswordField passwordField = new JPasswordField();      JPanel northPanel = new JPanel();      northPanel.setLayout(new GridLayout(2, 2));      northPanel.add(new JLabel("User name: ", SwingConstants.RIGHT));      northPanel.add(textField);      northPanel.add(new JLabel("Password: ", SwingConstants.RIGHT));      northPanel.add(passwordField);      add(northPanel, BorderLayout.NORTH);      JTextArea textArea = new JTextArea(TEXTAREA_ROWS, TEXTAREA_COLUMNS);      JScrollPane scrollPane = new JScrollPane(textArea);      add(scrollPane, BorderLayout.CENTER);      // add button to append text into the text area      JPanel southPanel = new JPanel();      JButton insertButton = new JButton("Insert");      southPanel.add(insertButton);      insertButton.addActionListener(event ->         textArea.append("User name: " + textField.getText() + " Password: "            + new String(passwordField.getPassword()) + "\n"));      add(southPanel, BorderLayout.SOUTH);      pack();   }}
package text;import java.awt.*;import javax.swing.*;/** * @version 1.41 2015-06-12 * @author Cay Horstmann */public class TextComponentTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         JFrame frame = new TextComponentFrame();         frame.setTitle("TextComponentTest");         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);      });   }}

  

  

 

测试程序3

l 在elipse IDE中调试运行教材489页程序12-3,结合运行结果理解程序;

l 掌握复选框组件的用法;

l 记录示例代码阅读理解中存在的问题与疑惑。

package checkBox;import java.awt.*;import java.awt.event.*;import javax.swing.*;/** * A frame with a sample text label and check boxes for selecting font * attributes. */public class CheckBoxFrame extends JFrame{   private JLabel label;   private JCheckBox bold;   private JCheckBox italic;   private static final int FONTSIZE = 24;   public CheckBoxFrame()   {      // add the sample text label      label = new JLabel("The quick brown fox jumps over the lazy dog.");      label.setFont(new Font("Serif", Font.BOLD, FONTSIZE));      add(label, BorderLayout.CENTER);      // this listener sets the font attribute of      // the label to the check box state      ActionListener listener = event -> {         int mode = 0;         if (bold.isSelected()) mode += Font.BOLD;         if (italic.isSelected()) mode += Font.ITALIC;         label.setFont(new Font("Serif", mode, FONTSIZE));      };      // add the check boxes      JPanel buttonPanel = new JPanel();      bold = new JCheckBox("Bold");      bold.addActionListener(listener);      bold.setSelected(true);      buttonPanel.add(bold);      italic = new JCheckBox("Italic");      italic.addActionListener(listener);      buttonPanel.add(italic);      add(buttonPanel, BorderLayout.SOUTH);      pack();   }}

  

package checkBox;import java.awt.*;import javax.swing.*;/** * @version 1.34 2015-06-12 * @author Cay Horstmann */public class CheckBoxTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         JFrame frame = new CheckBoxFrame();         frame.setTitle("CheckBoxTest");         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);      });   }}

  

 

 

测试程序4

l 在elipse IDE中调试运行教材491页程序12-4,运行结果理解程序;

l 掌握单选按钮组件的用法;

l 记录示例代码阅读理解中存在的问题与疑惑。

package radioButton;import java.awt.*;import java.awt.event.*;import javax.swing.*;/** * A frame with a sample text label and radio buttons for selecting font sizes. */public class RadioButtonFrame extends JFrame{   private JPanel buttonPanel;   private ButtonGroup group;   private JLabel label;   private static final int DEFAULT_SIZE = 36;   public RadioButtonFrame()   {            // add the sample text label      label = new JLabel("The quick brown fox jumps over the lazy dog.");      label.setFont(new Font("Serif", Font.PLAIN, DEFAULT_SIZE));      add(label, BorderLayout.CENTER);      // add the radio buttons      buttonPanel = new JPanel();      group = new ButtonGroup();      addRadioButton("Small", 8);      addRadioButton("Medium", 12);      addRadioButton("Large", 18);      addRadioButton("Extra large", 36);      add(buttonPanel, BorderLayout.SOUTH);      pack();   }   /**    * Adds a radio button that sets the font size of the sample text.    * @param name the string to appear on the button    * @param size the font size that this button sets    */   public void addRadioButton(String name, int size)   {      boolean selected = size == DEFAULT_SIZE;      JRadioButton button = new JRadioButton(name, selected);      group.add(button);      buttonPanel.add(button);      // this listener sets the label font size      ActionListener listener = event -> label.setFont(new Font("Serif", Font.PLAIN, size));      button.addActionListener(listener);   }}

  

package radioButton;import java.awt.*;import javax.swing.*;/** * @version 1.34 2015-06-12 * @author Cay Horstmann */public class RadioButtonTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         JFrame frame = new RadioButtonFrame();         frame.setTitle("RadioButtonTest");         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);      });   }}

  

 

测试程序5

l 在elipse IDE中调试运行教材494页程序12-5,结合运行结果理解程序;

l 掌握边框的用法;

l 记录示例代码阅读理解中存在的问题与疑惑。

package border;import java.awt.*;import javax.swing.*;import javax.swing.border.*;/** * A frame with radio buttons to pick a border style. */public class BorderFrame extends JFrame{   private JPanel demoPanel;   private JPanel buttonPanel;   private ButtonGroup group;   public BorderFrame()   {      demoPanel = new JPanel();      buttonPanel = new JPanel();      group = new ButtonGroup();      addRadioButton("Lowered bevel", BorderFactory.createLoweredBevelBorder());      addRadioButton("Raised bevel", BorderFactory.createRaisedBevelBorder());      addRadioButton("Etched", BorderFactory.createEtchedBorder());      addRadioButton("Line", BorderFactory.createLineBorder(Color.BLUE));      addRadioButton("Matte", BorderFactory.createMatteBorder(10, 10, 10, 10, Color.BLUE));      addRadioButton("Empty", BorderFactory.createEmptyBorder());      Border etched = BorderFactory.createEtchedBorder();      Border titled = BorderFactory.createTitledBorder(etched, "Border types");      buttonPanel.setBorder(titled);      setLayout(new GridLayout(2, 1));      add(buttonPanel);      add(demoPanel);      pack();   }   public void addRadioButton(String buttonName, Border b)   {      JRadioButton button = new JRadioButton(buttonName);      button.addActionListener(event -> demoPanel.setBorder(b));      group.add(button);      buttonPanel.add(button);   }}

  

package border;import java.awt.*;import javax.swing.*;/** * @version 1.34 2015-06-13 * @author Cay Horstmann */public class BorderTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         JFrame frame = new BorderFrame();         frame.setTitle("BorderTest");         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);      });   }}

  

 

 

 

测试程序6

l 在elipse IDE中调试运行教材498页程序12-6,结合运行结果理解程序;

l 掌握组合框组件的用法;

l 记录示例代码阅读理解中存在的问题与疑惑。

package comboBox;import java.awt.BorderLayout;import java.awt.Font;import javax.swing.JComboBox;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;/** * A frame with a sample text label and a combo box for selecting font faces. */public class ComboBoxFrame extends JFrame{   private JComboBox
faceCombo; private JLabel label; private static final int DEFAULT_SIZE = 24; public ComboBoxFrame() { // add the sample text label label = new JLabel("The quick brown fox jumps over the lazy dog."); label.setFont(new Font("Serif", Font.PLAIN, DEFAULT_SIZE)); add(label, BorderLayout.CENTER); // make a combo box and add face names faceCombo = new JComboBox<>(); faceCombo.addItem("Serif"); faceCombo.addItem("SansSerif"); faceCombo.addItem("Monospaced"); faceCombo.addItem("Dialog"); faceCombo.addItem("DialogInput"); // the combo box listener changes the label font to the selected face name faceCombo.addActionListener(event -> label.setFont( new Font(faceCombo.getItemAt(faceCombo.getSelectedIndex()), Font.PLAIN, DEFAULT_SIZE))); // add combo box to a panel at the frame's southern border JPanel comboPanel = new JPanel(); comboPanel.add(faceCombo); add(comboPanel, BorderLayout.SOUTH); pack(); }}

  

package comboBox;import java.awt.*;import javax.swing.*;/** * @version 1.35 2015-06-12 * @author Cay Horstmann */public class ComboBoxTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         JFrame frame = new ComboBoxFrame();         frame.setTitle("ComboBoxTest");         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);      });   }}

  

 

测试程序7

l 在elipse IDE中调试运行教材501页程序12-7,结合运行结果理解程序;

l 掌握滑动条组件的用法;

l 记录示例代码阅读理解中存在的问题与疑惑。

package slider;import java.awt.*;import java.util.*;import javax.swing.*;import javax.swing.event.*;/** * A frame with many sliders and a text field to show slider values. */public class SliderFrame extends JFrame{   private JPanel sliderPanel;   private JTextField textField;   private ChangeListener listener;   public SliderFrame()   {      sliderPanel = new JPanel();      sliderPanel.setLayout(new GridBagLayout());      // common listener for all sliders      listener = event -> {         // update text field when the slider value changes         JSlider source = (JSlider) event.getSource();         textField.setText("" + source.getValue());      };      // add a plain slider      JSlider slider = new JSlider();      addSlider(slider, "Plain");      // add a slider with major and minor ticks      slider = new JSlider();      slider.setPaintTicks(true);      slider.setMajorTickSpacing(20);      slider.setMinorTickSpacing(5);      addSlider(slider, "Ticks");      // add a slider that snaps to ticks      slider = new JSlider();      slider.setPaintTicks(true);      slider.setSnapToTicks(true);      slider.setMajorTickSpacing(20);      slider.setMinorTickSpacing(5);      addSlider(slider, "Snap to ticks");      // add a slider with no track      slider = new JSlider();      slider.setPaintTicks(true);      slider.setMajorTickSpacing(20);      slider.setMinorTickSpacing(5);      slider.setPaintTrack(false);      addSlider(slider, "No track");      // add an inverted slider      slider = new JSlider();      slider.setPaintTicks(true);      slider.setMajorTickSpacing(20);      slider.setMinorTickSpacing(5);      slider.setInverted(true);      addSlider(slider, "Inverted");      // add a slider with numeric labels      slider = new JSlider();      slider.setPaintTicks(true);      slider.setPaintLabels(true);      slider.setMajorTickSpacing(20);      slider.setMinorTickSpacing(5);      addSlider(slider, "Labels");      // add a slider with alphabetic labels      slider = new JSlider();      slider.setPaintLabels(true);      slider.setPaintTicks(true);      slider.setMajorTickSpacing(20);      slider.setMinorTickSpacing(5);      Dictionary
labelTable = new Hashtable<>(); labelTable.put(0, new JLabel("A")); labelTable.put(20, new JLabel("B")); labelTable.put(40, new JLabel("C")); labelTable.put(60, new JLabel("D")); labelTable.put(80, new JLabel("E")); labelTable.put(100, new JLabel("F")); slider.setLabelTable(labelTable); addSlider(slider, "Custom labels"); // add a slider with icon labels slider = new JSlider(); slider.setPaintTicks(true); slider.setPaintLabels(true); slider.setSnapToTicks(true); slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(20); labelTable = new Hashtable
(); // add card images labelTable.put(0, new JLabel(new ImageIcon("nine.gif"))); labelTable.put(20, new JLabel(new ImageIcon("ten.gif"))); labelTable.put(40, new JLabel(new ImageIcon("jack.gif"))); labelTable.put(60, new JLabel(new ImageIcon("queen.gif"))); labelTable.put(80, new JLabel(new ImageIcon("king.gif"))); labelTable.put(100, new JLabel(new ImageIcon("ace.gif"))); slider.setLabelTable(labelTable); addSlider(slider, "Icon labels"); // add the text field that displays the slider value textField = new JTextField(); add(sliderPanel, BorderLayout.CENTER); add(textField, BorderLayout.SOUTH); pack(); } /** * Adds a slider to the slider panel and hooks up the listener * @param s the slider * @param description the slider description */ public void addSlider(JSlider s, String description) { s.addChangeListener(listener); JPanel panel = new JPanel(); panel.add(s); panel.add(new JLabel(description)); panel.setAlignmentX(Component.LEFT_ALIGNMENT); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridy = sliderPanel.getComponentCount(); gbc.anchor = GridBagConstraints.WEST; sliderPanel.add(panel, gbc); }

  

package slider;import java.awt.*;import javax.swing.*;/** * @version 1.15 2015-06-12 * @author Cay Horstmann */public class SliderTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         SliderFrame frame = new SliderFrame();         frame.setTitle("SliderTest");         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);      });   }}

  

 

测试程序8

l 在elipse IDE中调试运行教材512页程序12-8,结合运行结果理解程序;

l 掌握菜单的创建、菜单事件监听器、复选框和单选按钮菜单项、弹出菜单以及快捷键和加速器的用法。

l 记录示例代码阅读理解中存在的问题与疑惑。 

package menu;import java.awt.event.*;import javax.swing.*;/** * A frame with a sample menu bar. */public class MenuFrame extends JFrame{   private static final int DEFAULT_WIDTH = 300;   private static final int DEFAULT_HEIGHT = 200;   private Action saveAction;   private Action saveAsAction;   private JCheckBoxMenuItem readonlyItem;   private JPopupMenu popup;   /**    * A sample action that prints the action name to System.out    */   class TestAction extends AbstractAction   {      public TestAction(String name)      {         super(name);      }      public void actionPerformed(ActionEvent event)      {         System.out.println(getValue(Action.NAME) + " selected.");      }   }   public MenuFrame()   {      setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);      JMenu fileMenu = new JMenu("File");      fileMenu.add(new TestAction("New"));  // 演示加速器           JMenuItem openItem = fileMenu.add(new TestAction("Open"));      openItem.setAccelerator(KeyStroke.getKeyStroke("ctrl O"));      fileMenu.addSeparator();      saveAction = new TestAction("Save");      JMenuItem saveItem = fileMenu.add(saveAction);      saveItem.setAccelerator(KeyStroke.getKeyStroke("ctrl S"));      saveAsAction = new TestAction("Save As");      fileMenu.add(saveAsAction);      fileMenu.addSeparator();      fileMenu.add(new AbstractAction("Exit")         {            public void actionPerformed(ActionEvent event)            {               System.exit(0);            }         }); // 演示复选框和单选按钮菜单      readonlyItem = new JCheckBoxMenuItem("Read-only");      readonlyItem.addActionListener(new ActionListener()         {            public void actionPerformed(ActionEvent event)            {               boolean saveOk = !readonlyItem.isSelected();               saveAction.setEnabled(saveOk);               saveAsAction.setEnabled(saveOk);            }         });      ButtonGroup group = new ButtonGroup();      JRadioButtonMenuItem insertItem = new JRadioButtonMenuItem("Insert");      insertItem.setSelected(true);      JRadioButtonMenuItem overtypeItem = new JRadioButtonMenuItem("Overtype");      group.add(insertItem);      group.add(overtypeItem);      // demonstrate icons      Action cutAction = new TestAction("Cut");      cutAction.putValue(Action.SMALL_ICON, new ImageIcon("cut.gif"));      Action copyAction = new TestAction("Copy");      copyAction.putValue(Action.SMALL_ICON, new ImageIcon("copy.gif"));      Action pasteAction = new TestAction("Paste");      pasteAction.putValue(Action.SMALL_ICON, new ImageIcon("paste.gif"));      JMenu editMenu = new JMenu("Edit");      editMenu.add(cutAction);      editMenu.add(copyAction);      editMenu.add(pasteAction);      // 演示嵌套菜单      JMenu optionMenu = new JMenu("Options");      optionMenu.add(readonlyItem);      optionMenu.addSeparator();      optionMenu.add(insertItem);      optionMenu.add(overtypeItem);      editMenu.addSeparator();      editMenu.add(optionMenu);        // 助记符演示      JMenu helpMenu = new JMenu("Help");      helpMenu.setMnemonic('H');      JMenuItem indexItem = new JMenuItem("Index");      indexItem.setMnemonic('I');      helpMenu.add(indexItem);      // 还可以将助记键添加到动作中      Action aboutAction = new TestAction("About");      aboutAction.putValue(Action.MNEMONIC_KEY, new Integer('A'));      helpMenu.add(aboutAction);         // 将所有顶级菜单添加到菜单栏      JMenuBar menuBar = new JMenuBar();      setJMenuBar(menuBar);      menuBar.add(fileMenu);      menuBar.add(editMenu);      menuBar.add(helpMenu);     // 演示弹出窗口      popup = new JPopupMenu();      popup.add(cutAction);      popup.add(copyAction);      popup.add(pasteAction);      JPanel panel = new JPanel();      panel.setComponentPopupMenu(popup);      add(panel);   }}

  

package menu;import java.awt.*;import javax.swing.*;/** * @version 1.24 2012-06-12 * @author Cay Horstmann */public class MenuTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         JFrame frame = new MenuFrame();         frame.setTitle("MenuTest");         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);      });   }}

  

 

  

测试程序9

l 在elipse IDE中调试运行教材517页程序12-9,结合运行结果理解程序;

l 掌握工具栏和工具提示的用法;

l 记录示例代码阅读理解中存在的问题与疑惑。

package toolBar;import java.awt.*;import java.awt.event.*;import javax.swing.*;/** * A frame with a toolbar and menu for color changes. */public class ToolBarFrame extends JFrame{   private static final int DEFAULT_WIDTH = 300;   private static final int DEFAULT_HEIGHT = 200;   private JPanel panel;   public ToolBarFrame()   {      setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);      // add a panel for color change      panel = new JPanel();      add(panel, BorderLayout.CENTER);      // set up actions      Action blueAction = new ColorAction("Blue", new ImageIcon("blue-ball.gif"), Color.BLUE);      Action yellowAction = new ColorAction("Yellow", new ImageIcon("yellow-ball.gif"),            Color.YELLOW);      Action redAction = new ColorAction("Red", new ImageIcon("red-ball.gif"), Color.RED);      Action exitAction = new AbstractAction("Exit", new ImageIcon("exit.gif"))         {            public void actionPerformed(ActionEvent event)            {               System.exit(0);            }         };      exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit");      // populate toolbar      JToolBar bar = new JToolBar();      bar.add(blueAction);      bar.add(yellowAction);      bar.add(redAction);      bar.addSeparator();      bar.add(exitAction);      add(bar, BorderLayout.NORTH);      // populate menu      JMenu menu = new JMenu("Color");      menu.add(yellowAction);      menu.add(blueAction);      menu.add(redAction);      menu.add(exitAction);      JMenuBar menuBar = new JMenuBar();      menuBar.add(menu);      setJMenuBar(menuBar);   }   /**    * The color action sets the background of the frame to a given color.    */   class ColorAction extends AbstractAction   {      public ColorAction(String name, Icon icon, Color c)      {         putValue(Action.NAME, name);         putValue(Action.SMALL_ICON, icon);         putValue(Action.SHORT_DESCRIPTION, name + " background");         putValue("Color", c);      }      public void actionPerformed(ActionEvent event)      {         Color c = (Color) getValue("Color");         panel.setBackground(c);      }   }}

  

package toolBar;import java.awt.*;import javax.swing.*;/** * @version 1.14 2015-06-12 * @author Cay Horstmann */public class ToolBarTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         ToolBarFrame frame = new ToolBarFrame();         frame.setTitle("ToolBarTest");         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);      });   }}

 

 

测试程序10

l 在elipse IDE中调试运行教材524页程序12-10、12-11,结合运行结果理解程序,了解GridbagLayout的用法。

package gridbag;import java.awt.Font;import java.awt.GridBagLayout;import java.awt.event.ActionListener;import javax.swing.BorderFactory;import javax.swing.JCheckBox;import javax.swing.JComboBox;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JTextArea;/** * A frame that uses a grid bag layout to arrange font selection components. */public class FontFrame extends JFrame{   public static final int TEXT_ROWS = 10;   public static final int TEXT_COLUMNS = 20;   private JComboBox
face; private JComboBox
size; private JCheckBox bold; private JCheckBox italic; private JTextArea sample; public FontFrame() { GridBagLayout layout = new GridBagLayout(); setLayout(layout); ActionListener listener = event -> updateSample(); // construct components JLabel faceLabel = new JLabel("Face: "); face = new JComboBox<>(new String[] { "Serif", "SansSerif", "Monospaced", "Dialog", "DialogInput" }); face.addActionListener(listener); JLabel sizeLabel = new JLabel("Size: "); size = new JComboBox<>(new Integer[] { 8, 10, 12, 15, 18, 24, 36, 48 }); size.addActionListener(listener); bold = new JCheckBox("Bold"); bold.addActionListener(listener); italic = new JCheckBox("Italic"); italic.addActionListener(listener); sample = new JTextArea(TEXT_ROWS, TEXT_COLUMNS); sample.setText("The quick brown fox jumps over the lazy dog"); sample.setEditable(false); sample.setLineWrap(true); sample.setBorder(BorderFactory.createEtchedBorder()); // add components to grid, using GBC convenience class add(faceLabel, new GBC(0, 0).setAnchor(GBC.EAST)); add(face, new GBC(1, 0).setFill(GBC.HORIZONTAL).setWeight(100, 0) .setInsets(1)); add(sizeLabel, new GBC(0, 1).setAnchor(GBC.EAST)); add(size, new GBC(1, 1).setFill(GBC.HORIZONTAL).setWeight(100, 0) .setInsets(1)); add(bold, new GBC(0, 2, 2, 1).setAnchor(GBC.CENTER).setWeight(100, 100)); add(italic, new GBC(0, 3, 2, 1).setAnchor(GBC.CENTER).setWeight(100, 100)); add(sample, new GBC(2, 0, 1, 4).setFill(GBC.BOTH).setWeight(100, 100)); pack(); updateSample(); } public void updateSample() { String fontFace = (String) face.getSelectedItem(); int fontStyle = (bold.isSelected() ? Font.BOLD : 0) + (italic.isSelected() ? Font.ITALIC : 0); int fontSize = size.getItemAt(size.getSelectedIndex()); Font font = new Font(fontFace, fontStyle, fontSize); sample.setFont(font); sample.repaint(); }}

  

package gridbag;import java.awt.*;/** * This class simplifies the use of the GridBagConstraints class. * @version 1.01 2004-05-06 * @author Cay Horstmann */public class GBC extends GridBagConstraints{   /**    * Constructs a GBC with a given gridx and gridy position and all other grid    * bag constraint values set to the default.    * @param gridx the gridx position    * @param gridy the gridy position    */   public GBC(int gridx, int gridy)   {      this.gridx = gridx;      this.gridy = gridy;   }   /**    * Constructs a GBC with given gridx, gridy, gridwidth, gridheight and all    * other grid bag constraint values set to the default.    * @param gridx the gridx position    * @param gridy the gridy position    * @param gridwidth the cell span in x-direction    * @param gridheight the cell span in y-direction    */   public GBC(int gridx, int gridy, int gridwidth, int gridheight)   {      this.gridx = gridx;      this.gridy = gridy;      this.gridwidth = gridwidth;      this.gridheight = gridheight;   }   /**    * Sets the anchor.    * @param anchor the anchor value    * @return this object for further modification    */   public GBC setAnchor(int anchor)   {      this.anchor = anchor;      return this;   }   /**    * Sets the fill direction.    * @param fill the fill direction    * @return this object for further modification    */   public GBC setFill(int fill)   {      this.fill = fill;      return this;   }   /**    * Sets the cell weights.    * @param weightx the cell weight in x-direction    * @param weighty the cell weight in y-direction    * @return this object for further modification    */   public GBC setWeight(double weightx, double weighty)   {      this.weightx = weightx;      this.weighty = weighty;      return this;   }   /**    * Sets the insets of this cell.    * @param distance the spacing to use in all directions    * @return this object for further modification    */   public GBC setInsets(int distance)   {      this.insets = new Insets(distance, distance, distance, distance);      return this;   }   /**    * Sets the insets of this cell.    * @param top the spacing to use on top    * @param left the spacing to use to the left    * @param bottom the spacing to use on the bottom    * @param right the spacing to use to the right    * @return this object for further modification    */   public GBC setInsets(int top, int left, int bottom, int right)   {      this.insets = new Insets(top, left, bottom, right);      return this;   }   /**    * Sets the internal padding    * @param ipadx the internal padding in x-direction    * @param ipady the internal padding in y-direction    * @return this object for further modification    */   public GBC setIpad(int ipadx, int ipady)   {      this.ipadx = ipadx;      this.ipady = ipady;      return this;   }}

 

package gridbag;import java.awt.EventQueue;import javax.swing.JFrame;/** * @version 1.35 2015-06-12 * @author Cay Horstmann */public class GridBagLayoutTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() ->           {               JFrame frame = new FontFrame();               frame.setTitle("GridBagLayoutTest");               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);               frame.setVisible(true);         });   }}

  

 

 

l 在elipse IDE中调试运行教材533页程序12-12,结合程序运行结果理解程序,了解GroupLayout的用法。

l 记录示例代码阅读理解中存在的问题与疑惑。

1 package groupLayout; 2  3 import java.awt.EventQueue; 4  5 import javax.swing.JFrame; 6  7 /** 8  * @version 1.01 2015-06-12 9  * @author Cay Horstmann10  */11 public class GroupLayoutTest12 {13    public static void main(String[] args)14    {15       EventQueue.invokeLater(() -> {16          JFrame frame = new FontFrame();17          frame.setTitle("GroupLayoutTest");18          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);19          frame.setVisible(true);20       });21    }22 }

  

1 package groupLayout;  2   3 import java.awt.Font;  4 import java.awt.event.ActionListener;  5   6 import javax.swing.BorderFactory;  7 import javax.swing.GroupLayout;  8 import javax.swing.JCheckBox;  9 import javax.swing.JComboBox; 10 import javax.swing.JFrame; 11 import javax.swing.JLabel; 12 import javax.swing.JScrollPane; 13 import javax.swing.JTextArea; 14 import javax.swing.LayoutStyle; 15 import javax.swing.SwingConstants; 16  17 /** 18  * A frame that uses a group layout to arrange font selection components. 19  */ 20 public class FontFrame extends JFrame 21 { 22    public static final int TEXT_ROWS = 10; 23    public static final int TEXT_COLUMNS = 20; 24  25    private JComboBox
face; 26 private JComboBox
size; 27 private JCheckBox bold; 28 private JCheckBox italic; 29 private JScrollPane pane; 30 private JTextArea sample; 31 32 public FontFrame() 33 { 34 ActionListener listener = event -> updateSample(); 35 36 // construct components 37 38 JLabel faceLabel = new JLabel("Face: "); 39 40 face = new JComboBox<>(new String[] { "Serif", "SansSerif", "Monospaced", "Dialog", 41 "DialogInput" }); 42 43 face.addActionListener(listener); 44 45 JLabel sizeLabel = new JLabel("Size: "); 46 47 size = new JComboBox<>(new Integer[] { 8, 10, 12, 15, 18, 24, 36, 48 }); 48 49 size.addActionListener(listener); 50 51 bold = new JCheckBox("Bold"); 52 bold.addActionListener(listener); 53 54 italic = new JCheckBox("Italic"); 55 italic.addActionListener(listener); 56 57 sample = new JTextArea(TEXT_ROWS, TEXT_COLUMNS); 58 sample.setText("The quick brown fox jumps over the lazy dog"); 59 sample.setEditable(false); 60 sample.setLineWrap(true); 61 sample.setBorder(BorderFactory.createEtchedBorder()); 62 63 pane = new JScrollPane(sample); 64 65 GroupLayout layout = new GroupLayout(getContentPane()); 66 setLayout(layout); 67 layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) 68 .addGroup( 69 layout.createSequentialGroup().addContainerGap().addGroup( 70 layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup( 71 GroupLayout.Alignment.TRAILING, 72 layout.createSequentialGroup().addGroup( 73 layout.createParallelGroup(GroupLayout.Alignment.TRAILING) 74 .addComponent(faceLabel).addComponent(sizeLabel)) 75 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 76 .addGroup( 77 layout.createParallelGroup( 78 GroupLayout.Alignment.LEADING, false) 79 .addComponent(size).addComponent(face))) 80 .addComponent(italic).addComponent(bold)).addPreferredGap( 81 LayoutStyle.ComponentPlacement.RELATED).addComponent(pane) 82 .addContainerGap())); 83 84 layout.linkSize(SwingConstants.HORIZONTAL, new java.awt.Component[] { face, size }); 85 86 layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) 87 .addGroup( 88 layout.createSequentialGroup().addContainerGap().addGroup( 89 layout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent( 90 pane, GroupLayout.Alignment.TRAILING).addGroup( 91 layout.createSequentialGroup().addGroup( 92 layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 93 .addComponent(face).addComponent(faceLabel)) 94 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 95 .addGroup( 96 layout.createParallelGroup( 97 GroupLayout.Alignment.BASELINE).addComponent(size) 98 .addComponent(sizeLabel)).addPreferredGap( 99 LayoutStyle.ComponentPlacement.RELATED).addComponent(100 italic, GroupLayout.DEFAULT_SIZE,101 GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)102 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)103 .addComponent(bold, GroupLayout.DEFAULT_SIZE,104 GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))105 .addContainerGap()));106 pack();107 }108 109 public void updateSample()110 {111 String fontFace = (String) face.getSelectedItem();112 int fontStyle = (bold.isSelected() ? Font.BOLD : 0)113 + (italic.isSelected() ? Font.ITALIC : 0);114 int fontSize = size.getItemAt(size.getSelectedIndex());115 Font font = new Font(fontFace, fontStyle, fontSize);116 sample.setFont(font);117 sample.repaint();118 }119 }

  

 

 

 

 

测试程序11

l 在elipse IDE中调试运行教材539页程序12-13、12-14,结合运行结果理解程序;

l 掌握定制布局管理器的用法。

l 记录示例代码阅读理解中存在的问题与疑惑。 

package circleLayout; 2  3 import java.awt.*; 4 import javax.swing.*; 5  6 /** 7  * @version 1.33 2015-06-12 8  * @author Cay Horstmann 9  */10 public class CircleLayoutTest11 {12    public static void main(String[] args)13    {14       EventQueue.invokeLater(() -> {15          JFrame frame = new CircleLayoutFrame();16          frame.setTitle("CircleLayoutTest");17          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);18          frame.setVisible(true);19       });20    }21 }

  

1 package circleLayout; 2  3 import javax.swing.*; 4  5 /** 6  * A frame that shows buttons arranged along a circle. 7  */ 8 public class CircleLayoutFrame extends JFrame 9 {10    public CircleLayoutFrame()11    {12       setLayout(new CircleLayout());13       add(new JButton("Yellow"));14       add(new JButton("Blue"));15       add(new JButton("Red"));16       add(new JButton("Green"));17       add(new JButton("Orange"));18       add(new JButton("Fuchsia"));19       add(new JButton("Indigo"));20       pack();21    }22 }

  

1 package circleLayout;  2   3 import java.awt.*;  4   5 /**  6  * A layout manager that lays out components along a circle.  7  */  8 public class CircleLayout implements LayoutManager  9 { 10    private int minWidth = 0; 11    private int minHeight = 0; 12    private int preferredWidth = 0; 13    private int preferredHeight = 0; 14    private boolean sizesSet = false; 15    private int maxComponentWidth = 0; 16    private int maxComponentHeight = 0; 17  18    public void addLayoutComponent(String name, Component comp) 19    { 20    } 21  22    public void removeLayoutComponent(Component comp) 23    { 24    } 25  26    public void setSizes(Container parent) 27    { 28       if (sizesSet) return; 29       int n = parent.getComponentCount(); 30  31       preferredWidth = 0; 32       preferredHeight = 0; 33       minWidth = 0; 34       minHeight = 0; 35       maxComponentWidth = 0; 36       maxComponentHeight = 0; 37  38       // compute the maximum component widths and heights 39       // and set the preferred size to the sum of the component sizes. 40       for (int i = 0; i < n; i++) 41       { 42          Component c = parent.getComponent(i); 43          if (c.isVisible()) 44          { 45             Dimension d = c.getPreferredSize(); 46             maxComponentWidth = Math.max(maxComponentWidth, d.width); 47             maxComponentHeight = Math.max(maxComponentHeight, d.height); 48             preferredWidth += d.width; 49             preferredHeight += d.height; 50          } 51       } 52       minWidth = preferredWidth / 2; 53       minHeight = preferredHeight / 2; 54       sizesSet = true; 55    } 56  57    public Dimension preferredLayoutSize(Container parent) 58    { 59       setSizes(parent); 60       Insets insets = parent.getInsets(); 61       int width = preferredWidth + insets.left + insets.right; 62       int height = preferredHeight + insets.top + insets.bottom; 63       return new Dimension(width, height); 64    } 65  66    public Dimension minimumLayoutSize(Container parent) 67    { 68       setSizes(parent); 69       Insets insets = parent.getInsets(); 70       int width = minWidth + insets.left + insets.right; 71       int height = minHeight + insets.top + insets.bottom; 72       return new Dimension(width, height); 73    } 74  75    public void layoutContainer(Container parent) 76    { 77       setSizes(parent); 78  79       // compute center of the circle 80  81       Insets insets = parent.getInsets(); 82       int containerWidth = parent.getSize().width - insets.left - insets.right; 83       int containerHeight = parent.getSize().height - insets.top - insets.bottom; 84  85       int xcenter = insets.left + containerWidth / 2; 86       int ycenter = insets.top + containerHeight / 2; 87  88       // compute radius of the circle 89  90       int xradius = (containerWidth - maxComponentWidth) / 2; 91       int yradius = (containerHeight - maxComponentHeight) / 2; 92       int radius = Math.min(xradius, yradius); 93  94       // lay out components along the circle 95  96       int n = parent.getComponentCount(); 97       for (int i = 0; i < n; i++) 98       { 99          Component c = parent.getComponent(i);100          if (c.isVisible())101          {102             double angle = 2 * Math.PI * i / n;103 104             // center point of component105             int x = xcenter + (int) (Math.cos(angle) * radius);106             int y = ycenter + (int) (Math.sin(angle) * radius);107 108             // move component so that its center is (x, y)109             // and its size is its preferred size110             Dimension d = c.getPreferredSize();111             c.setBounds(x - d.width / 2, y - d.height / 2, d.width, d.height);112          }113       }114    }115 }

   

  

 

  

 

测试程序12

l 在elipse IDE中调试运行教材544页程序12-15、12-16,结合运行结果理解程序;

l 掌握选项对话框的用法。

l 记录示例代码阅读理解中存在的问题与疑惑。

1 package optionDialog; 2  3 import java.awt.*; 4 import javax.swing.*; 5  6 /** 7  * @version 1.34 2015-06-12 8  * @author Cay Horstmann 9  */10 public class OptionDialogTest11 {12    public static void main(String[] args)13    {14       EventQueue.invokeLater(() -> {15          JFrame frame = new OptionDialogFrame();16          frame.setTitle("OptionDialogTest");17          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);18          frame.setVisible(true);19       });20    }21 }

  

1 package optionDialog; 2  3 import javax.swing.*; 4  5 /** 6  * A panel with radio buttons inside a titled border. 7  */ 8 public class ButtonPanel extends JPanel 9 {10    private ButtonGroup group;11 12    /**13     * Constructs a button panel.14     * @param title the title shown in the border15     * @param options an array of radio button labels16     */17    public ButtonPanel(String title, String... options)18    {19       setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title));20       setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));21       group = new ButtonGroup();22 23       // make one radio button for each option24       for (String option : options)25       {26          JRadioButton b = new JRadioButton(option);27          b.setActionCommand(option);28          add(b);29          group.add(b);30          b.setSelected(option == options[0]);31       }32    }33 34    /**35     * Gets the currently selected option.36     * @return the label of the currently selected radio button.37     */38    public String getSelection()39    {40       return group.getSelection().getActionCommand();41    }42 }

  

1 package optionDialog;  2   3 import java.awt.*;  4 import java.awt.event.*;  5 import java.awt.geom.*;  6 import java.util.*;  7 import javax.swing.*;  8   9 /** 10  * A frame that contains settings for selecting various option dialogs. 11  */ 12 public class OptionDialogFrame extends JFrame 13 { 14    private ButtonPanel typePanel; 15    private ButtonPanel messagePanel; 16    private ButtonPanel messageTypePanel; 17    private ButtonPanel optionTypePanel; 18    private ButtonPanel optionsPanel; 19    private ButtonPanel inputPanel; 20    private String messageString = "Message"; 21    private Icon messageIcon = new ImageIcon("blue-ball.gif"); 22    private Object messageObject = new Date(); 23    private Component messageComponent = new SampleComponent(); 24  25    public OptionDialogFrame() 26    { 27       JPanel gridPanel = new JPanel(); 28       gridPanel.setLayout(new GridLayout(2, 3)); 29  30       typePanel = new ButtonPanel("Type", "Message", "Confirm", "Option", "Input"); 31       messageTypePanel = new ButtonPanel("Message Type", "ERROR_MESSAGE", "INFORMATION_MESSAGE", 32             "WARNING_MESSAGE", "QUESTION_MESSAGE", "PLAIN_MESSAGE"); 33       messagePanel = new ButtonPanel("Message", "String", "Icon", "Component", "Other",  34             "Object[]"); 35       optionTypePanel = new ButtonPanel("Confirm", "DEFAULT_OPTION", "YES_NO_OPTION", 36             "YES_NO_CANCEL_OPTION", "OK_CANCEL_OPTION"); 37       optionsPanel = new ButtonPanel("Option", "String[]", "Icon[]", "Object[]"); 38       inputPanel = new ButtonPanel("Input", "Text field", "Combo box"); 39  40       gridPanel.add(typePanel); 41       gridPanel.add(messageTypePanel); 42       gridPanel.add(messagePanel); 43       gridPanel.add(optionTypePanel); 44       gridPanel.add(optionsPanel); 45       gridPanel.add(inputPanel); 46  47       // add a panel with a Show button 48  49       JPanel showPanel = new JPanel(); 50       JButton showButton = new JButton("Show"); 51       showButton.addActionListener(new ShowAction()); 52       showPanel.add(showButton); 53  54       add(gridPanel, BorderLayout.CENTER); 55       add(showPanel, BorderLayout.SOUTH); 56       pack(); 57    } 58  59    /** 60     * Gets the currently selected message. 61     * @return a string, icon, component, or object array, depending on the Message panel selection 62     */ 63    public Object getMessage() 64    { 65       String s = messagePanel.getSelection(); 66       if (s.equals("String")) return messageString; 67       else if (s.equals("Icon")) return messageIcon; 68       else if (s.equals("Component")) return messageComponent; 69       else if (s.equals("Object[]")) return new Object[] { messageString, messageIcon, 70             messageComponent, messageObject }; 71       else if (s.equals("Other")) return messageObject; 72       else return null; 73    } 74  75    /** 76     * Gets the currently selected options. 77     * @return an array of strings, icons, or objects, depending on the Option panel selection 78     */ 79    public Object[] getOptions() 80    { 81       String s = optionsPanel.getSelection(); 82       if (s.equals("String[]")) return new String[] { "Yellow", "Blue", "Red" }; 83       else if (s.equals("Icon[]")) return new Icon[] { new ImageIcon("yellow-ball.gif"), 84             new ImageIcon("blue-ball.gif"), new ImageIcon("red-ball.gif") }; 85       else if (s.equals("Object[]")) return new Object[] { messageString, messageIcon, 86             messageComponent, messageObject }; 87       else return null; 88    } 89  90    /** 91     * Gets the selected message or option type 92     * @param panel the Message Type or Confirm panel 93     * @return the selected XXX_MESSAGE or XXX_OPTION constant from the JOptionPane class 94     */ 95    public int getType(ButtonPanel panel) 96    { 97       String s = panel.getSelection(); 98       try 99       {100          return JOptionPane.class.getField(s).getInt(null);101       }102       catch (Exception e)103       {104          return -1;105       }106    }107 108    /**109     * The action listener for the Show button shows a Confirm, Input, Message, or Option dialog110     * depending on the Type panel selection.111     */112    private class ShowAction implements ActionListener113    {114       public void actionPerformed(ActionEvent event)115       {116          if (typePanel.getSelection().equals("Confirm")) JOptionPane.showConfirmDialog(117                OptionDialogFrame.this, getMessage(), "Title", getType(optionTypePanel),118                getType(messageTypePanel));119          else if (typePanel.getSelection().equals("Input"))120          {121             if (inputPanel.getSelection().equals("Text field")) JOptionPane.showInputDialog(122                   OptionDialogFrame.this, getMessage(), "Title", getType(messageTypePanel));123             else JOptionPane.showInputDialog(OptionDialogFrame.this, getMessage(), "Title",124                   getType(messageTypePanel), null, new String[] { "Yellow", "Blue", "Red" },125                   "Blue");126          }127          else if (typePanel.getSelection().equals("Message")) JOptionPane.showMessageDialog(128                OptionDialogFrame.this, getMessage(), "Title", getType(messageTypePanel));129          else if (typePanel.getSelection().equals("Option")) JOptionPane.showOptionDialog(130                OptionDialogFrame.this, getMessage(), "Title", getType(optionTypePanel),131                getType(messageTypePanel), null, getOptions(), getOptions()[0]);132       }133    }134 }135 136 /**137  * A component with a painted surface138  */139 140 class SampleComponent extends JComponent141 {142    public void paintComponent(Graphics g)143    {144       Graphics2D g2 = (Graphics2D) g;145       Rectangle2D rect = new Rectangle2D.Double(0, 0, getWidth() - 1, getHeight() - 1);146       g2.setPaint(Color.YELLOW);147       g2.fill(rect);148       g2.setPaint(Color.BLUE);149       g2.draw(rect);150    }151 152    public Dimension getPreferredSize()153    {154       return new Dimension(10, 10);155    }156 }

  

 

 

 

测试程序13

l 在elipse IDE中调试运行教材552页程序12-17、12-18,结合运行结果理解程序;

l 掌握对话框的创建方法;

l 记录示例代码阅读理解中存在的问题与疑惑。

package dialog;import java.awt.*;import javax.swing.*;/** * @version 1.34 2012-06-12 * @author Cay Horstmann */public class DialogTest{   public static void main(String[] args)   {      EventQueue.invokeLater(() -> {         JFrame frame = new DialogFrame();         frame.setTitle("DialogTest");         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         frame.setVisible(true);      });   }}

  

package dialog;import javax.swing.JFrame;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;/** * A frame with a menu whose File->About action shows a dialog. */public class DialogFrame extends JFrame{   private static final int DEFAULT_WIDTH = 300;   private static final int DEFAULT_HEIGHT = 200;   private AboutDialog dialog;   public DialogFrame()   {      setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);      // Construct a File menu.      JMenuBar menuBar = new JMenuBar();//菜单栏的实现      setJMenuBar(menuBar);//设置此窗体的菜单栏      JMenu fileMenu = new JMenu("File");//菜单的该实现是一个包含 JMenuItem 的弹出窗口,用户选择 JMenuBar 上的项时会显示该 JMenuItem。      menuBar.add(fileMenu);//将指定的菜单追加到菜单栏的末尾      // Add About and Exit menu items.      // The About item shows the About dialog.      JMenuItem aboutItem = new JMenuItem("About");//菜单中的项的实现      aboutItem.addActionListener(event -> {         if (dialog == null) // first time            dialog = new AboutDialog(DialogFrame.this);         dialog.setVisible(true); // 设置是否可见      });      fileMenu.add(aboutItem);//将某个菜单项追加到此菜单的末尾。返回添加的菜单项      // The Exit item exits the program.      JMenuItem exitItem = new JMenuItem("Exit");      exitItem.addActionListener(event -> System.exit(0));      fileMenu.add(exitItem);   }}

  

1 package dialog; 2  3 import java.awt.BorderLayout; 4  5 import javax.swing.JButton; 6 import javax.swing.JDialog; 7 import javax.swing.JFrame; 8 import javax.swing.JLabel; 9 import javax.swing.JPanel;10 11 /**12  * A sample modal dialog that displays a message and waits for the user to click the OK button.13  */14 public class AboutDialog extends JDialog15 {//创建一个具有指定标题,所有者Farmer和模式的对话框。如果owner为null,则一个共享的,隐藏的窗体将设置为该对话框的所有者。16    public AboutDialog(JFrame owner)17    {18       super(owner, "About DialogTest", true);19 20       // add HTML label to center//将指定的组件添加到此内容的尾部21 22       add(23             new JLabel(24                   "

Core Java


By Cay Horstmann"),25 BorderLayout.CENTER);26 27 // OK button closes the dialog28 29 JButton ok = new JButton("OK");//创建一个新的按钮30 ok.addActionListener(event -> setVisible(false));31 32 // add OK button to southern border33 34 JPanel panel = new JPanel();35 panel.add(ok);36 add(panel, BorderLayout.SOUTH);//边框布局,显示在下边37 38 pack();39 }40 }

  

 

 

测试程序14

l 在elipse IDE中调试运行教材556页程序12-19、12-20,结合运行结果理解程序;

l 掌握对话框的数据交换用法;

l 记录示例代码阅读理解中存在的问题与疑惑。

1 package dataExchange; 2  3 import java.awt.*; 4 import javax.swing.*; 5  6 /** 7  * @version 1.34 2015-06-12 8  * @author Cay Horstmann 9  */10 public class DataExchangeTest11 {12    public static void main(String[] args)13    {14       EventQueue.invokeLater(() -> {15          JFrame frame = new DataExchangeFrame();16          frame.setTitle("DataExchangeTest");17          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);18          frame.setVisible(true);19       });20    }21 }

  

1 package dataExchange; 2  3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6  7 /** 8  * A frame with a menu whose File->Connect action shows a password dialog. 9  */10 public class DataExchangeFrame extends JFrame11 {12    public static final int TEXT_ROWS = 20;13    public static final int TEXT_COLUMNS = 40;14    private PasswordChooser dialog = null;15    private JTextArea textArea;16 17    public DataExchangeFrame()18    {19       // construct a File menu20 21       JMenuBar mbar = new JMenuBar();22       setJMenuBar(mbar);23       JMenu fileMenu = new JMenu("File");24       mbar.add(fileMenu);25 26       // add Connect and Exit menu items27 28       JMenuItem connectItem = new JMenuItem("Connect");29       connectItem.addActionListener(new ConnectAction());30       fileMenu.add(connectItem);31 32       // The Exit item exits the program33 34       JMenuItem exitItem = new JMenuItem("Exit");35       exitItem.addActionListener(event -> System.exit(0));36       fileMenu.add(exitItem);37 38       textArea = new JTextArea(TEXT_ROWS, TEXT_COLUMNS);39       add(new JScrollPane(textArea), BorderLayout.CENTER);40       pack();41    }42 43    /**44     * The Connect action pops up the password dialog.45     */46    private class ConnectAction implements ActionListener47    {48       public void actionPerformed(ActionEvent event)49       {50          // if first time, construct dialog51 52          if (dialog == null) dialog = new PasswordChooser();53 54          // set default values55          dialog.setUser(new User("yourname", null));56 57          // pop up dialog58          if (dialog.showDialog(DataExchangeFrame.this, "Connect"))59          {60             // if accepted, retrieve user input61             User u = dialog.getUser();62             textArea.append("user name = " + u.getName() + ", password = "63                   + (new String(u.getPassword())) + "\n");64          }65       }66    }67 }

  

1 package dataExchange;  2   3 import java.awt.BorderLayout;  4 import java.awt.Component;  5 import java.awt.Frame;  6 import java.awt.GridLayout;  7   8 import javax.swing.JButton;  9 import javax.swing.JDialog; 10 import javax.swing.JLabel; 11 import javax.swing.JPanel; 12 import javax.swing.JPasswordField; 13 import javax.swing.JTextField; 14 import javax.swing.SwingUtilities; 15  16 /** 17  * A password chooser that is shown inside a dialog 18  */ 19 public class PasswordChooser extends JPanel 20 { 21    private JTextField username; 22    private JPasswordField password; 23    private JButton okButton; 24    private boolean ok; 25    private JDialog dialog; 26  27    public PasswordChooser() 28    { 29       setLayout(new BorderLayout()); 30  31       // construct a panel with user name and password fields 32  33       JPanel panel = new JPanel(); 34       panel.setLayout(new GridLayout(2, 2)); 35       panel.add(new JLabel("User name:")); 36       panel.add(username = new JTextField("")); 37       panel.add(new JLabel("Password:")); 38       panel.add(password = new JPasswordField("")); 39       add(panel, BorderLayout.CENTER); 40  41       // create Ok and Cancel buttons that terminate the dialog 42  43       okButton = new JButton("Ok"); 44       okButton.addActionListener(event -> { 45          ok = true; 46          dialog.setVisible(false); 47       }); 48  49       JButton cancelButton = new JButton("Cancel"); 50       cancelButton.addActionListener(event -> dialog.setVisible(false)); 51  52       // add buttons to southern border 53  54       JPanel buttonPanel = new JPanel(); 55       buttonPanel.add(okButton); 56       buttonPanel.add(cancelButton); 57       add(buttonPanel, BorderLayout.SOUTH); 58    } 59  60    /** 61     * Sets the dialog defaults. 62     * @param u the default user information 63     */ 64    public void setUser(User u) 65    { 66       username.setText(u.getName()); 67    } 68  69    /** 70     * Gets the dialog entries. 71     * @return a User object whose state represents the dialog entries 72     */ 73    public User getUser() 74    { 75       return new User(username.getText(), password.getPassword()); 76    } 77  78    /** 79     * Show the chooser panel in a dialog 80     * @param parent a component in the owner frame or null 81     * @param title the dialog window title 82     */ 83    public boolean showDialog(Component parent, String title) 84    { 85       ok = false; 86  87       // locate the owner frame 88  89       Frame owner = null; 90       if (parent instanceof Frame) 91          owner = (Frame) parent; 92       else 93          owner = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, parent); 94  95       // if first time, or if owner has changed, make new dialog 96  97       if (dialog == null || dialog.getOwner() != owner) 98       { 99          dialog = new JDialog(owner, true);100          dialog.add(this);101          dialog.getRootPane().setDefaultButton(okButton);102          dialog.pack();103       }104 105       // set title and show dialog106 107       dialog.setTitle(title);108       dialog.setVisible(true);109       return ok;110    }111 }

  

1 package dataExchange; 2  3 /** 4  * A user has a name and password. For security reasons, the password is stored as a char[], not a 5  * String. 6  */ 7 public class User 8 { 9    private String name;10    private char[] password;11 12    public User(String aName, char[] aPassword)13    {14       name = aName;15       password = aPassword;16    }17 18    public String getName()19    {20       return name;21    }22 23    public char[] getPassword()24    {25       return password;26    }27 28    public void setName(String aName)29    {30       name = aName;31    }32 33    public void setPassword(char[] aPassword)34    {35       password = aPassword;36    }37 }

  

 

测试程序15

l 在elipse IDE中调试运行教材556页程序12-21、12-2212-23,结合程序运行结果理解程序;

l 掌握文件对话框的用法;

l 记录示例代码阅读理解中存在的问题与疑惑。

package fileChooser;import java.io.*;import javax.swing.*;import javax.swing.filechooser.*;import javax.swing.filechooser.FileFilter;/** * A file view that displays an icon for all files that match a file filter. */public class FileIconView extends FileView {    private FileFilter filter;    private Icon icon;    /**     * Constructs a FileIconView.     *      * @param aFilter a file filter--all files that this filter accepts will be     *                shown with the icon.     * @param         anIcon--the icon shown with all accepted files.     */    public FileIconView(FileFilter aFilter, Icon anIcon) {        filter = aFilter;        icon = anIcon;    }    public Icon getIcon(File f) {        if (!f.isDirectory() && filter.accept(f))            return icon;        else            return null;    }}

  

package fileChooser;import java.awt.*;import java.io.*;import javax.swing.*;/** * A file chooser accessory that previews images. */public class ImagePreviewer extends JLabel {    /**     * Constructs an ImagePreviewer.     *      * @param chooser the file chooser whose property changes trigger an image     *                change in this previewer     */    public ImagePreviewer(JFileChooser chooser) {        setPreferredSize(new Dimension(100, 100));        setBorder(BorderFactory.createEtchedBorder());        chooser.addPropertyChangeListener(event -> {            if (event.getPropertyName() == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY) {                // the user has selected a new file                File f = (File) event.getNewValue();                if (f == null) {                    setIcon(null);                    return;                }                // read the image into an icon                ImageIcon icon = new ImageIcon(f.getPath());                // if the icon is too large to fit, scale it                if (icon.getIconWidth() > getWidth())                    icon = new ImageIcon(icon.getImage().getScaledInstance(getWidth(), -1, Image.SCALE_DEFAULT));                setIcon(icon);            }        });    }}

  

package fileChooser;import java.io.*;import javax.swing.*;import javax.swing.filechooser.*;import javax.swing.filechooser.FileFilter;/** * A frame that has a menu for loading an image and a display area for the * loaded image. */public class ImageViewerFrame extends JFrame {    private static final int DEFAULT_WIDTH = 300;    private static final int DEFAULT_HEIGHT = 400;    private JLabel label;    private JFileChooser chooser;    public ImageViewerFrame() {        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);        // set up menu bar        JMenuBar menuBar = new JMenuBar();        setJMenuBar(menuBar);        JMenu menu = new JMenu("File");        menuBar.add(menu);        JMenuItem openItem = new JMenuItem("Open");        menu.add(openItem);        openItem.addActionListener(event -> {            chooser.setCurrentDirectory(new File("."));            // show file chooser dialog            int result = chooser.showOpenDialog(ImageViewerFrame.this);            // if image file accepted, set it as icon of the label            if (result == JFileChooser.APPROVE_OPTION) {                String name = chooser.getSelectedFile().getPath();                label.setIcon(new ImageIcon(name));                pack();            }        });        JMenuItem exitItem = new JMenuItem("Exit");        menu.add(exitItem);        exitItem.addActionListener(event -> System.exit(0));        // use a label to display the images        label = new JLabel();        add(label);        // set up file chooser        chooser = new JFileChooser();        // accept all image files ending with .jpg, .jpeg, .gif        FileFilter filter = new FileNameExtensionFilter("Image files", "jpg", "jpeg", "gif");        chooser.setFileFilter(filter);        chooser.setAccessory(new ImagePreviewer(chooser));        chooser.setFileView(new FileIconView(filter, new ImageIcon("palette.gif")));    }}

  

 

测试程序16

l 在elipse IDE中调试运行教材570页程序12-24,结合运行结果理解程序;

l 了解颜色选择器的用法。

l 记录示例代码阅读理解中存在的问题与疑惑。

1 package colorChooser; 2  3 import java.awt.*; 4 import javax.swing.*; 5  6 /** 7  * @version 1.04 2015-06-12 8  * @author Cay Horstmann 9  */10 public class ColorChooserTest11 {12    public static void main(String[] args)13    {14       EventQueue.invokeLater(() -> {15          JFrame frame = new ColorChooserFrame();16          frame.setTitle("ColorChooserTest");17          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);18          frame.setVisible(true);19       });20    }21 }

  

1 package colorChooser; 2  3 import java.awt.Color; 4 import java.awt.Frame; 5 import java.awt.event.ActionEvent; 6 import java.awt.event.ActionListener; 7  8 import javax.swing.JButton; 9 import javax.swing.JColorChooser;10 import javax.swing.JDialog;11 import javax.swing.JPanel;12 13 /**14  * A panel with buttons to pop up three types of color choosers15  */16 public class ColorChooserPanel extends JPanel17 {18    public ColorChooserPanel()19    {20       JButton modalButton = new JButton("Modal");21       modalButton.addActionListener(new ModalListener());22       add(modalButton);23 24       JButton modelessButton = new JButton("Modeless");25       modelessButton.addActionListener(new ModelessListener());26       add(modelessButton);27 28       JButton immediateButton = new JButton("Immediate");29       immediateButton.addActionListener(new ImmediateListener());30       add(immediateButton);31    }32 33    /**34     * This listener pops up a modal color chooser35     */36    private class ModalListener implements ActionListener37    {38       public void actionPerformed(ActionEvent event)39       {40          Color defaultColor = getBackground();41          Color selected = JColorChooser.showDialog(ColorChooserPanel.this, "Set background",42                defaultColor);43          if (selected != null) setBackground(selected);44       }45    }46 47    /**48     * This listener pops up a modeless color chooser. The panel color is changed when the user49     * clicks the OK button.50     */51    private class ModelessListener implements ActionListener52    {53       private JDialog dialog;54       private JColorChooser chooser;55 56       public ModelessListener()57       {58          chooser = new JColorChooser();59          dialog = JColorChooser.createDialog(ColorChooserPanel.this, "Background Color",60                false /* not modal */, chooser, 61                event -> setBackground(chooser.getColor()), 62                null /* no Cancel button listener */);63       }64 65       public void actionPerformed(ActionEvent event)66       {67          chooser.setColor(getBackground());68          dialog.setVisible(true);69       }70    }71 72    /**73     * This listener pops up a modeless color chooser. The panel color is changed immediately when74     * the user picks a new color.75     */76    private class ImmediateListener implements ActionListener77    {78       private JDialog dialog;79       private JColorChooser chooser;80 81       public ImmediateListener()82       {83          chooser = new JColorChooser();84          chooser.getSelectionModel().addChangeListener(85                event -> setBackground(chooser.getColor()));86 87          dialog = new JDialog((Frame) null, false /* not modal */);88          dialog.add(chooser);89          dialog.pack();90       }91 92       public void actionPerformed(ActionEvent event)93       {94          chooser.setColor(getBackground());95          dialog.setVisible(true);96       }97    }98 }

  

1 package colorChooser; 2  3 import javax.swing.*; 4  5 /** 6  * A frame with a color chooser panel 7  */ 8 public class ColorChooserFrame extends JFrame 9 {10    private static final int DEFAULT_WIDTH = 300;11    private static final int DEFAULT_HEIGHT = 200;12 13    public ColorChooserFrame()14    {      15       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);16 17       // add color chooser panel to frame18 19       ColorChooserPanel panel = new ColorChooserPanel();20       add(panel);21    }22 }

  

 

实验总结:在调用超类构造器时,需要提供拥有者框架,对框标题集模式特征。

拥有者框架控制对话框的显示位置,如果将拥有者标识为null,那么对话框将由一个隐藏框架所拥有。

本次实例代码中,之建立了一次对话框,无论何时用户点击About按钮,都可以重要实验它。

 

转载于:https://www.cnblogs.com/baimaciren/p/10040013.html

转载地址:https://blog.csdn.net/weixin_34228387/article/details/93195364 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:javascript判断两个块级元素是否重叠
下一篇:C#垃圾回收机制

发表评论

最新留言

不错!
[***.144.177.141]2024年04月05日 12时50分23秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章