1

Application is simple with two panels in one frame

  1. First panel, retrieve from database all student s, use multiple hashmap get parent and child arrangement and show it on tree.

  2. Second panel, when you click on a student all details of that student (selectionlistener) shown in textboxes.

Now when I alter the name of the student on the 2nd panel, the database updates it properly but the tree shows the old value.

I have tried treepanel.reload(), I have tried treemodellistener.

Can anyone help me out here. Going through a lot of solutions online, all are partial which i could not apply to my code.

Thanks in advance.


Main frame.java

/**
 * @author Suraj Baliga
 * 
 * Returns a JFrame with two Panels one having the Jtree and other 
 * having the details of the selected tree component.It also has dynamic tree and 
 * dynamic textbox where updation of text in the textbox will change the value in 
 * databse on click of save button.The JDBC localhost url may change with each machine 
 * as the database location and port number may vary.
*/




package Student_Details;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import org.apache.commons.collections.MultiHashMap;

public final class Main_frame extends JPanel 
{
    String sname,sschool;

    ArrayList StudName_arrylst = new ArrayList();
    ArrayList SchlName_arrylst = new ArrayList();
    ArrayList StudDetailTxtFld_arrylst = new ArrayList();


    static public Connection connect,connect_update;
    public ResultSet resultSet;
    public static ResultSet resultset2;
    MultiHashMap SchlStud_hashmap = new MultiHashMap();

    int i,j,k,k2,z;

    DefaultMutableTreeNode tree_parent;
    int SchlName_arylist_length, StudNamearrylst_length;
    private tree_generation treePanel;


    static JButton save_button = new JButton("Save");
    static JButton cancel_button = new JButton("Cancel");

    static JTextField studName_txtbox= new JTextField();
    static JTextField studAddress_txtbox = new JTextField();
    static JTextField studOthr_txtbox = new JTextField();

   static public String user_name;
   static public String user_add;
   static public String user_other;




    static JLabel name_label = new JLabel("Name : ");
    static JLabel address_label = new JLabel("Adress : ");
    static JLabel other_label = new JLabel("Other Deatils : ");

   static String studDetailsTxtbox_disp[] = new String[10];
    static String studDetailsTxtbx_disp_db[] = new String[10];
    static String studDetailsTxtbxchange[] = new String[10];

    public JPanel panel;
    static JPanel panel_boxes = new JPanel();




    public Main_frame() 
    {

        super(new BorderLayout());

        //Create the components.
        treePanel = new tree_generation();
        populateTree(treePanel);

        //Lay everything out.
        treePanel.setPreferredSize(new Dimension(300, 150));
        add(treePanel, BorderLayout.WEST);

        panel = new JPanel(new GridLayout(1, 2));
        add(panel, BorderLayout.CENTER); 
     }






    public void populateTree(tree_generation treePanel) 
    {
        try 
        {
            Class.forName("org.apache.derby.jdbc.ClientDriver");
            connect = DriverManager.getConnection("jdbc:derby://localhost:1527/treedata2", "suraj", "suraj");
            PreparedStatement AllStuddetails = connect.prepareStatement("SELECT * from student_details");
            resultSet = AllStuddetails.executeQuery();
            while (resultSet.next()) 
            {

                sname = resultSet.getString(1);
                sschool = resultSet.getString(3);
                SchlStud_hashmap.put(sschool, sname);
            }
        } 
        catch (Exception e) 
         {

         }
        Set keySet = SchlStud_hashmap.keySet();
        Iterator keyIterator = keySet.iterator();

        while (keyIterator.hasNext())
        {
            Object key = keyIterator.next();
            SchlName_arrylst.add(key);

            Collection values = (Collection) SchlStud_hashmap.get(key);
            Iterator valuesIterator = values.iterator();

            while (valuesIterator.hasNext()) 
            {
                StudName_arrylst.add(valuesIterator.next());

            }
            SchlName_arylist_length = SchlName_arrylst.size();
            StudNamearrylst_length = StudName_arrylst.size();

            String schlname_tree[] = new String[SchlName_arylist_length];
            String studname_tree[] = new String[StudNamearrylst_length];

            Iterator SchlName_iterator = SchlName_arrylst.iterator();

            i = 0;
            while (SchlName_iterator.hasNext()) 
            {
                schlname_tree[i] = SchlName_iterator.next().toString();
            }

            Iterator StudName_iterator = StudName_arrylst.iterator();
            j = 0;
            while (StudName_iterator.hasNext()) 
            {
                studname_tree[j] = StudName_iterator.next().toString();
                 j++;
            }

            for (k = 0; k < schlname_tree.length; k++) 
            {
                  tree_parent = treePanel.addObject(null, schlname_tree[k]);
                  for (k2 = 0; k2 < studname_tree.length; k2++) 
                     {
                            treePanel.addObject(tree_parent, studname_tree[k2]);
                     }
            }
           StudName_arrylst.clear();
           SchlName_arrylst.clear();
         }

  }







