🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.jbuilder.java.swing
1 messages
1 total messages Started by Alan Shiers Mon, 01 Mar 2004 21:51
coordinating events
#1256
Author: Alan Shiers
Date: Mon, 01 Mar 2004 21:51
379 lines
15548 bytes
Hi there,

I'm having difficulty trying to coordinate the sequence of events for
populating a JTree with data received from a server app.  I'm so-o-o-o close
and yet no banana! It's proving to be very tricky processing.  I could use
some help in trying to make this work properly.  Perhaps you may understand
better as to why my efforts are being thwarted by the either the JTree
object or its DefaultTreeModel?

Here's the setup:

1)  I have a server app that, when requested from the client app, will
provide a child count on any given directory node on the server.  Also, it
will serve up the names of each child node for any given node upon request.

2)  The client app contains a JTree object that I'm trying to initially
populate with the root node.  Subsequently, the plan is to dynamically
populate any directory node in the JTree whenever the treeWillExpand( ... )
event is triggered as the user tries to expand on a node.

3) Throughout my code I have a number of System.out.println( ... )
statements so that I can see what sequence of events are taking place as the
client app makes requests to the server and receives replies back from the
server.  Also, some println(...) statements in some key methods which you'll
see.

4) The sequence of events is supposed to go like so:

    i)   root node is created
    ii)  as the root node is passed as a parameter when creating the JTree
object
         the getChildCount( ) method of the root node [type DefaultTreeNode
extends DefaultMutableTreeNode ]
         is called.

         public int getChildCount()
        {
            if (!hasChildren)
            {
               defineChildNodes();
            }
            return(super.getChildCount());
         }

    iii) Since the root node initially has no children, getChildCount( )
then calls the method
        defineChildNodes( ).

         protected void defineChildNodes()
        {
            hasChildren = true;
            ref.requestChildCountFromServer(this);
         }

         As you can see, defineChildNodes( ) simply sets the flag
hasChildren to true then
         calls a method requestChildCountFromServer(this) which exists in a
class called Response
         referred here by the variable "ref".  Also in the Response class
there exists the method
         populateTree( )  which initially created the root node and JTree
objects:

        protected void populateTree(String NodeName)
       {
          //System.out.println("Entering populatTree() method");
          //This could take a while, so change the cursor icon
          //ref.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
          try
         {
             String separator = "";
             if(ref.serverOS.equals("Windows"))
                separator = "\\";
             else
                separator = "/";
             rootNode = new DefaultTreeNode(NodeName, true, separator);
             expandingNode = rootNode;
             String rootPath = getLeadingPath(ref.rootPath);
             rootNode.setLeadingPath(rootPath);
             rootNode.setResponseReference(this);
             jTree1 = new JTree(rootNode);
             jTree1.setRootVisible(true);
             jTree1.setShowsRootHandles(true);
             jTree1.collapseRow(0);
             MouseListener popupListener = new PopupListener(ref);
             jTree1.addMouseListener(popupListener);

            //Listen to our own expand/collapse events to keep the labels in
sync
            jTree1.addTreeWillExpandListener(this);

        }
        catch(Exception e){System.out.println("Exception in populateTree()
method"); e.printStackTrace();return;}
         ....
         ....
      }

     iv)  The requestChildCountFromServer( ) method then makes a request to
the server app for
           the child count for the root node.

     v)  I have a separate thread running that listens for all responses
from the server
          called ResponseListener.    In its run( ) method I have the
following code:

          else if(connected == ref.ref.SENDING_CHILDCOUNT)
          {
               System.out.println("Received message: ReceivingChildCount");
               ref.expandingNode.numChildren = input.readInt();
               //expandingNode.setReceivedChildCount(true);
               ref.ref.imageLabel.setIcon(ref.ref.blank);
               ref.ref.textLabel.setText("");
          }

          When the root node was originally created I set a reference to it
using a variable
          named expandingNode.  Here you can see that the root node's
