Search code examples
javaswingjframejtableobservers

Pass Object into class that extends JFrame


I need help with passing an Object from one class to another that extends JFrame, whenever that method is called. So far this is what I have. I need to pass the added circle to the NodeTracker class and make sure it displays the added object.

public class Nodes
{
   ArrayList<Circle> circles;
   ArrayList<Squares> squares;

   public Node()
   {
       circles = new ArrayList<Circles>();
       squares = new ArrayList<Squares>();
   }

   public void addCircle(Circle c)
   {
       circles.add(c);
       // Here I want to implement a method that allows me to pass "c"
       // to the NodeTracker
   }

}

// All I have so far that opens a blank table.
public class NodeTracker extends JFrame 
{

    private JPanel topPanel;
    private JTable table;
    private JScrollPane scrollPane;

    public NodeTracker()
    {
        setTitle("Node Tracker");
        setSize(700, 700);

        topPanel = new JPanel();
        topPanel.setLayout(new BorderLayout());
        getContentPane().add(topPanel);

        String columns[] = { "Color", "Radius" };

        String data[][] =
        {
            //whenever added, would update
            //{circle.color, circle.radius},
            //{circle.color, circle.radius}
        };

        table = new JTable(data, columns);

        scrollPane = new JScrollPane(table);
        topPanel.add(scrollPane, BorderLayout.CENTER);
    }

    //Temporary
    public static void main( String args[] )
    {
        NodeTracker mainFrame = new NodeTracker();
        mainFrame.setVisible( true );
    }
}

Thank you so much.


Solution

  • // Here I want to implement a method that allows me to pass "c" to the NodeTracker"

    No, you don't. You want to implement an Observer Pattern. Nodes shouldn't care who is listening for changes, only that when addCircle is called, it will tell them.

    This way NodeTracker would register an interest in Nodes to be told when a circle is added and would then be able to respond to in some meaningful fashion

    This is a pretty key concept in Swing and is implemented through it's "listener" API

    Start by defining a interface which describes the events that the Nodes class will generate

    public interface NodesListener {
        public void nodesCircleWasAdded(Nodes source, Circle circle);
    }
    

    Next, add support for the new listener into Nodes, allowing other classes to register/deregister interest and for actually triggering the events

    public class Nodes {
    
        ArrayList<Circle> circles;
        ArrayList<Squares> squares;
        private List<NodesListener> listeners;
    
        public Nodes() {
            circles = new ArrayList<Circles>();
            squares = new ArrayList<Squares>();
            listeners = new ArrayList<>(25);
        }
    
        public void addNodesListener(NodesListener listener) {
            listeners.add(listener);
        }
    
        public void addCircle(Circle c) {
            circles.add(c);
            for (NodesListener listener : listeners) {
                listener.nodesCircleWasAdded(this, c);
            }
        }
    
    }
    

    Finally, create an instance of Nodes or pass a pre-existing instance to the class and register your interest in getting notifications from it...

    public class NodeTracker extends JFrame {
    
        private JPanel topPanel;
        private JTable table;
        private JScrollPane scrollPane;
        private Nodes nodes;
    
        public NodeTracker() {
            setTitle("Node Tracker");
            setSize(700, 700);
    
            nodes = new Nodes();
            nodes.addNodesListener(new NodesListener() {
                @Override
                public void nodesCircleWasAdded(Nodes source, Circle circle) {
                    // A circle was added
                }
            });
    
            topPanel = new JPanel();
            topPanel.setLayout(new BorderLayout());
            getContentPane().add(topPanel);
    
            String columns[] = {"Color", "Radius"};
    
            String data[][]
                            = { //whenever added, would update
                            //{circle.color, circle.radius},
                            //{circle.color, circle.radius}
                            };
    
            table = new JTable(data, columns);
    
            scrollPane = new JScrollPane(table);
            topPanel.add(scrollPane, BorderLayout.CENTER);
        }
    
        //Temporary
        public static void main(String args[]) {
            NodeTracker mainFrame = new NodeTracker();
            mainFrame.setVisible(true);
        }
    }