Monday, November 9, 2009

Riding the swing

Only because of Sun Developer exam I had to consider swing coding. Much to my disappointment though according to the assignment text use of any third party libraries was prohibited resulting no possible use of a WYSIWYG tool like NetBeans. I resorted to learning the fundamentals and going through the APIs. By the looks of the assignment I thought the implementation of the functionality that was limited to edit and read was going to be easy. Once I actually started working on that, however, I realized the complexities in JFC APIs. For instance, to create a basic Frame with Menu I do not have a handy utility class and method. For getting a parent frame from a MenuItem I do not have a straight forward one line method call. For each one of such instance, I had to write several lines of code. My toughest challenge - or should I say that the worst nightmare - was the laying out of the GUI components on  the frame using the Layout Manager. Anyhow, finally, I am able to create a few utility methods/class myself that I would be briefing on.
1. Acting on a JTable based on event on a MenuItem:
a> Register an event listener to the menu item.
b> Implement actionPerformed contract to take whatever action on the table you want.
c> Now, to obtain the table mentioned in the above point write method or a class. The way I have been doing this is writing an utility class that will take care of such concerns.

      /**
         * This method obtains the Parent Frame window of the Menu Item.

 * @param menuItem where the action was taken
* @return JFrame  parent frame
      **/


public JFrame getMainFrame(JMenuItem menuItem) {
JPopupMenu popupMenu = (JPopupMenu) menuItem.getParent();
JMenu menu = (JMenu) popupMenu.getInvoker();
JComponent component = (JComponent) menu;
JFrame frame = (JFrame) component.getTopLevelAncestor();
return frame;
}

        /**
           * Make use of the Reflection APIs and recursion to grab the wanted component from the frame
           * @param container - Container like JPanel, JScrollPane.
           *               className - Class name of the component to be obtained - javax.swing.JTable, etc
           * @return JComponent Object of the class mentioned inside the container passed.


public static JComponent getComponent(Container container, String className) throws ClassNotFoundException{
if (container != null){
Class cl = Class.forName(className);
Component[] components = container.getComponents();
for (int i = 0; i < components.length; ++i){
Component c = components[i];
if (c.getClass().getName().equals(className)){
component = (JComponent)c;
}else if (c instanceof Container){
getComponent((Container)c, className);
}
}
}
return component;
}

Now what if you need a set of several similar components? For example, grab me a list of all the text fields present inside a container.
Use the similar recursive approach with a little modification. Instead of calling this method directly, call an intercepting method. This will, after resetting the instance Collection field, in turn, call the aforementioned method that may be considered to be of private scope. Hence it would go something like this:



public List getComponents(Container container, String className) throws ClassNotFoundException{
componentList = new ArrayList(); //Reset\initialize the Collection
return getComponentList(container, className); //Call the method that internally calls itself
}


private List getComponentList(Container container, String className) throws ClassNotFoundException{
if (container != null){
Class cl = Class.forName(className);
Component[] components = container.getComponents();
for (int i = 0; i < components.length; ++i){
Component c = components[i];
if (c.getClass().getName().equals(className)){
component = (JComponent)c;
componentList.add(component);
}else if (c instanceof Container){
isRecursiveCall = true;
getComponents((Container)c, className);
}
}
}
return componentList;
}

Method to obtain the root panel (JDialog or JFrame):
public Container getMainFrame(JButton button){ Container container = button.getParent(); while(true){ System.out.println(container); if (container instanceof JFrame){ return (JFrame)container; }else if (container instanceof JDialog){ return (JDialog)container; } else{ container = container.getParent(); System.out.println("Container: " + container); } } }


Welcome to my blogs

The contents here are my independent point of view. They reflect my thoughts, experience in my professional and social life.

Search This Blog