SSISO Community

시소당

Uses reflection and JavaBeans introspection to

import  java.awt.Color;
import  java.awt.Component;
import  java.awt.Font;
import  java.awt.event.ActionEvent;
import  java.awt.event.ActionListener;
import  java.awt.event.WindowAdapter;
import  java.awt.event.WindowEvent;
import  java.beans.BeanInfo;
import  java.beans.Introspector;
import  java.beans.PropertyDescriptor;
import  java.lang.reflect.Method;
import  java.util.Vector;

import  javax.swing.ButtonGroup;
import  javax.swing.JFrame;
import  javax.swing.JMenu;
import  javax.swing.JMenuBar;
import  javax.swing.JMenuItem;
import  javax.swing.JRadioButtonMenuItem;
import  javax.swing.JTabbedPane;
import  javax.swing.SwingUtilities;
import  javax.swing.UIManager;

/**
  *  This  class  is  a  program  that  uses  reflection  and  JavaBeans  introspection  to
  *  create  a  set  of  named  components,  set  named  properties  on  those  components,
  *  and  display  them.  It  allows  the  user  to  view  the  components  using  any
  *  installed  look-and-feel.  It  is  intended  as  a  simple  way  to  experiment  with
  *  AWT  and  Swing  components,  and  to  view  a  number  of  the  other  examples
  *  developed  in  this  chapter.  It  also  demonstrates  frames,  menus,  and  the
  *  JTabbedPane  component.
  */
public  class  ShowComponent  {
    //  The  main  program
    public  static  void  main(String[]  args)  {
        //  Process  the  command  line  to  get  the  components  to  display
        Vector  components  =  getComponentsFromArgs(args);

        //  Create  a  frame  (a  window)  to  display  them  in
        JFrame  frame  =  new  JFrame("ShowComponent");

        //  Handle  window  close  requests  by  exiting  the  VM
        frame.addWindowListener(new  WindowAdapter()  {  //  Anonymous  inner  class
                    public  void  windowClosing(WindowEvent  e)  {
                        System.exit(0);
                    }
                });

        //  Set  up  a  menu  system  that  allows  the  user  to  select  the
        //  look-and-feel  of  the  component  from  a  list  of  installed  PLAFs
        JMenuBar  menubar  =  new  JMenuBar();  //  Create  a  menubar
        frame.setJMenuBar(menubar);  //  Tell  the  frame  to  display  it
        JMenu  plafmenu  =  createPlafMenu(frame);  //  Create  a  menu
        menubar.add(plafmenu);  //  Add  the  menu  to  the  menubar

        //  Create  a  JTabbedPane  to  display  each  of  the  components
        JTabbedPane  pane  =  new  JTabbedPane();

        //  Now  add  each  component  as  a  tab  of  the  tabbed  pane
        //  Use  the  unqualified  component  classname  as  the  tab  text
        for  (int  i  =  0;  i  <  components.size();  i++)  {
            Component  c  =  (Component)  components.elementAt(i);
            String  classname  =  c.getClass().getName();
            String  tabname  =  classname
                    .substring(classname.lastIndexOf('.')  +  1);
            pane.addTab(tabname,  c);
        }

        //  Add  the  tabbed  pane  to  the  frame.  Note  the  call  to  getContentPane()
        //  This  is  required  for  JFrame,  but  not  for  most  Swing  components
        frame.getContentPane().add(pane);

        //  Set  the  frame  size  and  pop  it  up
        frame.pack();  //  Make  frame  as  big  as  its  kids  need
        frame.setVisible(true);  //  Make  the  frame  visible  on  the  screen

        //  The  main()  method  exits  now  but  the  Java  VM  keeps  running  because
        //  all  AWT  programs  automatically  start  an  event-handling  thread.
    }

    /**
      *  This  static  method  queries  the  system  to  find  out  what  Pluggable
      *  Look-and-Feel  (PLAF)  implementations  are  available.  Then  it  creates  a
      *  JMenu  component  that  lists  each  of  the  implementations  by  name  and  allows
      *  the  user  to  select  one  of  them  using  JRadioButtonMenuItem  components.
      *  When  the  user  selects  one,  the  selected  menu  item  traverses  the  component
      *  hierarchy  and  tells  all  components  to  use  the  new  PLAF.
      */
    public  static  JMenu  createPlafMenu(final  JFrame  frame)  {
        //  Create  the  menu
        JMenu  plafmenu  =  new  JMenu("Look  and  Feel");

        //  Create  an  object  used  for  radio  button  mutual  exclusion
        ButtonGroup  radiogroup  =  new  ButtonGroup();

        //  Look  up  the  available  look  and  feels
        UIManager.LookAndFeelInfo[]  plafs  =  UIManager
                .getInstalledLookAndFeels();

        //  Loop  through  the  plafs,  and  add  a  menu  item  for  each  one
        for  (int  i  =  0;  i  <  plafs.length;  i++)  {
            String  plafName  =  plafs[i].getName();
            final  String  plafClassName  =  plafs[i].getClassName();

            //  Create  the  menu  item
            JMenuItem  item  =  plafmenu.add(new  JRadioButtonMenuItem(plafName));

            //  Tell  the  menu  item  what  to  do  when  it  is  selected
            item.addActionListener(new  ActionListener()  {
                public  void  actionPerformed(ActionEvent  e)  {
                    try  {
                        //  Set  the  new  look  and  feel
                        UIManager.setLookAndFeel(plafClassName);
                        //  Tell  each  component  to  change  its  look-and-feel
                        SwingUtilities.updateComponentTreeUI(frame);
                        //  Tell  the  frame  to  resize  itself  to  the  its
                        //  children's  new  desired  sizes
                        frame.pack();
                    }  catch  (Exception  ex)  {
                        System.err.println(ex);
                    }
                }

            });

            //  Only  allow  one  menu  item  to  be  selected  at  once
            radiogroup.add(item);
        }
        return  plafmenu;
    }

