Null pointer exception in unselecting checkbox in Java?

Hi,
I am writing a code to unselect all checkboxes of a Tree.

When I click on a button in the GUI, it calls unselectAll method as below:

CheckListTree.getInstance().unselectAll();

Open in new window


CheckListTree class is like this. It has getInstance, unselectAll, checkPath, checkItems, and createCheckListTree methods.

When I print "instance" it is not null in line 7, but when I print "tree' in unselectAll method, it returns null in line 13. Therefore, I get this null pointer exception error.

But I don't know why it is null. Can you please take a look at it?



public class CheckListTree {
    private Tree tree;
   
    public static CheckListTree getInstance()
    {
        CheckListTree instance = new CheckListTree();
        System.out.println("instance: " + instance);
        return instance;
    }
    
    
    public void unselectAll (){
        System.out.println("tree: " + tree);
        for (TreeItem item : tree.getItems()) {   
            System.out.println("item: " + item);
            checkItems(item, false);
        }
        
    }
    
    public void checkPath(TreeItem item, boolean checked, boolean grayed) {
        if (item == null) return;
        if (grayed) {
            checked = true;
        } else {
            int index = 0;
            TreeItem[] items = item.getItems();
            while (index < items.length) {
                TreeItem child = items[index];
                if (child.getGrayed() || checked != child.getChecked()) {
                    checked = grayed = true;
                    break;
                }
                index++;
            }
        }
        item.setChecked(checked);
        item.setGrayed(grayed);
        checkPath(item.getParentItem(), checked, grayed);
    }

    public void checkItems(TreeItem item, boolean checked) {
        item.setGrayed(false);
        item.setChecked(checked);
        TreeItem[] items = item.getItems();
        for (int i = 0; i < items.length; i++) {
            checkItems(items[i], checked);
        }
    }

    public void createCheckListTree(Composite compTab2, GridData layoutData, List<HashMap<Integer, String>> checkList)  {
            tree = new Tree(compTab2, SWT.BORDER | SWT.CHECK);
            tree.setLayoutData(layoutData);
            tree.addListener(SWT.Selection, new Listener() {
                public void handleEvent(Event event) {
                    if (event.detail == SWT.CHECK) {
                        TreeItem item = (TreeItem) event.item;
                        boolean checked = item.getChecked();
                        checkItems(item, checked);
                        checkPath(item.getParentItem(), checked, false);
                    }
                }
            });
                  
            
            Iterator<HashMap<Integer, String>> checkListIter = checkList.iterator();
            while(checkListIter .hasNext()) {
              HashMap<Integer, String> amap =   (HashMap<Integer, String>) checkListIter .next();
              Set<?> keysetString = (Set<?>) amap .keySet();
              Iterator<?> iter = keysetString.iterator();
              while( iter.hasNext() ) {
                Integer keyVal = (Integer) iter.next();
                //System.out.println("keyVal " + keyVal);
                String valFromKey = amap.get(keyVal);
                //System.out.println("valFromKey " + valFromKey);
                TreeItem itemI = new TreeItem(tree, SWT.NONE);
                itemI.setText(valFromKey);
              } 
            }
    }        
}

Open in new window


Thanks,
TolgarAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Melih SARICAOwnerCommented:
Before for each loop getitems instance to a variable and loop in that variable.  I think problem is object lcking issue
0
TolgarAuthor Commented:
But, tree is null. In that case getItems will not be able to get anything from the tree. So, I didn't understand how is it going to help if I assign getitems instance to a variable.

What do you think?
0
Melih SARICAOwnerCommented:
in line 13 u use variable tree.. but in getinstance u set a local variable instance.. u did nto set localvariable tree in getinstance function. set tree variable in getinstance function
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

TolgarAuthor Commented:
Can you please show me what you mean? I am a little confused.
0
TolgarAuthor Commented:
and I set tree in the beginning of the class

private Tree tree;

Open in new window


What is wrong with this? I use this variable in other methods in the same class but not in unselectAll method.
0
Melih SARICAOwnerCommented:
public class CheckListTree {
    private Tree tree;
   
    public static CheckListTree getInstance()
    {
        CheckListTree instance = new CheckListTree();
        System.out.println("instance: " + instance);
        return instance;
    }
   
   
    public void unselectAll (){
        System.out.println("tree: " + tree); // this variable(tree) is not assinged yet.. if u mean self with  tree use "this" as tree
        for (TreeItem item : tree.getItems()) {  
            System.out.println("item: " + item);
            checkItems(item, false);
        }
       
    }

UR code ll be something like this
public void unselectAll (){
        System.out.println("tree: " + this);
        for (TreeItem item : this.getItems()) {  
            System.out.println("item: " + item);
            checkItems(item, false);
        }
       
    }
0
StillUnAwareCommented:
There is one of many ways to achieve what you are looking for, here I extend the class Tree (not recommended, Eclipse asks you not to extend its classes, see method
checkSubclass

Open in new window

). Then the CheckListTree can be used as any other UI component, but with it's additional features. Here is the code:

package com.andriusburokas.pluginplayground;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;

public class CheckListTree extends Tree {
	
