Java核心技术:卷1笔记[7] Swing用户界面组件

来源:互联网 发布:网络谐音词大全 编辑:程序博客网 时间:2024/06/08 16:12
 

1.MVC设计模式:

       1)模型:存储内容,实现改变和发现内容的方法。模型是不可见的。

       2)视图:显示内容,一个模型可以有多个视图,其中每个视图可以显示完整内容的不同部分或不同方面。

       3)控制器:处理用户输入,决定是否把用户输入事件转化成对模型或视图的改变。

2.对于大多数控件,模型类实现了名字结尾为Model的接口,例如ButtonModel接口。一般来说,每个Swing组件都有一个后缀为UI的相关视图对象,但并不是所有的Swing组件都有专门的控制器对象。

3.容器内的所有组件都由一个布局管理器进行管理,面板的默认布局管理器为流布局管理器,其特点是在一行上水平排列组件,直到该行没有足够的空间,则另起一行。当用户缩放容器时,布局管理器会自动回流组件使其填充可用空间。可以指定对其方式,如:setLayout(new FlowLayout(FlowLayout.LEFT));

4.JFrame的内容窗格的默认布局管理器为边界布局,可以选择把组件放在窗格中的中部、北部、南部、东部或者西部。如:add(yellowButton,BorderLayout.SOUTH);边界布局会增大所有组件来填充可用空间。

5.网格布局按行列来排列所有的组件,每个单元总是一样的大小。可以指定行数和列数及水平和垂直间距:

       panel.setLayout(new GridLayout(5,4,3,3));

       添加组件时,从第一行的第一列开始,然后是第一行的第二列,这样持续下去。

6.对应单行文本输入的类为JTextField,对应多行文本的类为JTextArea,这两个类都继承自抽象类JTextComponent类。

7.可以在JTextField的构造器中设定其宽度,如JTextField textField=new JTextField(“Default String”,20);但该宽度并不是用户能够输入的字符个数的上限。如果需要在运行时重新设置列数,可以使用setColumns方法,如:

       textField.setColumns(10);

       panel.validate();

       validate方法会重新计算容器内所有组件的大小,并且对它们重新布局。

8.所有文本组件的模型都由Document接口说明,既包括无格式的文本,也包括格式化的文本。当数据改变后,可以要求文档(而非文本组件)发出通知,这需要安装一个文档监听器:

       textField.getDocument().addDocumentListener(listener);

       当文本发生改变后,下面三个方法中的一个会被调用:

       void insertUpdate(DocumentEvent e)

       void removeUpdate(DocumentEvent e)

       void changedUpdate(DocumentEvent e)

9.Java提供JpasswordField类来实现密码框,其setEchoChar方法用来设置回显字符,getPassword方法用来获取包含在密码框内的文本。

10.JFormattedTextField类用来实现格式化输入。如创建一个整型输入的文本框:

       JFormattedTextField intField = new JFormattedTextField( NumberFormat.getIntegerInstance(); )

       可以用setValue的方法来设置默认值,该方法参数为Object类型,如:intField.setValue(new Integer(100));可以用getValue方法得到结果,该方法返回类型为Object,需要将它转化为适当的类型。如果用户没有编辑数值,它返回原来的Integer对象,如果用户编辑了数值,则返回类型为Long的对象。所以应该把返回值转化为通用的超类Number:

       Number value = (Number)intField.getValue();

       int v = value.intValue();

11.当格式化文本框失去焦点时,格式器检测用户输入的文本字符串。如果格式器知道怎么把文本字符串转化为对象,那么该文本就是有效的,否则就是无效的。可以用isEditValid方法进行检测。

12.失去焦点的默认行为被称为“提交或者恢复”。如果文本字符串有效,那么就提交它,格式器把它转化为对象,该对象变为当前文本框的值。然后该值转化为字符串,成为文本框内可见的文本字符串。如果文本字符串无效,那么当前值不会改变,文本框恢复代表原来值的字符串。如果文本字符串以一个整数开始,那么整型格式器就认为该字符串是有效的。可以用setFocusLostBehavior方法来设置其他行为。

