zoukankan      html  css  js  c++  java
  • 201871010133-赵永军《面向对象程序设计(java)》第十五周学习总结

    201871010133-赵永军《面向对象程序设计(java)》第十五周学习总结

    项目 内容
    这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/
    这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p/11995615.html
    作业学习目标

    (1) 掌握菜单组件用途及常用API;

    (2) 掌握对话框组件用途及常用API;

    (3) 学习设计简单应用程序的GUI。

     

     

     

     

     

     

     

     

     

     

    第一部分:理论部分

    一、 菜单

      位于窗口顶部的菜单栏(menu bar)包括了下拉菜单的名字。点击一个名字就可以打开包含菜单项和子菜单的菜单。  

      当用户点击菜单项时,所有的菜单都会被关闭并且将一条消息发送给程序。

    1、菜单      

        创建菜单栏:             

            JMenuBar menuBar=new JMenuBar()      

        将菜单栏添加到框架:            

             frame.setJMenuBar();      

        为每个菜单建立一个菜单对象:

                JMenu editMenu=new JMenu("Edit");
          将顶层菜单添加到菜单栏中:
                menuBar.add(editMenu);
          向菜单对象添加菜单项,分隔符和子菜单:
                JMenuItem pasteItem=new JMenuItem("Paste");
                editMenu.add(pasteItem);
                editMenu.addSeparator();
                JMenu optionsMenu=...;
                editMenu.add(optionsMenu);
    2、菜单项中的图标
        JMenuItem类扩展了AbstractButton类。与按钮一样,菜单可以包含文本标签、图标,也可以两者都包含。
        既可以利用JMenuItem(String,Icon)或者JMenuItem(Icon)构造器为菜单指定一个图标,
        也可以利用JmenuItem类中的setIcon方法(继承自AbstractButton类)指定一个图标
    3、复选框和单选按钮菜单项
        复选框和单选按钮菜单项在文本旁边显示了一个复选框或一个单选按钮。
        当用户选择一个菜单框时,菜单项就会自动地在选择和未选择间进行切换
    4、弹出菜单
        弹出菜单(pop-up menu)是不固定在菜单栏中随处浮动的菜单
        创建一个弹出菜单和创建一个常规菜单方法类似,只是弹出菜单没有标题
        当用户点击某个鼠标键时弹出菜单。这就是所谓的弹出式触发器(pop-up trigger)。
        在Window或者Linux中,弹出式触发器是鼠标右键。
    5、快捷键和加速器
        可以通过在菜单项的构造器中指定一个快捷字母来为菜单项设置快捷键
        快捷键会自动地显示在菜单项中,并带有一条下划线
        如果有一个Action对象,就可以把快捷键作为Action.MNEMONIC_KEY的键值添加到对象中。
            cutAction.putValue(Action.MENMONIC_KEY,new Integer('A'));
        只能在菜单项的构造器中设定快捷键子母,而不是在菜单构造器中。如果想为菜单设置快捷键,需要调用setMnemonic方法:
            JMenu helpMenu=new JMenu("helo");
            helpMenu.setMnemonic('H');
        可以同时按下ALT键和菜单的快捷键来实现在菜单栏中选择一个顶层菜单的操作。
        可以使用快捷键从当前打开的菜单中选择一个子菜单或者菜单项。而加速器是在不打开菜单的情况下选择菜单项的快捷键。
        当用户按下加速器组合键时,就会自动地选择相应的菜单项,同时激活一个动作事件,这与手动地选择这个菜单项一样。
        加速器只能关联到菜单项上,不能关联到菜单上。加速器键并不实际打开菜单。它将直接地激活菜单关联的动作事件
    6、启用和禁用菜单项
        启动和禁用菜单项有两种策略。每次环境发生变化就对相关的菜单项或动作调用setEnabled。
        另一种方式是在现实菜单之前禁用这些菜单栏
    7、工具提示
        工具栏有个缺点就是用户常常需要猜测按钮上小图标按钮的含义,为解决这个问题,用户界面设计了工具提示。
        当光标停留在某个按钮上片刻时,工具提示就会被激活。
        工具提示文本显示在一个有颜色的矩形里。当用户移开鼠标时,工具提示就会自动地消失
    二、对话框
    1、对话框
        与大多数的窗口系统一样,AWT也分为模式对话框和无模式对话框。
        模式对话框是指在结束对它的处理之前,不允许用户与应用程序的其余窗口进行交互。
        模式对话框主要用于在程序继续运行之前获取用户提供的信息。
        无模式对话框是指允许用户同时在对话框和应用程序的其他窗口中输入信息。
       
        使用无模式对话框的最好例子就是工具栏。工具栏可以停靠在任何地方,
        并且用户可以在需要的时候,同时与应用程序窗口和工具栏进行交互。
        
        简单信息模式对话框:
        Swing有一个很容易使用的类JOptionPane,它可以弹出一个简单的对话框,而不必编写任何对话框的相关代码。
    2、选项对话框
        Swing有一套简单的对话框,用于获取用户的一些简单信息。
        JOptionPane有4个用于显示这些对话框的静态方法:
            showMessageDialog:显示一条消息并等待用户点击OK
            showConfirmDialog:显示一条消息并等待用户确认(与OK/Cancel类似)
            showOptionDialog:显示一条消息并获得用户在一组选项中的选择
            showInputDialog:显示一条消息并获得用户输入的一行文本
        输入对话框有一个用于接收用户输入的额外组件。它既可能是用于输入任何字符串的文本域,也可能是允许用户从中选择的组合框
        每个对话框类型都有一个方法,可以用来提供自己的图标,以替代原来的图标。
        可以为每个对话框类型指定一条消息,如字符串、图标、用户界面组件,或其他类型的对象
        唯一底部的按钮取决于对话框类型和选项类型
        使用showOptionDialog可以指定任意的选项
    3、创建对话框
        要想创建一个对话框,需要从JDialog派生一个类,具体过程:
            1) 在对话框构造器中,调用超类JDialog的构造器。
            2) 添加对话框的用户界面组件。
            3) 添加事件处理器。
            4) 设置对话框的大小。
        在调用超类构造器时,需要提供拥有者框架(owner frame)、对话框标题及模式特征。
        拥有者框架控制对话框的显示位置,如果将拥有者标识为null,那么对话框将由一个隐藏框架所拥有。
        模式特征将指定对话框处于显示状态时,应用程序中其他窗口是否被锁住。
        无模式对话框不会锁住其他窗口,而有模式对话框将锁住应用程序中的所有其他窗口(除对话框的子窗口外)。
        用户经常使用的工具栏就是无模式对话框,另一方面,如果想强迫用户在继续操作之前提供一些必要的信息就应该使用模式对话框。
        
    4、文件对话框
        一个好的文件对话框可以显示文件和目录,可以让用户浏览文件系统。
        Swing中提供了JFileChooser类,它可以显示一个文本对话框,其外观与本地应用程序中使用的文件对话框基本一样。
        JFileChooser是一个模式对话框
        
        建立文件对话框并且获取用户选择信息的步骤如下:
            1 建立一个JFileChooser对象。与JDialog类的构造器不同,它不需要指定父组件。允许在多个框架中重用一个文件选择器。
            2 调用setCurrentDirectory方法设置当前目录。
            3 如果有一个想要作为用户选择的默认文件名,可以使用setSelectedFile方法进行指定。
            4 如果允许用户在对话框中选择多个文件,需要调用setMultiSelectionEnabled方法
            5 如果想让对话框仅显示某一种类型的文件,需要设置文件过滤器。
            6 在默认情况下,用户在文件选择器中只能选择文件。如果希望选择目录,需要调用setFileSelectionMode方法。
                参数值为:JFileChooser.FILES_ONLY(默认值),JFileChooser.DIRECTORIES_ONLY或者JFileChooser.FILES_AND_DIRECTORIES。
            7 调用showOpenDialog或者showSaveDialog方法显示对话框。
            8 调用getSelectedFile()或者getSelectedFiles()方法获取用户选择的一个或多个文件。

    三、常用API

    ①java.lang.reflect.AccessibleObject
      void setAccessible(boolean flag)
      为反射对象设置可访问标志。flag为true表明屏蔽Java语言的访问检查,使得对象的私有属性也可以被查询和设置。

      boolean isAccessible()
      返回反射对象的可访问标志的值。

      static void setAccessible(AccessibleObject[] array,boolean flag)
      是一种设置对象数组可访问标志的快捷方法。

    ②java.lang.Class
      Field getField(String name)
      Field getField()
      返回指定名称的公有域,或包含所有域的数组。

      Field getDeclaredField(String name)
      Field getDeclaredFields()
      返回类中声明的给定名称的域,或者包含声明的全部域的数组。

    ③java.lang.reflect.Field
      Object get(Object obj)
      返回obj对象中用Field对象表示的域值。

      void set(Object obj,Object newValue)
      用一个新值设置Obj对象中Field对象表示的域。

    2、实验内容和步骤

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

    测试程序1

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

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

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

    实验程序如下:

     1 package menu;
     2 
     3 import java.awt.*;
     4 import javax.swing.*;
     5 
     6 /**
     7  * @version 1.24 2012-06-12
     8  * @author Cay Horstmann
     9  */
    10 public class MenuTest
    11 {
    12    public static void main(String[] args)
    13    {
    14       EventQueue.invokeLater(() -> {
    15          JFrame frame = new MenuFrame();
    16          frame.setTitle("MenuTest");
    17          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    18          frame.setVisible(true);
    19       });
    20    }
    21 }
    View Code
      1 import java.awt.event.*;
      2 import javax.swing.*;
      3 
      4 /**
      5  * 一个带有示例菜单栏的框架。
      6  */
      7 public class MenuFrame extends JFrame
      8 {
      9    private static final int DEFAULT_WIDTH = 300;
     10    private static final int DEFAULT_HEIGHT = 200;
     11    private Action saveAction;
     12    private Action saveAsAction;
     13    private JCheckBoxMenuItem readonlyItem;
     14    private JPopupMenu popup;
     15 
     16    /**
     17     * 将动作名称打印到Studio.OUT的示例动作。
     18     */
     19    class TestAction extends AbstractAction
     20    {
     21       public TestAction(String name)
     22       {
     23          super(name);
     24       }
     25 
     26       public void actionPerformed(ActionEvent event)
     27       {
     28          System.out.println(getValue(Action.NAME) + " selected.");
     29       }
     30    }
     31 
     32    public MenuFrame()
     33    {
     34       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
     35 
     36       JMenu fileMenu = new JMenu("File");
     37       fileMenu.add(new TestAction("New"));
     38 
     39       // 演示加速器
     40       JMenuItem openItem = fileMenu.add(new TestAction("Open"));
     41       openItem.setAccelerator(KeyStroke.getKeyStroke("ctrl O"));
     42 
     43       fileMenu.addSeparator();
     44 
     45       saveAction = new TestAction("Save");
     46       JMenuItem saveItem = fileMenu.add(saveAction);
     47       saveItem.setAccelerator(KeyStroke.getKeyStroke("ctrl S"));
     48 
     49       saveAsAction = new TestAction("Save As");
     50       fileMenu.add(saveAsAction);
     51       fileMenu.addSeparator();
     52 
     53       fileMenu.add(new AbstractAction("Exit")
     54          {
     55             public void actionPerformed(ActionEvent event)
     56             {
     57                System.exit(0);
     58             }
     59          });
     60 
     61       // 演示复选框和单选按钮菜单
     62 
     63       readonlyItem = new JCheckBoxMenuItem("Read-only");
     64       readonlyItem.addActionListener(new ActionListener()
     65          {
     66             public void actionPerformed(ActionEvent event)
     67             {
     68                boolean saveOk = !readonlyItem.isSelected();
     69                saveAction.setEnabled(saveOk);
     70                saveAsAction.setEnabled(saveOk);
     71             }
     72          });
     73 
     74       ButtonGroup group = new ButtonGroup();
     75 
     76       JRadioButtonMenuItem insertItem = new JRadioButtonMenuItem("Insert");
     77       insertItem.setSelected(true);
     78       JRadioButtonMenuItem overtypeItem = new JRadioButtonMenuItem("Overtype");
     79 
     80       group.add(insertItem);
     81       group.add(overtypeItem);
     82 
     83       // 演示图标
     84 
     85       Action cutAction = new TestAction("Cut");
     86       cutAction.putValue(Action.SMALL_ICON, new ImageIcon("cut.gif"));
     87       Action copyAction = new TestAction("Copy");
     88       copyAction.putValue(Action.SMALL_ICON, new ImageIcon("copy.gif"));
     89       Action pasteAction = new TestAction("Paste");
     90       pasteAction.putValue(Action.SMALL_ICON, new ImageIcon("paste.gif"));
     91 
     92       JMenu editMenu = new JMenu("Edit");
     93       editMenu.add(cutAction);
     94       editMenu.add(copyAction);
     95       editMenu.add(pasteAction);
     96 
     97       // 演示嵌套菜单
     98 
     99       JMenu optionMenu = new JMenu("Options");
    100 
    101       optionMenu.add(readonlyItem);
    102       optionMenu.addSeparator();
    103       optionMenu.add(insertItem);
    104       optionMenu.add(overtypeItem);
    105 
    106       editMenu.addSeparator();
    107       editMenu.add(optionMenu);
    108 
    109       // 助记符演示
    110 
    111       JMenu helpMenu = new JMenu("Help");
    112       helpMenu.setMnemonic('H');
    113 
    114       JMenuItem indexItem = new JMenuItem("Index");
    115       indexItem.setMnemonic('I');
    116       helpMenu.add(indexItem);
    117 
    118       // 还可以将助记键添加到动作中。
    119       Action aboutAction = new TestAction("About");
    120       aboutAction.putValue(Action.MNEMONIC_KEY, new Integer('A'));
    121       helpMenu.add(aboutAction);
    122       
    123       // 将所有顶级菜单添加到菜单栏
    124 
    125       JMenuBar menuBar = new JMenuBar();
    126       setJMenuBar(menuBar);
    127 
    128       menuBar.add(fileMenu);
    129       menuBar.add(editMenu);
    130       menuBar.add(helpMenu);
    131 
    132       // 演示弹出窗口
    133 
    134       popup = new JPopupMenu();
    135       popup.add(cutAction);
    136       popup.add(copyAction);
    137       popup.add(pasteAction);
    138 
    139       JPanel panel = new JPanel();
    140       panel.setComponentPopupMenu(popup);
    141       add(panel);
    142    }
    143 }
    View Code

    实验结果如下:

    测试程序2

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

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

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

     实验程序如下:

     1 package toolBar;
     2 
     3 import java.awt.*;
     4 import javax.swing.*;
     5 
     6 /**
     7  * @version 1.14 2015-06-12
     8  * @author Cay Horstmann
     9  */
    10 public class ToolBarTest
    11 {
    12    public static void main(String[] args)
    13    {
    14       EventQueue.invokeLater(() -> {
    15          ToolBarFrame frame = new ToolBarFrame();
    16          frame.setTitle("ToolBarTest");
    17          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    18          frame.setVisible(true);
    19       });
    20    }
    21 }
    View Code
     1 package toolBar;
     2 
     3 import java.awt.*;
     4 import java.awt.event.*;
     5 import javax.swing.*;
     6 
     7 /**
     8  * 带有工具栏和菜单的框架,用于颜色变化。
     9  */
    10 public class ToolBarFrame extends JFrame
    11 {
    12    private static final int DEFAULT_WIDTH = 300;
    13    private static final int DEFAULT_HEIGHT = 200;
    14    private JPanel panel;
    15 
    16    public ToolBarFrame()
    17    {
    18       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
    19 
    20       // 添加颜色变化面板
    21 
    22       panel = new JPanel();
    23       add(panel, BorderLayout.CENTER);
    24 
    25       // 设置动作
    26       Action blueAction = new ColorAction("Blue", new ImageIcon("blue-ball.gif"), Color.BLUE);
    27       Action yellowAction = new ColorAction("Yellow", new ImageIcon("yellow-ball.gif"),
    28             Color.YELLOW);
    29       Action redAction = new ColorAction("Red", new ImageIcon("red-ball.gif"), Color.RED);
    30 
    31       Action exitAction = new AbstractAction("Exit", new ImageIcon("exit.gif"))
    32          {
    33             public void actionPerformed(ActionEvent event)
    34             {
    35                System.exit(0);
    36             }
    37          };
    38       exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit");
    39 
    40       // 填充工具栏
    41 
    42       JToolBar bar = new JToolBar();
    43       bar.add(blueAction);
    44       bar.add(yellowAction);
    45       bar.add(redAction);
    46       bar.addSeparator();
    47       bar.add(exitAction);
    48       add(bar, BorderLayout.NORTH);
    49 
    50       // 填充菜单
    51 
    52       JMenu menu = new JMenu("Color");
    53       menu.add(yellowAction);
    54       menu.add(blueAction);
    55       menu.add(redAction);
    56       menu.add(exitAction);
    57       JMenuBar menuBar = new JMenuBar();
    58       menuBar.add(menu);
    59       setJMenuBar(menuBar);
    60    }
    61 
    62    /**
    63     * 颜色动作将帧的背景设置为给定的颜色。
    64     */
    65    class ColorAction extends AbstractAction
    66    {
    67       public ColorAction(String name, Icon icon, Color c)
    68       {
    69          putValue(Action.NAME, name);
    70          putValue(Action.SMALL_ICON, icon);
    71          putValue(Action.SHORT_DESCRIPTION, name + " background");
    72          putValue("Color", c);
    73       }
    74 
    75       public void actionPerformed(ActionEvent event)
    76       {
    77          Color c = (Color) getValue("Color");
    78          panel.setBackground(c);
    79       }
    80    }
    81 }
    View Code

    实验结果如下:

    测试程序3

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

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

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

     实验程序如下:

     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 OptionDialogTest
    11 {
    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 }
    View Code
     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 OptionDialogTest
    11 {
    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 }
    View Code
     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 border
    15     * @param options an array of radio button labels
    16     */
    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 option
    24       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 }
    View Code
      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 dialog
    110     * depending on the Type panel selection.
    111     */
    112    private class ShowAction implements ActionListener
    113    {
    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 surface
    138  */
    139 
    140 class SampleComponent extends JComponent
    141 {
    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 }
    View Code

    实验结果如下:

    测试程序4

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

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

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

    实验程序如下:

     1 package dialog;
     2 
     3 import java.awt.*;
     4 import javax.swing.*;
     5 
     6 /**
     7  * @version 1.34 2012-06-12
     8  * @author Cay Horstmann
     9  */
    10 public class DialogTest
    11 {
    12    public static void main(String[] args)
    13    {
    14       EventQueue.invokeLater(() -> {
    15          JFrame frame = new DialogFrame();
    16          frame.setTitle("DialogTest");
    17          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    18          frame.setVisible(true);
    19       });
    20    }
    21 }
    View Code
     1 package dialog;
     2 
     3 import javax.swing.JFrame;
     4 import javax.swing.JMenu;
     5 import javax.swing.JMenuBar;
     6 import javax.swing.JMenuItem;
     7 
     8 /**
     9  * A frame with a menu whose File->About action shows a dialog.
    10  */
    11 public class DialogFrame extends JFrame
    12 {
    13    private static final int DEFAULT_WIDTH = 300;
    14    private static final int DEFAULT_HEIGHT = 200;
    15    private AboutDialog dialog;
    16 
    17    public DialogFrame()
    18    {
    19       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
    20 
    21       // Construct a File menu.
    22 
    23       JMenuBar menuBar = new JMenuBar();
    24       setJMenuBar(menuBar);
    25       JMenu fileMenu = new JMenu("File");
    26       menuBar.add(fileMenu);
    27 
    28       // Add About and Exit menu items.
    29 
    30       // The About item shows the About dialog.
    31 
    32       JMenuItem aboutItem = new JMenuItem("About");
    33       aboutItem.addActionListener(event -> {
    34          if (dialog == null) // first time
    35             dialog = new AboutDialog(DialogFrame.this);
    36          dialog.setVisible(true); // pop up dialog
    37       });
    38       fileMenu.add(aboutItem);
    39 
    40       // The Exit item exits the program.
    41 
    42       JMenuItem exitItem = new JMenuItem("Exit");
    43       exitItem.addActionListener(event -> System.exit(0));
    44       fileMenu.add(exitItem);
    45    }
    46 }
    View Code
     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 JDialog
    15 {
    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                   "<html><h1><i>Core Java</i></h1><hr>By Cay Horstmann</html>"),
    25             BorderLayout.CENTER);
    26 
    27       // OK button closes the dialog
    28 
    29       JButton ok = new JButton("OK");
    30       ok.addActionListener(event -> setVisible(false));
    31 
    32       // add OK button to southern border
    33 
    34       JPanel panel = new JPanel();
    35       panel.add(ok);
    36       add(panel, BorderLayout.SOUTH);
    37 
    38       pack();
    39    }
    40 }
    View Code

    实验结果如下:

    测试程序5

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

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

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

    实验程序如下:

     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 DataExchangeTest
    11 {
    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 }
    View Code
     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 JFrame
    11 {
    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 menu
    20 
    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 items
    27 
    28       JMenuItem connectItem = new JMenuItem("Connect");
    29       connectItem.addActionListener(new ConnectAction());
    30       fileMenu.add(connectItem);
    31 
    32       // The Exit item exits the program
    33 
    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 ActionListener
    47    {
    48       public void actionPerformed(ActionEvent event)
    49       {
    50          // if first time, construct dialog
    51 
    52          if (dialog == null) dialog = new PasswordChooser();
    53 
    54          // set default values
    55          dialog.setUser(new User("yourname", null));
    56 
    57          // pop up dialog
    58          if (dialog.showDialog(DataExchangeFrame.this, "Connect"))
    59          {
    60             // if accepted, retrieve user input
    61             User u = dialog.getUser();
    62             textArea.append("user name = " + u.getName() + ", password = "
    63                   + (new String(u.getPassword())) + "
    ");
    64          }
    65       }
    66    }
    67 }
    View Code
      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 dialog
    106 
    107       dialog.setTitle(title);
    108       dialog.setVisible(true);
    109       return ok;
    110    }
    111 }
    View Code
     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 }
    View Code

     实验结果如下:

    测试程序6

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

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

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

     实验程序如下:

     1 package fileChooser;
     2  
     3 import java.awt.*;
     4 import javax.swing.*;
     5  
     6 /**
     7  * @version 1.25 2015-06-12
     8  * @author Cay Horstmann
     9  */
    10 public class FileChooserTest
    11 {
    12    public static void main(String[] args)
    13    {
    14       EventQueue.invokeLater(() -> {
    15          JFrame frame = new ImageViewerFrame();
    16          frame.setTitle("FileChooserTest");
    17          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    18          frame.setVisible(true);
    19       });
    20    }
    21 }
    View Code
     1 package fileChooser;
     2  
     3 import java.io.*;
     4 import javax.swing.*;
     5 import javax.swing.filechooser.*;
     6 import javax.swing.filechooser.FileFilter;
     7  
     8 /**
     9  * A file view that displays an icon for all files that match a file filter.
    10  */
    11 public class FileIconView extends FileView
    12 {
    13    private FileFilter filter;
    14    private Icon icon;
    15  
    16    /**
    17     * Constructs a FileIconView.
    18     * @param aFilter a file filter--all files that this filter accepts will be shown
    19     * with the icon.
    20     * @param anIcon--the icon shown with all accepted files.
    21     */
    22    public FileIconView(FileFilter aFilter, Icon anIcon)
    23    {
    24       filter = aFilter;
    25       icon = anIcon;
    26    }
    27  
    28    public Icon getIcon(File f)
    29    {
    30       if (!f.isDirectory() && filter.accept(f)) return icon;
    31       else return null;
    32    }
    33 }
    View Code
     1 package fileChooser;
     2  
     3 import java.awt.*;
     4 import java.io.*;
     5  
     6 import javax.swing.*;
     7  
     8 /**
     9  * A file chooser accessory that previews images.
    10  */
    11 public class ImagePreviewer extends JLabel
    12 {
    13    /**
    14     * Constructs an ImagePreviewer.
    15     * @param chooser the file chooser whose property changes trigger an image
    16     *        change in this previewer
    17     */
    18    public ImagePreviewer(JFileChooser chooser)
    19    {
    20       setPreferredSize(new Dimension(100, 100));
    21       setBorder(BorderFactory.createEtchedBorder());
    22  
    23       chooser.addPropertyChangeListener(event -> {
    24          if (event.getPropertyName() == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)
    25          {
    26             //用户选择了一个新文件
    27             File f = (File) event.getNewValue();
    28             if (f == null)
    29             {
    30                setIcon(null);
    31                return;
    32             }
    33  
    34             //将影像读取成图示
    35             ImageIcon icon = new ImageIcon(f.getPath());
    36  
    37             // 如果图标太大,无法安装,请缩放
    38             if (icon.getIconWidth() > getWidth())
    39                icon = new ImageIcon(icon.getImage().getScaledInstance(
    40                      getWidth(), -1, Image.SCALE_DEFAULT));
    41  
    42             setIcon(icon);
    43          }
    44       });
    45    }
    46 }
    View Code
     1 package fileChooser;
     2  
     3 import java.io.*;
     4  
     5 import javax.swing.*;
     6 import javax.swing.filechooser.*;
     7 import javax.swing.filechooser.FileFilter;
     8  
     9 /**
    10  * A frame that has a menu for loading an image and a display area for the
    11  * loaded image.
    12  */
    13 public class ImageViewerFrame extends JFrame
    14 {
    15    private static final int DEFAULT_WIDTH = 300;
    16    private static final int DEFAULT_HEIGHT = 400;
    17    private JLabel label;
    18    private JFileChooser chooser;
    19  
    20    public ImageViewerFrame()
    21    {
    22       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
    23  
    24       // 设置菜单栏
    25       JMenuBar menuBar = new JMenuBar();
    26       setJMenuBar(menuBar);
    27  
    28       JMenu menu = new JMenu("File");
    29       menuBar.add(menu);
    30  
    31       JMenuItem openItem = new JMenuItem("Open");
    32       menu.add(openItem);
    33       openItem.addActionListener(event -> {
    34          chooser.setCurrentDirectory(new File("."));
    35  
    36          // 显示文件选择器对话框
    37             int result = chooser.showOpenDialog(ImageViewerFrame.this);
    38  
    39             // 如果图像文件被接受,将其设置为标签的图标
    40             if (result == JFileChooser.APPROVE_OPTION)
    41             {
    42                String name = chooser.getSelectedFile().getPath();
    43                label.setIcon(new ImageIcon(name));
    44                pack();
    45             }
    46          });
    47  
    48       JMenuItem exitItem = new JMenuItem("Exit");
    49       menu.add(exitItem);
    50       exitItem.addActionListener(event -> System.exit(0));
    51  
    52       //使用标签显示影像
    53       label = new JLabel();
    54       add(label);
    55  
    56       // 设置文件选择器
    57       chooser = new JFileChooser();
    58  
    59       //接受所有以之结尾的影像档案。JPG。杰伯图形交换格式
    60       FileFilter filter = new FileNameExtensionFilter(
    61             "Image files", "jpg", "jpeg", "gif");
    62       chooser.setFileFilter(filter);
    63  
    64       chooser.setAccessory(new ImagePreviewer(chooser));
    65  
    66       chooser.setFileView(new FileIconView(filter, new ImageIcon("palette.gif")));
    67    }
    68 }
    View Code

    实验结果如下:

    测试程序7

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

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

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

    实验程序如下:

     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       // 添加颜色选择器面板到框架
    18  
    19       ColorChooserPanel panel = new ColorChooserPanel();
    20       add(panel);
    21    }
    22 }
    View Code
     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 choosers
    15  */
    16 public class ColorChooserPanel extends JPanel
    17 {
    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 chooser
    35     */
    36    private class ModalListener implements ActionListener
    37    {
    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 user
    49     * clicks the OK button.
    50     */
    51    private class ModelessListener implements ActionListener
    52    {
    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 when
    74     * the user picks a new color.
    75     */
    76    private class ImmediateListener implements ActionListener
    77    {
    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 }
    View Code
     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 ColorChooserTest
    11 {
    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    }
    View Code

    实验结果如下:

     第三部分:实验总结

         这一周学习了Swing用户界面组件以及GUI相关组件。在学习过程中,自己对理论知识的学习学的比较混乱,混淆了这几部分的学习内容。另外,对于本周的实验,实验都有很多相同和类似的地方,在实验过程中任然没有理解的太清楚。在查了课本上的内容之后,稍微有了掌握。在运行程序过程中,对程序中有的代码还是不能理解,通过查书、上网查找才得以理解。

  • 相关阅读:
    Java 常见异常种类
    Spring3.2+mybatis3.2+Struts2.3整合配置文件大全
    Java中的基本类型和引用类型变量的区别
    【git】Git 提示fatal: remote origin already exists 错误解决办法
    【Java集合】Java中集合(List,Set,Map)
    POJ3322-经典的游戏搜索问题
    程序人生[流程图]
    不使用中间变量交换两个数
    做人要低调,别把自己太当回事
    【转】嵌套子控件设计时支持
  • 原文地址:https://www.cnblogs.com/zhaoyongjun0911/p/12005281.html
Copyright © 2011-2022 走看看