    /**
      *  This  method  loops  through  the  command  line  arguments  looking  for  class
      *  names  of  components  to  create  and  property  settings  for  those  components
      *  in  the  form  name=value.  This  method  demonstrates  reflection  and  JavaBeans
      *  introspection  as  they  can  be  applied  to  dynamically  created  GUIs
      */
    public  static  Vector  getComponentsFromArgs(String[]  args)  {
        Vector  components  =  new  Vector();  //  List  of  components  to  return
        Component  component  =  null;  //  The  current  component
        PropertyDescriptor[]  properties  =  null;  //  Properties  of  the  component
        Object[]  methodArgs  =  new  Object[1];  //  We'll  use  this  below

        nextarg:  //  This  is  a  labeled  loop
        for  (int  i  =  0;  i  <  args.length;  i++)  {  //  Loop  through  all  arguments
            //  If  the  argument  does  not  contain  an  equal  sign,  then  it  is
            //  a  component  class  name.  Otherwise  it  is  a  property  setting
            int  equalsPos  =  args[i].indexOf('=');
            if  (equalsPos  ==  -1)  {  //  Its  the  name  of  a  component
                try  {
                    //  Load  the  named  component  class
                    Class  componentClass  =  Class.forName(args[i]);
                    //  Instantiate  it  to  create  the  component  instance
                    component  =  (Component)  componentClass.newInstance();
                    //  Use  JavaBeans  to  introspect  the  component
                    //  And  get  the  list  of  properties  it  supports
                    BeanInfo  componentBeanInfo  =  Introspector
                            .getBeanInfo(componentClass);
                    properties  =  componentBeanInfo.getPropertyDescriptors();
                }  catch  (Exception  e)  {
                    //  If  any  step  failed,  print  an  error  and  exit
                    System.out.println("Can't  load,  instantiate,  "
                            +  "or  introspect:  "  +  args[i]);
                    System.exit(1);
                }

                //  If  we  succeeded,  store  the  component  in  the  vector
                components.addElement(component);
            }  else  {  //  The  arg  is  a  name=value  property  specification
                String  name  =  args[i].substring(0,  equalsPos);  //  property  name
                String  value  =  args[i].substring(equalsPos  +  1);  //  property
                                                                  //  value

                //  If  we  don't  have  a  component  to  set  this  property  on,  skip!
                if  (component  ==  null)
                    continue  nextarg;

                //  Now  look  through  the  properties  descriptors  for  this
                //  component  to  find  one  with  the  same  name.
                for  (int  p  =  0;  p  <  properties.length;  p++)  {
                    if  (properties[p].getName().equals(name))  {
                        //  Okay,  we  found  a  property  of  the  right  name.
                        //  Now  get  its  type,  and  the  setter  method
                        Class  type  =  properties[p].getPropertyType();
                        Method  setter  =  properties[p].getWriteMethod();

                        //  Check  if  property  is  read-only!
                        if  (setter  ==  null)  {
                            System.err.println("Property  "  +  name
                                    +  "  is  read-only");
                            continue  nextarg;  //  continue  with  next  argument
                        }

                        //  Try  to  convert  the  property  value  to  the  right  type
                        //  We  support  a  small  set  of  common  property  types  here
                        //  Store  the  converted  value  in  an  Object[]  so  it  can
                        //  be  easily  passed  when  we  invoke  the  property  setter
                        try  {
                            if  (type  ==  String.class)  {  //  no  conversion  needed
                                methodArgs[0]  =  value;
                            }  else  if  (type  ==  int.class)  {  //  String  to  int
                                methodArgs[0]  =  Integer.valueOf(value);
                            }  else  if  (type  ==  boolean.class)  {  //  to  boolean
                                methodArgs[0]  =  Boolean.valueOf(value);
                            }  else  if  (type  ==  Color.class)  {  //  to  Color
                                methodArgs[0]  =  Color.decode(value);
                            }  else  if  (type  ==  Font.class)  {  //  String  to  Font
                                methodArgs[0]  =  Font.decode(value);
                            }  else  {
                                //  If  we  can't  convert,  ignore  the  property
                                System.err.println("Property  "  +  name
                                        +  "  is  of  unsupported  type  "
                                        +  type.getName());
                                continue  nextarg;
                            }
                        }  catch  (Exception  e)  {
                            //  If  conversion  failed,  continue  with  the  next  arg
                            System.err.println("Can't  convert    '"  +  value
                                    +  "'  to  type  "  +  type.getName()
                                    +  "  for  property  "  +  name);
                            continue  nextarg;
                        }

                        //  Finally,  use  reflection  to  invoke  the  property
                        //  setter  method  of  the  component  we  created,  and  pass
                        //  in  the  converted  property  value.
                        try  {
                            setter.invoke(component,  methodArgs);
                        }  catch  (Exception  e)  {
                            System.err.println("Can't  set  property:  "  +  name);
                        }

                        //  Now  go  on  to  next  command-line  arg
                        continue  nextarg;
                    }
                }

                //  If  we  get  here,  we  didn't  find  the  named  property
                System.err.println("Warning:  No  such  property:  "  +  name);
            }
        }

        return  components;
    }
}

818 view

4.0 stars