    /**
     * Create the GUI and show it.  
     */
    private static void createAndShowGUI() 
    {
        //Create and set up the window.
        JFrame frame = new JFrame("Student Details");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        Main_frame newContentPane = new Main_frame();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);
        panel_boxes.setLayout(null);

        name_label.setBounds(55,90,150,100);   
        studName_txtbox.setBounds(225,130, 155, 25);
        panel_boxes.add(name_label);
        panel_boxes.add(studName_txtbox);


        address_label.setBounds(55,160, 150, 100);
        studAddress_txtbox.setBounds(225,200, 155, 25);
        panel_boxes.add(address_label);
        panel_boxes.add(studAddress_txtbox);

        other_label.setBounds(55,220, 150, 100);
        studOthr_txtbox.setBounds(225,270, 155, 25);
        panel_boxes.add(other_label); 
        panel_boxes.add(studOthr_txtbox);


        save_button.setBounds(150,350, 100, 50);
        cancel_button.setBounds(350,350, 100, 50);
        panel_boxes.add(save_button);
        panel_boxes.add(cancel_button); 

        frame.add(panel_boxes); 
        //Display the window.
        frame.pack();
        frame.setSize(1000,700);
        frame.setVisible(true);


        save_button.setEnabled(false);
        cancel_button.setEnabled(false);


         studName_txtbox.addFocusListener(new FocusListener() 
         {
            @Override //since some additional functionality is added by the user to 
                      //the inbuilt function @override notation is used
            public void focusGained(FocusEvent e) 
            {
             save_button.setEnabled(true);
             cancel_button.setEnabled(true);
            }

            @Override
            public void focusLost(FocusEvent e) 
            {
                System.out.println("out of focus textbox");
            }


        });

          studAddress_txtbox.addFocusListener(new FocusListener() {

            @Override
            public void focusGained(FocusEvent e) 
            {
             save_button.setEnabled(true);
             cancel_button.setEnabled(true);    
            }

            @Override
            public void focusLost(FocusEvent e) 
            {
               save_button.setEnabled(false);
                cancel_button.setEnabled(false); 
            }
        });


            studOthr_txtbox.addFocusListener(new FocusListener() {

            @Override
            public void focusGained(FocusEvent e) 
            {
             save_button.setEnabled(true);
             cancel_button.setEnabled(true);    
            }

            @Override
            public void focusLost(FocusEvent e) 
            {
               save_button.setEnabled(false);
                cancel_button.setEnabled(false); 
            }
        });