    public CheckListTree(Composite compTab2, GridData layoutData, List<HashMap<Integer, String>> checkList) {
    	super(compTab2, SWT.BORDER | SWT.CHECK);
    	setLayoutData(layoutData);
    	addListener(SWT.Selection, new Listener() {
    		public void handleEvent(Event event) {
    			if (event.detail == SWT.CHECK) {
    				TreeItem item = (TreeItem) event.item;
    				boolean checked = item.getChecked();
    				checkItems(item, checked);
    				checkPath(item.getParentItem(), checked, false);
    			}
    		}
    	});

    	Iterator<HashMap<Integer, String>> checkListIter = checkList.iterator();
    	while(checkListIter .hasNext()) {
    		HashMap<Integer, String> amap =   (HashMap<Integer, String>) checkListIter .next();
    		Set<?> keysetString = (Set<?>) amap .keySet();
    		Iterator<?> iter = keysetString.iterator();
    		while( iter.hasNext() ) {
    			Integer keyVal = (Integer) iter.next();
    			//System.out.println("keyVal " + keyVal);
    			String valFromKey = amap.get(keyVal);
    			//System.out.println("valFromKey " + valFromKey);
    			TreeItem itemI = new TreeItem(this, SWT.NONE);
    			itemI.setText(valFromKey);
    		} 
    	}
    }
    
    public void unselectAll (){
        System.out.println("tree: " + this);
        for (TreeItem item : this.getItems()) {   
            System.out.println("item: " + item);
            checkItems(item, false);
        }
        
    }
    
    public void checkPath(TreeItem item, boolean checked, boolean grayed) {
        if (item == null) return;
        if (grayed) {
            checked = true;
        } else {
            int index = 0;
            TreeItem[] items = item.getItems();
            while (index < items.length) {
                TreeItem child = items[index];
                if (child.getGrayed() || checked != child.getChecked()) {
                    checked = grayed = true;
                    break;
                }
                index++;
            }
        }
        item.setChecked(checked);
        item.setGrayed(grayed);
        checkPath(item.getParentItem(), checked, grayed);
    }

    public void checkItems(TreeItem item, boolean checked) {
        item.setGrayed(false);
        item.setChecked(checked);
        TreeItem[] items = item.getItems();
        for (int i = 0; i < items.length; i++) {
            checkItems(items[i], checked);
        }
    }

    protected void checkSubclass () {
    	
    }
}

Open in new window


And the sample usage code:

		ArrayList<HashMap<Integer, String>> list = new ArrayList<HashMap<Integer, String>>();
		HashMap<Integer, String> map1 = new HashMap<Integer, String>();
		map1.put(1, "One");
		map1.put(2, "Two");
		map1.put(3, "Three");
		list.add(map1);
		HashMap<Integer, String> map2 = new HashMap<Integer, String>();
		map1.put(4, "Three");
		map1.put(5, "Four");
		map1.put(6, "Five");
		list.add(map2);
		final CheckListTree listTree = new CheckListTree(container, new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1), list);
		Button button = new Button(container, SWT.NONE);
		button.setText("Unselect All");
		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				listTree.unselectAll();
			}
		});

Open in new window

0
StillUnAwareCommented:
The reason why your class was not working:

calling method createCheckListTree you create a tree and assign it's instance to field CheckListTree.tree, that's ok. BUT, whenever you call method getInstance you create always new class CheckListTree which has yet unset field tree.

In other words, you could use your CheckListTree, but you must very carefully choose what methods and when to call. This would work:

		final CheckListTree cltree = CheckListTree.getInstance();
		cltree.createCheckListTree(container, new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1), list);
		Button button = new Button(container, SWT.NONE);
		button.setText("Unselect All");
		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				cltree.unselectAll();
			}
		});

Open in new window

0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
CheckListTree.getInstance().unselectAll();
While there are some valid uses of this type of pattern, I doubt that in your case it is really what you want, and also your implementation of the pattern is wrong. I would really recommend that you read/learn a bit more of the fundamental principles of object-oriented programming if you are keen to understand why you are having these issues. And to practise on a simpler project than trying to get a GUI working, as the complexities of dealing with SWT and the like are probably getting in the way of basic OOP issues.

Having said that, maybe you are not as worried about the "why" and instead just want to get this working. If that is the case, AND you will only ever use ONE instance of your check list tree ANYWHERE in this program, then the following would be the simplest way to sort it out. Replace the first 9 lines of your code above with this.   It correctly implements the "static factory method" pattern that you are trying to do with the getInstance() method (note that this code is NOT thread-safe, assuming there is no need for considering multi-threading issues)...
public class CheckListTree {
    
    static private CheckListTree instance = null;
    
    private Tree tree;
    
    private CheckListTree() {
    }
    
    public static CheckListTree getInstance()
    {
        if (instance == null) {
            instance = new CheckListTree();
        }
        System.out.println("instance: " + instance);
        return instance;
    }

Open in new window

Note that this code MAY cause errors in other parts of your code. If it does, it would be on lines like... new CheckListTree()   If that is the case, you just need to change those to.... CheckListTree.getInstance() to make it all work.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
TolgarAuthor Commented:
@mccarl: I made the changes that you recommended. And it worked fine.

Can you please point me to a good documentation to learn about these things in OOP?

Thanks,
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
The Oracle Java tutorial/lessons are generally quite good, I think.

http://docs.oracle.com/javase/tutorial/java/index.html

Especially the lesson on OOP concepts, but a refresher on how that applies in Java is useful too. Now I realise that you obvious do know Java, and I don't mean to be condescending but I put that there because sometimes it is easy to get the general idea but it may be good to go back and make sure you really understand what is happening at a deeper level. In particular with all of this, make sure you really understand classes and objects and how they relate, how they are different, etc. Variables/members, as in class members, instance members, local variables, etc and their scope, including the use of the keyword static.

Then once you are happy with that, then I would also look at some general design patterns/best practices for working with OOP. Search Google for "object oriented best practices" and you will get lots of useful information on this. It will help you move from "adding just whatever code seems to make it work" to "structured code that is easy to maintain and add features too when needed".
0
TolgarAuthor Commented:
Thanks a lot.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.