13.任何时候控制器处理一个命令使文本插入到文档中,这被称为“插入字符串”命令。被插入的字符串可以是单独的一个字符也可以是粘贴缓冲区的内容。文档过滤器可以中途截取该命令,并且修改字符串或者取消插入,例如,实现一个过滤器分析要插入的字符并且只插入是数字或者-符号的字符:

       class IntFilter extends DocumentFilter

       {

              public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)

                                                 throws BadLocationException

              {    

                     StringBuffer buffer = new StringBuffer();

                     for(int i=buffer.length()-1;i>=0;i--)

                     {

                            char ch = buffer.charAt(i);

                            if(!Character.isDigit(ch) && ch!=’-‘)

                                   buffer.deleteChar(i);

                     }

                     super.insertString(fb,offset,buffer.toString(),attr);

              }

       }

       也可以覆盖DocumentFilter类的replace方法,当选择并替换文本时,该方法被调用。

14.安装文本过滤器需要覆盖格式器类的getDocumentFilter方法,并传递格式器类的对象到JFormattedTextField,如:

       JFormattedTextField intField = new JFormattedTextField(new

                                   InternationalFormatter(NumberFormat.getIntegerInstance())

                                   {

                                          protected DocumentFilter getDocumentFilter()

                                          {

                                                 return filter;

                                          }

                                          private DocumentFilter filter=new IntFilter();

                                   });

15.可以给任何JComponent附加检验器。如果组件失去焦点,则询问检验器,如果检验器报告说组件的内容无效,该组件立刻重新获得焦点,用户在提供其他输入前被强迫修改内容。检验器必须继承抽象类InputVerifier,并且定义verify方法。如:

       class FormattedTextFieldVerifier extends InputVerifier

       {

              public boolean verify(JComponent component)

              {

                     JFormattedTextField field=(JFormattedTextField)component;

                     return field.isEditValid();

              }

       }

       安装检验器:intField.setInputVerfier(new FormattedTextFieldVerifier());

16.NumberFormat类有静态方法:getNumberInstance、getCurrencyInstance、getPercentInstance用来产生浮点数、金额和百分数的格式器。编辑日期和时间可以使用DateFormat类的静态方法之一。

17.DefaultFormatter可以格式化任何类的对象,这些类都有一个以一个字符串为参数的构造器和匹配的toString方法。该格式器针对文本框值调用toString来初始化文本框的文本。当文本框失去焦点时,格式器使用带有String参数的构造器构造相同类的新对象作为当前值。如果构造器抛出异常,那么编辑就是无效的。

18.MaskFormatter对处理一些常量和一些变量字符的固定尺寸样式很有用。如,new MaskFormatter(“##-###-##”);

19.自定义格式器需要继承DefaultFormatter类并且覆盖以下方法:

       String valueToString(Object value),把值转化为字符串显式在文本框中;

       Object stringToValue(String text),分析用户输入的文本,并把它转回为对象。如果其中任一方法检测到错误,将抛出ParseException异常。如自定义IP地址格式器:

class IPAddressFormatter extends DefaultFormatter

{

   public String valueToString(Object value)

      throws ParseException

   {

      if (!(value instanceof byte[]))

         throw new ParseException("Not a byte[]", 0);

      byte[] a = (byte[])value;

      if (a.length != 4)

         throw new ParseException("Length != 4", 0);

      StringBuffer buffer = new StringBuffer();

      for (int i = 0; i < 4; i++)

      {

         int b = a[i];

         if (b < 0) b += 256;

         buffer.append(String.valueOf(b));

         if (i < 3) buffer.append('.');

      }

      return buffer.toString();

   }

 

   public Object stringToValue(String text) throws ParseException

   {

      StringTokenizer tokenizer = new StringTokenizer(text, ".");

      byte[] a = new byte[4];

      for (int i = 0; i < 4; i++)

      {

         int b = 0;

         try

         {

            b = Integer.parseInt(tokenizer.nextToken());

         }

         catch (NumberFormatException e)

         {

            throw new ParseException("Not an integer", 0);

         }

         if (b < 0 || b >= 256)

            throw new ParseException("Byte out of range", 0);

         a[i] = (byte)b;

      }

      return a;

   }

}

20.如果文本区中的文本超出显示范围,那么剩下的文本就会被修剪掉。可以通过使用换行来避免修剪长行:textArea.setLineWrap(true);换行只是视觉效果,文档中的文本并没有改变,并没有’\n’字符被插入到文本中。

21.文本区没有滚动条,如果需要滚动条,必须把文本区插入到一个滚动窗格中,例如:

       JScrollPane scrollPane=new JScrollPane(textArea);

       滚动是由滚动窗格内部处理的,无需处理滚动事件。

22.JtextArea组件只显示无格式的文本,如果要显示格式化文本,需要使用JEditorPane和JTextPane

23.可以使用SwingConstants接口中的常量来指定对其方式,JLabel是实现了此接口的Swing类之一,因此可以如下构造一个左对齐的标签:

       JLabel label = new JLabel(“TEXT”,SwingConstants.LEFT);

       可以在按钮、标签、菜单项中直接使用HTML文本,如:

       label = new JLabel(“<html><B>Required</B>entry:</html>”);

24.文本框类和文本区类都从超类JTextComponent中继承了方法来选择组件包含的文本,这两个类也都能够检查当前所选文本。

       selectAll方法用来选中所有文本;select方法用来选中文本的一部分,其参数和subString完全一样;getSelectionStart和getSelectionEnd方法返回当前选择的起始和结束位置,getSelectedText返回选中的文本。

25.实现单选按钮组:首先为按钮组构造一个ButtonGroup类型的对象,接着把JRadioButton类型的对象添加到该按钮组中,在按钮组中,当点击一个新按钮时,前一个被选中的按钮自动取消选定,如:

       ButtonGroup group = new ButtonGroup();

       JRadioButton smallButton=new JRadioButton(“Small”,false);

       group.add(smallButton);

26.只有通过setActionCommand命令明确设定了所有单选按钮的动作命令,才能通过方法:buttonGroup.getSelection().getActionCommand()获得当前选中的按钮的动作命令(也可以为每个单选按钮添加独立的动作监听器)。

27.可以为任何扩展了JComponent的组件提供一种边界,最常见的用法是在一个面板周围设置一种边界,然后用其他用户界面元素来填充该面板。有几种不同的边界可供选择,但是使用它们的步骤完全一样:

       1)调用BorderFactory的一个静态方法来创建边界,Java自定义了几种不同的边界风格;

       2)可以为边界添加一个标题,使用BorderFactory.creatTitledBorder实现;

       3)可以把几种边界组合起来,使用BorderFactory。createCompoundBorder实现;

       4)将结果添加到组件中去,通过调用JComponent的setBorder方法实现:

              Border etched=BorderFactory.createEtchedBorder();

              Border title=BorderFactory.createTitledBorder(etched,”A Title”);

              panel.setBorder(titled);

28.当用户从组合框中选择一个选项时,该组合框就会生成一个动作事件。为了判断哪个选项被选择,可以在事件参数上调用getSource方法来得到发送事件的组合框的一个引用,接着调用getSelectedItem方法来提取当前被选择的项,如:

       faceCombo.addActionListener(new

         ActionListener()

         {

            public void actionPerformed(ActionEvent event)

            {

               label.setFont(new Font( (String)faceCombo.getSelectedItem(),Font.PLAIN,

                  DEFAULT_SIZE));        

            }

         });

29.构造一个滑块:JSlider slider=new JSlider(min,max,initialValue);

       当用户滑动滑块时,一个ChangeEvent事件就会被发送到所有的改变监听器上。为了得到这些改变的通知,需要调用addChangeListener方法,并安装实现了ChangeListener接口的对象,该接口只有一个方法stateChanged,在该方法中,可以提取滑块的值:

       public void stateChange(ChangeEvent event)

       {

              JSlider slider =(JSlider)event.getSource();

              int value = slider.getValue();

       }

30.可以通过显示标尺来修饰滑块,如:

       slider.setMajorTickSpacing(20);//大标尺

       slider.setMinorTickSpacing(5);//小标尺

       要把标尺实际显示出来还须调用:slider.setPaintTicks(true);

       可以强制滑块对其标尺:slider.setSnapToTicks(true);

31.也可以提供其他标尺标记,如字符串或者图标:首先填充一个键值为new Integer(tickValue),而值为Component类型的哈希表,然后调用setLabelTable方法,组件就会放置在标尺标记下,如把标尺的标签设为A,B,C,D,E,F:

       Hashtable labelTable=new Hashtable();

       labelTable.put(new Integer(0),new JLabel(“A”));

       labelTable.put(new Integer(0),new JLabel(“A”));

       …

       labelTable.put(new Integer(0),new JLabel(“F”));

       slider.setLabelTable(labelTable);

32.填充滑块:slider.putClientProperty(“JSlider.isFilled”,Boolean.TRUE);

       逆向填充:Slider.setInverted(true);

33.JSpinner也是文本框,它在一边带有两个小按钮,可以增加或者减少存储在文本框内的值。