             cancel_button.addActionListener(new ActionListener() 
        { 
                public void actionPerformed(ActionEvent e) 
                { 
                    if(e.getSource()== cancel_button )
                    {
                 clear_textboxes();
                 }
                }
              } );
            save_button.addActionListener(new ActionListener() 
        { 
                public void actionPerformed(ActionEvent e) 
                { 
                    if(e.getSource()== save_button )
                    {
                 selectionButtonPressed();
                 }
                }
              } );
    }




     public void fill_textboxes(ArrayList a1)
    {
        Iterator alldetails = a1.iterator();
        z=0;
        while (alldetails.hasNext()) 
         {
          studDetailsTxtbx_disp_db[z]= (String) alldetails.next();
          System.out.println("this is the Detail : "+studDetailsTxtbx_disp_db[z]);
           z++;   
         }  

     studName_txtbox.setText(studDetailsTxtbx_disp_db[0]);
     studAddress_txtbox.setText(studDetailsTxtbx_disp_db[1].toString());
     studOthr_txtbox.setText(studDetailsTxtbx_disp_db[2]);

 }
  public static void selectionButtonPressed()
    {
      studDetailsTxtbxchange[0]=studName_txtbox.getText(); 
      studDetailsTxtbxchange[1]=studAddress_txtbox.getText();
      studDetailsTxtbxchange[2]=studOthr_txtbox.getText();
      try 
        {
            if((studDetailsTxtbxchange[0].equals(""))||(studDetailsTxtbxchange[0] == null)||(studDetailsTxtbxchange[1].equals(""))||(studDetailsTxtbxchange[1] == null)||(studDetailsTxtbxchange[2].equals(""))||(studDetailsTxtbxchange[2] == null))
            {
            JOptionPane.showMessageDialog(null,"One of the Fields is Blank","Error",JOptionPane.ERROR_MESSAGE);
            }
            else
            {
            System.out.println("control here inside else baby..that has : : "+studDetailsTxtbxchange[0]);
            Class.forName("org.apache.derby.jdbc.ClientDriver");
            connect_update = DriverManager.getConnection("jdbc:derby://localhost:1527/treedata2", "suraj", "suraj");
            PreparedStatement execqry = connect.prepareStatement("select * from student_details where student_name='"+studDetailsTxtbxchange[0]+"'");
            resultset2=execqry.executeQuery();
             System.out.println("control at end if else");
            if(resultset2.next())
            {
                JOptionPane.showMessageDialog(null,"Sorry This name already exists","Error",JOptionPane.ERROR_MESSAGE);
            }
            else
            {
               System.out.println("control here");
               Class.forName("org.apache.derby.jdbc.ClientDriver");
               connect_update = DriverManager.getConnection("jdbc:derby://localhost:1527/treedata2", "suraj", "suraj");
               PreparedStatement updateQry = connect.prepareStatement("UPDATE student_details SET student_name='"+studDetailsTxtbxchange[0]+"',student_address='"+studDetailsTxtbxchange[1]+"',student_school='"+studDetailsTxtbxchange[2]+"' WHERE student_name='"+user_name+"' and student_address='"+user_add+"'and student_school='"+user_other+"'");
               updateQry.executeUpdate();
               JOptionPane.showMessageDialog(null,"Record Updated!","UPDATED",JOptionPane.OK_OPTION);
                  tree_generation.loadit();
            }

            } 

        }
        catch (Exception e) 
         {
           e.printStackTrace(); 
         }              
    }

  public static void clear_textboxes() 
     {
     studName_txtbox.setText(studDetailsTxtbx_disp_db[0]);
     studAddress_txtbox.setText(studDetailsTxtbx_disp_db[1].toString());
     studOthr_txtbox.setText(studDetailsTxtbx_disp_db[2]);
     }

    void dbaction(String string)
      {

      studDetailsTxtbox_disp[0]= string;
      System.out.println("This is the stuff :" + studDetailsTxtbox_disp[0]);
       try
       {
       Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
       connect = DriverManager.getConnection("jdbc:derby://localhost:1527/treedata2","suraj","suraj");
       PreparedStatement statement4 = connect.prepareStatement("SELECT * from student_details where student_name ='"+studDetailsTxtbox_disp[0]+"'");                
       resultSet = statement4.executeQuery();
       while(resultSet.next())
                   {

                             user_name = resultSet.getString("student_name");
                            StudDetailTxtFld_arrylst.add(user_name);
                            System.out.println("name :"+user_name);

                            user_add = resultSet.getString("student_address");
                            StudDetailTxtFld_arrylst.add(user_add);
                            System.out.println("address : "+ user_add);


                            user_other = resultSet.getString("student_school");
                            StudDetailTxtFld_arrylst.add(user_other);
                            System.out.println("school : "+user_other);
                 }

    }
    catch (Exception e1) 
    {
        e1.printStackTrace();
    }
   fill_textboxes(StudDetailTxtFld_arrylst);
 }




    public static void main(String[] args) 
    {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            public void run() 
            {
                createAndShowGUI();
            }
        });
    }
}

tree_generation.java

/**
 * @author Suraj
 * 
 * Tree generation and actions such as adding new parent or child takes place here
 * Section Listeners for displaying relavent details of the selected student.
 */


package Student_Details;

import java.awt.GridLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;

public class tree_generation extends JPanel
{


    protected DefaultMutableTreeNode rootNode;
    protected DefaultTreeModel treeModel;
    protected JTree tree;
    public  String studDetailsTxtbox_disp[] = new String[10];



    public tree_generation() 
    {
      super(new GridLayout(1,0));
        rootNode = new DefaultMutableTreeNode("Click for Student Details");
        treeModel = new DefaultTreeModel(rootNode);
    tree = new JTree(treeModel);
        tree.setEditable(true);
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        tree.addTreeSelectionListener(new TreeSelectionListener() 
            {
           @Override
            public void valueChanged(TreeSelectionEvent e) 
           {
           studDetailsTxtbox_disp[0]= tree.getLastSelectedPathComponent().toString(); 
           Main_frame db = new Main_frame();
           db.dbaction(studDetailsTxtbox_disp[0]);
           }
        }); 
        tree.setShowsRootHandles(true);
        JScrollPane scrollPane = new JScrollPane(tree);
        add(scrollPane);
    }

