0

I create the JTree and all its components, then in another class I add it to a JPanel. After that, I add the JPanel to a JFrame; and yes, I've made sure that everything is set to visible, the Panel is added to the frame BEFORE setVisible(), etc.

So why isn't my scrollpane with the JTree showing up?

    package TreeExample;

import java.awt.Color;

    import javax.swing.JComponent;
    import javax.swing.JScrollPane;
    import javax.swing.JTree;
    import javax.swing.tree.DefaultMutableTreeNode;

public class Tree extends JComponent
{
    JTree tree;
    JScrollPane scrollPane;
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("RootNode");

    public Tree()
    {
        setVisible(true);
        setSize(100, 300);
        createChildNodes(root);
        tree = new JTree(root);
        tree.setVisible(true);
        tree.setSize(100, 300);
        scrollPane = new JScrollPane(tree);
        scrollPane.add(tree);
        scrollPane.setVisible(true);
        scrollPane.setSize(100, 300);
        scrollPane.setViewportView(this);
        scrollPane.setBackground(Color.red);
    }

    private void createChildNodes(DefaultMutableTreeNode rootNode)
    {
        DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1");
        DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child 2");
        DefaultMutableTreeNode child3 = new DefaultMutableTreeNode("Child 3");

        rootNode.add(child1);
        rootNode.add(child2);
        rootNode.add(child3);

        DefaultMutableTreeNode grandchild1 = new DefaultMutableTreeNode(
                "Grandchild 1");
        DefaultMutableTreeNode grandchild2 = new DefaultMutableTreeNode(
                "Grandchild 2");

        child1.add(grandchild1);
        child1.add(grandchild2);
    }
}

Here's my panel...

    package TreeExample;

import java.awt.BorderLayout;
import java.awt.TextArea;

import javax.swing.JPanel;

public class Panel extends JPanel
{
    Panel()
    {
        setLayout(new BorderLayout());
        add(new Toolbar(), BorderLayout.NORTH);
        add(new TextArea(), BorderLayout.CENTER);
        add(new Tree(), BorderLayout.WEST);
    }
}

And here's my frame.

package TreeExample;

import javax.swing.JFrame;

public class Frame extends JFrame
{
    Frame()
    {
        setTitle("ToolBar Example");
        add(new Panel());
        pack();
        setVisible(true);
        setSize(500, 500);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    public static void main(String[] args)
    {
        new Frame();
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1
    Bold is for **emphasis.** Please do not bold every word of your post. – VGR Oct 27 '13 at 23:39
  • For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Oct 27 '13 at 23:42
  • 1
    `setSize(100, 300);` Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components. To organize the components for a robust GUI, instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556), along with layout padding & borders for [white space](http://stackoverflow.com/q/17874717/418556). Setting sizes might be (is probably) the cause of this problem. – Andrew Thompson Oct 27 '13 at 23:44

3 Answers3

3

Your class Tree extends JComponent.

You create a JTree and JScrollPane in your class, but you don't add the scrollpane to the component so your Tree component is empty.

You need to set a layout manager for the Tree class add some components to it.

Edit:

scrollPane = new JScrollPane(tree);
//scrollPane.add(tree);

The above code is wrong. First you create a scrollpane with the tree as the parameter. This is correct as the tree is added to the viewport of the scrollpane.

However, then you add the tree to the scrollpane directly which is wrong because a component can only have a single parent so the tree gets removed from the scrollpane.

Comment out the line as shown and then you should be able to use this.add(scrollpane);

camickr
  • 321,443
  • 19
  • 166
  • 288
2

This is pretty much what camickr was noting, but with code as an SSCCE and a few other tweaks. I swapped out the JComponent for a JPanel for simplicity.

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;

public class Frame extends JFrame
{
    Frame()
    {
        setTitle("ToolBar Example");
        add(new Panel());
        //setSize(500, 500);
        setLocationByPlatform(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();  //should be next to last!
        setVisible(true); //should be last!
    }

    public static void main(String[] args)
    {
        new Frame();
    }
}

class Tree extends JPanel
{
    JTree tree;
    JScrollPane scrollPane;
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("RootNode");

    public Tree()
    {
        //setVisible(true);
        //setSize(100, 300);
        createChildNodes(root);
        tree = new JTree(root);
        tree.setVisibleRowCount(5);
        //tree.setVisible(true);
        //tree.setSize(100, 300);
        scrollPane = new JScrollPane(tree);
        //scrollPane.add(tree);
        //scrollPane.setVisible(true);
        //scrollPane.setSize(100, 300);
        //scrollPane.setViewportView(this);
        scrollPane.setBackground(Color.red);
        add(scrollPane);
    }

    private void createChildNodes(DefaultMutableTreeNode rootNode)
    {
        DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1");
        DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child 2");
        DefaultMutableTreeNode child3 = new DefaultMutableTreeNode("Child 3");

        rootNode.add(child1);
        rootNode.add(child2);
        rootNode.add(child3);

        DefaultMutableTreeNode grandchild1 = new DefaultMutableTreeNode(
                "Grandchild 1");
        DefaultMutableTreeNode grandchild2 = new DefaultMutableTreeNode(
                "Grandchild 2");

        child1.add(grandchild1);
        child1.add(grandchild2);
    }
}


class Panel extends JPanel
{
    Panel()
    {
        setLayout(new BorderLayout());
//        add(new Toolbar(), BorderLayout.NORTH);
        // Don't mix Swing & AWT without good cause..
        add(new JTextArea(5,20), BorderLayout.CENTER);
        add(new Tree(), BorderLayout.WEST);
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
1

Take another look at your default constructor for Tree:

JTree tree;
JScrollPane scrollPane;
DefaultMutableTreeNode root = new DefaultMutableTreeNode("RootNode");

public Tree()
{
    setVisible(true);
    setSize(100, 300);
    createChildNodes(root);
    tree = new JTree(root);
    tree.setVisible(true);
    tree.setSize(100, 300);
    scrollPane = new JScrollPane(tree);
    scrollPane.add(tree);
    scrollPane.setVisible(true);
    scrollPane.setSize(100, 300);
    scrollPane.setViewportView(this);
    scrollPane.setBackground(Color.red);
}

Your "Tree" component contains both a JScrollPane and JTree. In your constructor, you attempt to instantiate both objects and then add your JTree to your JScrollPane.

In your current code, you do this poorly. You make a call to JScrollPane(Component) which, according to the docs:

Creates a JScrollPane that displays the contents of the specified component, where both horizontal and vertical scrollbars appear whenever the component's contents are larger than the view.

You then attempt to add the tree again to the JScrollPane once it has already been set as the view and then reset the view again to your custom "Tree" component that does not have any painting logic implemented.

Try removing calls to JSrollPane.add(Component) and JScrollPane.setViewportView(Component) and when you add this component to your "Panel", add the contained JScrollPane instead, like so:

add(new Tree().scrollPane, BorderLayout.WEST);
Taylor Hx
  • 2,815
  • 23
  • 36