34.创建一个菜单栏:JMenuBar menuBar=new JMenuBar();

       在框架中添加菜单栏:frame.setJMenuBar(menuBar);

       创建一个菜单对象并添加到菜单栏中:

              JMenu editMenu=new JMenu(“Edit”);

              menuBar.add(editMenu);

       在菜单对象中添加菜单项、分隔符及子菜单:

              JMenuItem pasteItem=new JMenuItem(“Paste”);

              editMenu.add(pasteItem);

              editMenu.addSeparator();

              JMenu optionsMenu=…;//submenu

              editMenu.add(optionsMenu);

       利用JMenu.add(String s)可以把一个菜单项添加到菜单的结尾,并返回创建的子菜单项,例如

              JMenuItem pasteItem=editMenu.add(“Paste”);           

              pasteItem.addActionListener(listener);

35.JMenuItem类继承了AbstractButton类,因此同按钮一样,菜单也可以具有文本标签、图标或者二者兼有。

36.复选框和单选按钮菜单项会在文本旁边显示一个复选框或一个单选按钮。当用户选择该菜单项时,该菜单项会自动在选择和未选择之间切换。如创建一个复选框菜单项:

       JCheckBoxMenuItem checkMenuItem=new JCheckBoxMenuItem(“ReadOnly”);

       创建单选按钮菜单项使用JRadioButtonMenuItem。单选按钮菜单项同常规单选按钮一样,必须添加到一个按钮组中。

37.创建弹出菜单同创建常规菜单很相似,但是弹出菜单没有标题:

       JPopupMenu popup=new JPopupMenu();

       必须明确调用show方法来显示,且需要指定其父组件与位置:

       popup.show(panel,x,y);

38.用户点击弹出触发器弹出菜单的步骤:

       1)安装一个鼠标监听器;

       2)在鼠标监听器中安装如下代码:

       public void mousePressed(MouseEvent event)

       {

              if(event.isPopupTrigger())

                     popup.show(event.getComponent(),event.getX(),event.getY());

       }

39.可以通过在菜单项构造器中指定一个快捷字母来为菜单项设置快捷键:

       JMenuItem cutItem = new JMenuItem(“Cut”,”T”);

       若要为一个菜单设置快捷键,需要调用setMnemonic方法:

       JMenu helpMenu = new JMenu(“Help”);

       helpMenu.setMnemonic(‘H’);

40.快捷键用来从当前打开的菜单中选择一个子菜单或者菜单项,而加速器是在不打开菜单的情况下选择菜单项的快捷键,它直接激活同菜单关联的动作事件,如把加速器CTRL+O关联到openItem菜单项:

       openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,InputEvent.CTRL_MASK));

41.只有工具栏(JToolBar)在一个具有边界布局或者其他任何支持North、East、South、West约束布局的容器内,那么它才能够被拖动。

42.三种复杂布局管理:

       1)箱式布局:BoxLayout

       2)网格组布局:GridBagLayout,使用GridBagConstraints约束布局,该约束包含一系列字段、参数;

       3)弹簧布局:SpringLayout

43.当一个窗口初次显示时,便利顺序中的第一个组件会具有键盘焦点。每次用户按下TAB键,那么下一个组件就会得到焦点。Swing的遍历顺序是从左至右,从上到下的。如果一个容器中还包含了其他的容器,当焦点被设到其他容器时,该容器左上角的组件会得到焦点,并且依次在该容器内传递焦点,最后焦点被设到跟着该容器的组件上。

44.要改变遍历顺序,可以把相关组件组合到面板中,如果这样不奏效,那么就要安装一个比较器对组件进行不同排序,要么完全替换遍历策略。

45.JOptionPane有四个静态方法来显示简单对话框:

       1)showMessageDialog,无返回值;

       2)showConfirmDialog,代表选择项的一个整数;

       3)showOptionDialog,代表选择项的一个整数;

       4)showInputDialog,用户选择或输入的字符串;

46.简单对话框总结:

       1)选择对话框类型:消息、确认、选项、输入;

       2)选择图标:错误、信息、警告、问题、无、自定义;

       3)选择消息:字符串、图标、定制组件、它们的集合;

       4)对于确认对话框,选择选项类型:默认、Yes/No、Yes/NoCancel、OK/Cancel;

       5)对于选项对话框,选择选项(字符串、图标、定制组件)和默认选项;

       6)对于输入对话框,选择输入组件(文本框或者组合框);

       底部按钮取决于对话框类型和选项类型。

47.文件选择对话框JFileChooser及颜色选择对话框JColorChooser其实都是组件而非对话框,也即它们并不是继承于JDialog;

原创粉丝点击