    /** Add child to the currently selected node. */
    public DefaultMutableTreeNode addObject(Object child) 
    {
        DefaultMutableTreeNode parentNode = null;
        TreePath parentPath = tree.getSelectionPath();

        if (parentPath == null) {
            parentNode = rootNode;
        } 
        else 
        {
            parentNode = (DefaultMutableTreeNode)
                         (parentPath.getLastPathComponent());
        }

        return addObject(parentNode, child, true);
    }



    public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
                                            Object child) 
    {
        return addObject(parent, child, false);
    }




    public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
                                            Object child, 
                                            boolean shouldBeVisible) 
    {
        DefaultMutableTreeNode childNode = 
                new DefaultMutableTreeNode(child);

        if (parent == null) 
        {
            parent = rootNode;
        }

    //It is key to invoke this on the TreeModel
        treeModel.insertNodeInto(childNode, parent, 
                                 parent.getChildCount());

        //Make sure the user can see the new node.
        if (shouldBeVisible) 
        {
            tree.scrollPathToVisible(new TreePath(childNode.getPath()));
        }
        return childNode;
    }
      static void loadit()
      {


     tree_generation.treeModel.reload();
//i tried this too//
          //treePanel = new tree_generation();
      // populateTree(treePanel);
    }


    class MyTreeModelListener implements TreeModelListener {
        public void treeNodesChanged(TreeModelEvent e) {
            DefaultMutableTreeNode node;
            node = (DefaultMutableTreeNode)(e.getTreePath().getLastPathComponent());
   node.setUserObject("HELLO WORLD");
            /*
             * If the event lists children, then the changed
             * node is the child of the node we've already
             * gotten.  Otherwise, the changed node and the
             * specified node are the same.
             */

                int index = e.getChildIndices()[0];
                node = (DefaultMutableTreeNode)(node.getChildAt(index));

            System.out.println("The user has finished editing the node.");
            System.out.println("New value: " + node.getUserObject());
        }
        public void treeNodesInserted(TreeModelEvent e) {
        }
        public void treeNodesRemoved(TreeModelEvent e) {
        }
        @Override
        public void treeStructureChanged(TreeModelEvent e) 
        {
            System.out.println("tree sturct changed") ;
                 DefaultMutableTreeNode node;
            node = (DefaultMutableTreeNode)(e.getTreePath().getLastPathComponent());
   node.setUserObject("HELLO WORLD");
            tree.updateUI();
            e.getTreePath();
        }
    }
    }

Queries - DATABASE NAME : treedata2

create table student_details(student_name varchar(20),student_address varchar(30),student_school varchar(20));

insert into student_details values('suraj','mangalore','dps');
insert into student_details values('prassana','Bangalore lalbagh 23/16 2nd main road','dps');
insert into student_details values('deepika','Mangalore kadri park , 177b','dav');
insert into student_details values('sujith','delhi , rajinder nagar, d black','dav');
insert into student_details values('sanjay','bombay marina drive, 12/34','dav');
insert into student_details values('suresh','jaipur , lalbagh cjhowki','kv');
insert into student_details values('manu','surat, pune warior house','kv');
insert into student_details values('tarun','chennai, glof club','salwan');
insert into student_details values('vinay','haryana, indutrial area','hindu senior');
insert into student_details values('veeru','trivendrum, kottayam 12/77','canara')
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Suraj B
  • 25
  • 1
  • 8
  • 1
    Consider simplifying your code such that it's runnable for us but has had all database references removed and all code not related to the problem removed, in order to both isolate the problem, and if the problem still occurs, to allow us to run your code without need of your database, to review your code without going through a ton of unrelated code, and hopefully to allow us to find a fix. – Hovercraft Full Of Eels Jul 26 '12 at 14:19
  • hi Hovercraft Full Of Eels, Thanks for going through. Actually the code is runnable. The database file is also there you just have to copy paste it in the netbeans derby. The java files into a new project folder pasted and run. Let me know if i should still remove it. – Suraj B Jul 26 '12 at 14:20
  • 1
    @SurajB Sure, remove what's not necessary. The code is not runnable without creating your database, adding commons-collections, etc... This makes it quite reluctant for others to grab your code and execute it. There is too much code to read. Als, you should consider the following: 1) Don't catch silently an exception (this is a rookie mistake) 2) Indent your code properly 3) Follow java coding conventions: Class name starts with an upper case letter, packages should contain only lower-case letters, variables start with a lower case letter etc... Use camel case instead of underscores – Guillaume Polet Jul 26 '12 at 14:27
  • 1
    @SurajB If you are not modifying the look and feel nor any of its properties you should not need to call `tree.updateUI();` – Guillaume Polet Jul 26 '12 at 14:28
  • 1
    @Suraj: No one is requiring you to make the changes that Guillaume and I are suggesting, but usually the easier you make it for folks to help you, the better your chances of getting good swift help. If you get a decent solution without making these changes, then great, but if not and you're still stuck, please consider our recommendations. – Hovercraft Full Of Eels Jul 26 '12 at 14:32
  • hi Guillaume Polet and Hovercraft Full Of Eels, i cant Thank you guys enough for your help in advising me and giving me pointers. Right, ill make the changes as soon as I can. :) – Suraj B Jul 27 '12 at 04:41

1 Answers1

3

Ok, I think I found what's not working in your code, but you should probably try it yourself and confirm.

Class.forName("org.apache.derby.jdbc.ClientDriver");
connect_update = DriverManager.getConnection("jdbc:derby://localhost:1527/treedata2", "suraj", "suraj");
PreparedStatement updateQry = connect.prepareStatement("UPDATE student_details SET student_name='"+studDetailsTxtbxchange[0]+"',student_address='"+studDetailsTxtbxchange[1]+"',student_school='"+studDetailsTxtbxchange[2]+"' WHERE student_name='"+user_name+"' and student_address='"+user_add+"'and student_school='"+user_other+"'");
updateQry.executeUpdate();
JOptionPane.showMessageDialog(null,"Record Updated!","UPDATED",JOptionPane.OK_OPTION);
tree_generation.loadit();

In this code, you indeed update the database but you don't update the model of the tree. You are calling the static method loadit() but that method does not contain any code. In order to worker you should probably refresh/reload your TreeModel. There are different ways to do that. One would be to directly spot the TreeNode to refresh and update it with the new values. Another would be to recreate your entire TreeModel (but this can be costly if your tree is big). Using an object-mapping model (for instance JPA/Hibernate) you could have something much cleaner with an appropriate MVC-pattern and a model notifying the views of the updated values, but it requires extra-effort to set up.

For what it is worth, you should consider dropping those static keywords as they are not necessary nor appropriately used. Whenever possible, you should try to avoid using that keyword (unless it is used in conjunction with finalto describe a constant value).

One more thing, try to use appropriate LayoutManager's instead of using absolute-positionning. Using appropriate layout manager makes your code easier to maintain and more portable across different platforms/look and feels.

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • Thank you so much for your input Guillaume Polet. I ll definitly try and remove the static where possible and also put down a layout manager. As for refresh, can you please guide me as to how to refresh the whole tree by my code? i know its costly but thats the need of the hour right now so. – Suraj B Jul 27 '12 at 04:34
  • Hi trashgod , thanks for looking in to my problem. Actually i visited the example you provided but couldnt find out where reload was used. I would be greatful if you could give me a pointer on how to implement it on a JTree. – Suraj B Jul 27 '12 at 04:37
  • @SurajB: Apologies for my careless link; this related [example](http://stackoverflow.com/a/11639595/230513) uses `reload()`. – trashgod Jul 27 '12 at 05:37
  • Hi trashgod, i did visit your link. After analysing and trying to apply the same principle i noticed that treeModel.reload() is doing the refresh work. I tried that same { i have edited the code see the loadit() function } but in vain. The Jtree does not refresh. Any advice? – Suraj B Jul 27 '12 at 11:58
  • Guillaume Polet i did add treeModel.reload() in the loadit() function { i have edited it} but it still does not refresh with the changed value in the database – Suraj B Jul 27 '12 at 12:00
  • @SurajB Of course. The tree has no idea that it is connected to data coming from a database. There is no way for the tree to find that out. The simplest way for you would be to recreate the entire tree model by fetching the data from the database. – Guillaume Polet Jul 27 '12 at 17:05
  • @Guillaume Polet oh i see, well last question, i tried to recreate the entire tree but i could do it only by recreating the JFrame which means everytime a new JFrame is created. Can you please guide me how to recreate only the tree Panel? Looking at the code i could not figure out any way to repopulate only the tree panel. By the way thank you for your inputs and advices. Looking forward to end this ordeal once and for all. I am starting to get bugged with JTrees :D – Suraj B Jul 28 '12 at 15:08
  • @SurajB Sure, there are way better solutions. Being far from optimal, this is likely to remain one of the simplest solution: recreate the entire TreeModel and set it on the JTree. No need to recreat a JFrame nor a tree_generation panel. For this to work easily, I would have created some method that can fetch data from the database and create the DefaultTreeModel and then return it. Then to refresh your JTree, you would call that methods and set the returned result on the JTree, using setModel(). Again, far from optimal but it should require very few changes in your code for this to work. – Guillaume Polet Jul 28 '12 at 16:36