[Java] Swing系列-顶层容器JFrame使用的学习体会

      今天记录两个内容:

           1. JFrame在不同版本下面的add方法区别

           2. JFrame的层次问题(如何在监听器中获取JFrame

      ----------------------------------------------------------------------------------------------------------------

      在做毕业设计的时候,经常要用到JFrame,这是一个可以在桌面上显示的组件,在网上查看使用方法和技巧的时候,一般对于Swing组件的使用是这样的描述:

     ---------------------------------------------------------------------------------------------

     ---------------------------------------------------------------------------------------------

     与AWT组件不同,Swing组件不能直接添加到顶层容器中,它必须添加到一个与Swing顶层容器相

    关联的内容面板(content pane)上。内容面板是顶层容器包含的一个普通容器,它是一个轻量

    级组件。

    即,把Swing组件放入一个顶层Swing容器的内容面板上

     ---------------------------------------------------------------------------------------------

    对JFrame添加组件有两种方式:

  1、用getContentPane( )方法获得JFrame的内容面板,再对其加入组件:即,

               frame.getContentPane().add(childComponent)

  2、建立一个Jpanel JDesktopPane之类的中间容器,把组件添加到容器中,用

         setContentPane()方法把该容器置为JFrame的内容面板,再向上面添加组件

     ---------------------------------------------------------------------------------------------

 

 

    在翻我们原来学的教材时候(java程序设计教程),上面使用的是第一种方法。

后来一次设计一个小窗口的时,我直接在JFrame上使用add(Component)来添加组件(我以为自己写的是一个JPanel),之后检查时发现这个问题,但我也很惊讶这样直接就把组件添加上去了。

  查了API文档,发现原来JDK1.5以后的版本,JFrame中已经可以直接使用add方法添加组件,下面摘录不同版本API文档的描述:

JDK1.4

      For example, to add a child to an AWT frame you'd write:

            frame.add(child);

       However using JFrame you need to add the child to the JFrame's content pane instead:

             frame.getContentPane().add(child);

       The same is true for setting layout managers, removing components, listing children, and so on.

             -----------------------------------

JDK1.5

    作为 add的便捷方法及其变体,已经重写了 remove setLayout,以在必要时将其转发到

        contentPane。这意味着可以编写:

                       frame.add(child);

        子级将被添加到 contentPane

             -----------------------------------

JDK1.6

    为了方便地使用 add及其变体,已经重写了 remove setLayout,以在必要时将其转发到

        contentPane。这意味着可以编写:

                       frame.add(child);

        子级将被添加到 contentPane

 

  这就一目了然了,从1.5开始,在JFrame使用add方法就可以直接将组件添加到默认ContentPane上,而不用在采用前文所说的第二种方法.

 

  关于这个机制改变,是在接口 RootPaneContaine做的。可以看到,在JDK1.5中,这个接口的描述:

    -----------------------------------------------------------

    -----------------------------------------------------------

  为了便于使用 JFrameJDialogJWindowJApplet JInternalFrame,默认情况下,将 addremove setLayout方法的所有调用转发到 contentPane。这意味着您可以调用:

     rootPaneContainer.add(component);

 而不是:

     rootPaneContainer.getContentPane().add(component);

   -------------------------------------------------

  于是这个问题就很清晰了,我也得出一个经验,那就是一定要关注新版本的JDK,研究其与老版本之前的差别,这样才能更好的做开发。

 

·············································

  (下面这个问题使用jdk1.5版本以上)

  下面是我遇到的另一个问题,比如如下代码:(假设我已经有一个监听器handler)

      JFrame frame = new JFrame();

             button = new JButton("Test");

             button.addActionListener(handler);

             frame.add(button);

  那么,当点击这个button时,在监听器的ActionPerformed(ActionEvent e)中要如何获取button所在的JFrame??(假设监听器是一个独立的实现ActionListener接口的类)

  请看下图

 

 

  这个图是我自己根据理解画的,展示了JFrame的层次。这也就是说,当点击button时,点击事件发生在上图JButton所在的层次上,如果想要根据这个button点击事件获取JFrame,自然就需要getParent() 4

  下面代码展示了这个过程:

      public void actionPerformed(ActionEvent e) { JButton button = (JButton) e.getSource(); JPanel panel = (JPanel)button.getParent(); JLayeredPane layeredPane = (JLayeredPane)panel.getParent(); JRootPane rootPane = (JRootPane) layeredPane.getParent(); JFrame frame = (JFrame) rootPane.getParent(); }   

  这样最终才获取了JFrame

      

    关于上图中的JPanel的解释:如果直接用frame.add()方法添加button,那么该组件会添加到一个默认的ContentPane上面,也就是一个JPanel

      

-------------------------------------------------------

-------------------------------------------------------

我使用frame的一些经验:

经验1--

  在毕业设计后面的开发中,我改掉了直接用frame.add()方法添加组件的代码,因为我构思了一个功能:

 (虽然后来没用)点击button改变ContentPane

  如果我使用默认面板,由于这个面板并没有名字,所以在我更换了contentPane后再想要改回原先的默认面板时,就无从下手了。(注:当然也可以在事先获取默认面板并保存)

    所以说,建立一个Jpanel JDesktopPane之类的中间容器,把组件添加到容器中,用setContentPane()方法把该容器置为JFrame的内容面板是比较好的方式。我觉得这样更容易表达设计的思路。

----------------

经验2--

  另外,我在设计的时候,要经常在监听器的事件处理方法中改变各种面板的内容,比如我想要操作一个JFrame,那么,如果使用上面给出的代码来获取,是比较麻烦的方式。

  后来我想了个办法,我编写了一个类似于注册部门的类,起名叫注册类,在编写好一个JFrame后,就把这个frame注册到这个类中。如果在哪里需要使用这个frane,就通过这个注册类的静态方法进行获取。(注:翻看设计模式的时候,发现这有点类似中介者模式,我还需要研究) 

 

-------------------------------------------------------------------------------------------------------------- ------------------------------------

     我是一个菜鸟,我热烈欢迎任何人指出我的错误和缺点!

 

你可能感兴趣的:(Java,GUI,Java)