instance variable
          named numChildren is set to a value read in by the DataInputStream
object
          named input.

    vi)  The requestChildCountFromServer( ) method in turn calls another
method in the
         Response class named RequestChildrenFromServer(String path).
         RequestChildrenFromServer(String path) method requests from the
server the names
         of all the child nodes for the root node.

    vii) ResponseListener then receives a response from the server:

          else if(connected == ref.ref.SENDING_TREE_DATA)
          {
               System.out.println("Received message: SendingTreeData");
               ref.expandingNode.TreeDataIncoming = true;
               ref.expandingNode.ReceiveChildrenFromServer(input);
               ref.ref.imageLabel.setIcon(ref.ref.blank);
               ref.ref.textLabel.setText("");
          }

          Here you can see that the root nodes method named
          ReceiveChildrenFromServer(input) is then called
          while passing it a reference to the DataInputStream so that the
method can
          read in the names of the child nodes as they come in over the
wire.

    viii) The root node's method ReceiveChildrenFromServer(input) then
begins receiving the
           names of each child node, creates a new DefaultTreeNode object
for each child node
           and adds it to the root node, seen below:

            protected void ReceiveChildrenFromServer(DataInputStream input)
            {
                System.out.println("Entering ReceiveChildrenFromServer()");

                DefaultTreeNode child = null;
                String name = "";
                try
               {

//ref.ref.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                     //System.out.println("numChildren = " + numChildren);
                     int nodeType = 0;//default
                    //iterate through each of the children as they come in
                    //from the server.
                    for(int i = 0; i < numChildren; i++)
                    {
                        name = input.readUTF(); //get the name
                        System.out.println("child node: " + name);
                        child = new DefaultTreeNode(name); //create a new
child node

                       //determine if this node is a directory
                       //or a file. Empty directories are denoted
                       //as having (nodeType == -1)
                       nodeType = input.readInt();
                      //System.out.println("node type: " + nodeType);
                      if(nodeType == 0)
                      {
                         //Since a file is a leaf node
                         //we won't be needing to continue
                         //reading in nodes for it.
                         child.setResponseReference(ref);
                         child.setAllowsChildren(false);
                         child.setHasChildren(false);
                         child.setLeadingPath(getWholeServerPath());
                         if(ref.ref.serverOS.equals("Windows"))
                             child.setSeparator("\\");
                         else
                             child.setSeparator("/");
                      }
                      else if(nodeType == -1)
                     {
                         child.setResponseReference(ref);
                         child.setAllowsChildren(true); //It's an empty
directory
                         child.setHasChildren(false);
                         child.setLeadingPath(getWholeServerPath());
                          if(ref.ref.serverOS.equals("Windows"))
                             child.setSeparator("\\");
                          else
                             child.setSeparator("/");

                     }
                     else
                     {
                          child.setResponseReference(ref);
                          child.setAllowsChildren(true); //It's a directory
with child nodes
                          child.setHasChildren(true);
                          child.setLeadingPath(getWholeServerPath());
                           if(ref.ref.serverOS.equals("Windows"))
                               child.setSeparator("\\");
                            else
                               child.setSeparator("/");
                    }

                    this.insert(child,i);
                 }//end for loop


//ref.ref.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
              }//end try
              catch(IOException ioe){ioe.printStackTrace();}
              catch(NullPointerException npe){npe.printStackTrace();}
           }//end method

           IT IS HERE THAT I RUN INTO PROBLEMS!!!!

All the code you see compiles fine.  What I found annoying is that, at
run-time, the sequence of events were as I depict them here until I start
reading in the names of the childnodes with the
ReceiveChildrenFromServer(...) method.  While it is going through its for
loop, mysteriously the method getChildCount( ) is called again, which in
turn calls defineChildNodes( ), which in turn calls
requestChildCountFromServer(...), which interrupts the processing of the for
loop in ReceiveChildrenFromServer(...) .  Here is the read out from the
console to prove it:

***************************************
    Entering requestChildCountFromServer
    waiting for response...
    checking...
    Received message: ReceivingChildCount
    checking...
    got ChildCount: 26                      <<<Root node has 26 child nodes
    Entering RequestChildrenFromServer()
    path is: C:\JavaProjects
    Finished calling server for children
    Received message: SendingTreeData
    Entering ReceiveChildrenFromServer()
    checking for tree data ...
    child node: AssignmentServer        <<<<ReceiveChildrenFromServer(...)
method begins reading in names
    child node: AssignmentSubmitter
    child node: Borland
    child node: ClientServerJTreeProject
    child node: DBJavaBean
    child node: DirAdmin.bak
    Entering requestChildCountFromServer   <<<This method is called by
defineChildNodes( ) which was

called by getChildCount( )
    waiting for response...
    checking...
    checking...
    Node Expanding.
    checking...
    checking...
    got ChildCount: 0                                      <<< Don't know
why this is reading zero. It should be 26
    child node: DirectoryAdministratorProject  <<<For loop from
ReceiveChildrenFromServer(...) method

resumes reading in names
    child node: EZSmtp
    child node: Icon Editor
    child node: images
    child node: IniFileProject
    child node: J2exe
    child node: JCalculator
    child node: JGridProject
    child node: JSlideShow
    child node: MSSTextEditorProject
    child node: MySQL_JDBC
    child node: PersonalNetSearchProject
    child node: Print_Preview
    child node: PropertiesFileAccessExample
    child node: Sample_EBusiness
    child node: SharewareProject
    child node: SystemTreeProject
    child node: TestProgram
    child node: Thread_Pooling
    child node: ZeroG
    Received message: ReceivingChildCount
*****************************************

Ultimately, I wind up with a root node being displayed in the JTree that
only has maybe five or six child nodes displayed when there should be 26
child nodes.

For further clarity here are the methods requestChildCountFromServer(...)
and RequestChildrenFromServer(...):

    public void requestChildCountFromServer(DefaultTreeNode node)
   {

      System.out.println("Entering requestChildCountFromServer");
      String name = "";
      try
      {
        //ref.ref.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

        output.writeInt(ref.PATH);
        output.flush();
        output.writeUTF(node.getWholeServerPath());
        output.flush();
        output.writeInt(ref.REQUEST_CHILD_COUNT);
        output.flush();
        System.out.println("waiting for response...");
        timer1 = new ChildCountTimer(node);
        timer1.start();
        timer1.join();
        System.out.println("got ChildCount: " + node.numChildren);
        if(node.numChildren > 0)
        {
            //NodeExpanding = false; //reset
            RequestChildrenFromServer(node.getWholeServerPath());
            //Set up TreeDataTimer so that we know we have a
            //response from the server.
            timer2 = new TreeDataTimer(node);
            timer2.start();
            timer2.join();
        }


//ref.ref.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
      }
      catch(InterruptedException ie){}
      catch(IOException ioe){ioe.printStackTrace();}
      catch(NullPointerException npe){npe.printStackTrace();}
    }

    protected void RequestChildrenFromServer(String path)
    {
      System.out.println("Entering RequestChildrenFromServer()");

      //Request Children from server
      try
      {
        //ref.ref.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        output.writeInt(ref.PATH);
        output.flush();
        System.out.println("path is: " + path);
        output.writeUTF(path);
        output.flush();
        //Sending REQUEST_CHILDREN should cause a response
        //from the server: SENDING_TREE_DATA
        output.writeInt(ref.REQUEST_CHILDREN);
        output.flush();

//ref.ref.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

      }
      catch(IOException ioe){ioe.printStackTrace();}
      System.out.println("Finished calling server for children");
    }

I realize this post is rather lengthy, however, I didn't know how else to
explain my dilemma with this project.  If you need more information, just
ask.

Please advise,

Alan
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads