Solved

JScrollPane not scrolling

Posted on 2000-02-27
14
1,866 Views
Last Modified: 2008-03-17
I am having troubles getting a JScrollPane to correctly scroll when needed.  I have a mainPanel that contains a childPanel.  The childPanel was added to a JScrollPane and then added to the mainPanel, however the childPanel never scrolls, even when needed.  Although when I add the scrollable childPanel directly to the main frame everything works.  Why does putting a scrollable panel into another panel cause things to break?

Here is the code:import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;

public class ScrollPane{

    public static void main(String[] Args)
    {
              JFrame mainFrame = new JFrame();

              final JPanel mainPane = new JPanel();
              final JPanel childPane = new JPanel(){
                               public Dimension getPreferredSize(){ Dimension size = new Dimension(350,100);
                               return size;
                               }

                               public Dimension getMaximumSize(){ Dimension size = new Dimension(350,100);
                               return size;
                               }
                        };
              TitledBorder childBorder = new TitledBorder("ChildPane");
              childPane.setBorder(childBorder);
              childPane.add( new Label("One") );
              childPane.add( new Label("Two") );
              childPane.add( new Label("Three") );
              childPane.add( new Label("Four") );
              childPane.add( new Label("Five") );

              JScrollPane childScrollPane = new JScrollPane( childPane );

              mainPane.add(childScrollPane);
              mainFrame.getContentPane().add(mainPane);
              /*mainFrame.getContentPane().add(childScrollPane);*/


              mainFrame.pack();
              mainFrame.setVisible(true);
       }
}


0
Comment
Question by:troys
  • 8
  • 6
14 Comments
 
LVL 8

Expert Comment

by:diakov
ID: 2563906
The scheme works like this:

Add the jscrollpane to the mainframe, then add the component to scroll to the jscrollpane by:

 scrollpane.setViewportView(myBigComponentToScroll);

Sometimes when the child panel changes size dynamically, you have to notify by calling the JScrollPane1.getViewPort().revalidate()

Greetings,
  Nikolay
0
 

Author Comment

by:troys
ID: 2566503
Edited text of question.
0
 

Author Comment

by:troys
ID: 2566508
Hello Nikolay,

Thanks for the help, but I need the childPane to be scrollable and the mainPane to remain non-scrollable.  

I have a larger application that the above code fits into where making the mainPane scrollable will not work.

I tried playing around with the ViewPort.revalidate() but the childPane still didn't scroll.
0
 
LVL 8

Expert Comment

by:diakov
ID: 2566694
I suggest another design:

ScrollPane.java
---------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;

public class ScrollPane{

  public static void main(String[] Args)
  {
    TestFrame f = new TestFrame();
    f.setSize(300, 200);
    f.pack();
    f.setVisible(true);
  }
}

TestFrame.java
--------------
import java.awt.*;
import javax.swing.*;

public class TestFrame extends JFrame
{
  JScrollPane jScrollPane1 = new JScrollPane();
  JPanel jPanel1 = new JPanel();
  JLabel jLabel1 = new JLabel();
  JLabel jLabel2 = new JLabel();
  JLabel jLabel3 = new JLabel();
  JLabel jLabel4 = new JLabel();
  JLabel jLabel5 = new JLabel();
  JLabel jLabel6 = new JLabel();

  public TestFrame()
  {
    try
    {
      jbInit();
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

  private void jbInit() throws Exception
  {
    jPanel1.setPreferredSize(new Dimension(500, 600));
    jLabel1.setText("jLabel1");
    jLabel2.setText("jLabel2");
    jLabel3.setText("jLabel3");
    jLabel4.setText("jLabel4");
    jLabel5.setText("jLabel5");
    jLabel6.setText("jLabel6");
    this.getContentPane().add(jScrollPane1, BorderLayout.CENTER);
    jScrollPane1.getViewport().add(jPanel1, null);
    jPanel1.add(jLabel1, null);
    jPanel1.add(jLabel2, null);
    jPanel1.add(jLabel3, null);
    jPanel1.add(jLabel4, null);
    jPanel1.add(jLabel5, null);
    jPanel1.add(jLabel6, null);
  }
}

This is scrolling now.

Cheers,
  Nik
0
 

Author Comment

by:troys
ID: 2566893

The problem is that the application that I am working on has a JPanel that contains 2 other JPanels, one that must scroll and one that must not scroll.  Your code above does work, however when you put the jScrollPane1 variable when added to another JPanel, it does not scroll.  This is the problem that I need to solve.

For example I changed the following line, this.getContentPane().add(jScrollPane1, BorderLayout.CENTER);  

to
            JPanel jPanel2 = new JPanel();
            jPanel2.add(jScrollPane1, BorderLayout.CENTER);
            this.getContentPane().add(jPanel2, BorderLayout.CENTER );

Once I do this the scrolling stops.  I agree that without putting a Scrolling Panel into a non scrolling Panel things work.  However this is what I would really like to figure out.

I have found that by using a BoxLayout or a BorderLayout the problem is solved. However the FlowLayout doesn't work. Does anyone know why?

Thanks
0
 

Author Comment

by:troys
ID: 2567061
Adjusted points to 150
0
 
LVL 8

Accepted Solution

by:
diakov earned 150 total points
ID: 2567890
We are in a discussion clearing out your thoughts and intentions about the the example program. Please be patient.

Let me analyse a bit more:

You have a big FRAME: that contains a panel2: that contains a scrollpane: that contains a panel (the one to scroll).

Now, since the frame's content pane does not have scrollong abilities, you have to resize the panel2 inside (if it is not JScrollPane it does not do this by it self) to fit the frame when resized.
Then, the JScrollPane inside the panel2 will resize itself to the size of panel2 leaving panel1 to scroll around.

You really have to play around with the different layouts if you don't want to write the resizing (chained) yourself.

the following code (with the gridlayout as you might have tried already) scrolls the desired set up of panels:

  private void jbInit() throws Exception
  {
    jPanel1.setPreferredSize(new Dimension(500, 600));
    jLabel1.setText("jLabel1");
    jLabel2.setText("jLabel2");
    jLabel3.setText("jLabel3");
    jLabel4.setText("jLabel4");
    jLabel5.setText("jLabel5");
    jLabel6.setText("jLabel6");
//    this.getContentPane().add(jScrollPane1, BorderLayout.CENTER);
    JPanel jPanel2 = new JPanel();
    jPanel2.setLayout(gridLayout1);
    this.getContentPane().setLayout(borderLayout2);
    this.getContentPane().add(jPanel2, BorderLayout.CENTER );
    jPanel2.add(jScrollPane1, null);
    jScrollPane1.getViewport().add(jPanel1, BorderLayout.CENTER );
    jPanel1.add(jLabel1, null);
    jPanel1.add(jLabel2, null);
    jPanel1.add(jLabel3, null);
    jPanel1.add(jLabel4, null);
    jPanel1.add(jLabel5, null);
    jPanel1.add(jLabel6, null);
  }

Note where I've put the gridlayout. In the panel2. The weak place is between the containment of JScrolPane and it's container (panel2). As I mentioned, JScrollPane have to be resized to the visible area which is done by the gridlayout, and for some reason not by the borderlayout.center (which I tought would work).
The flow layout organizes in a totally different way and does not enforce resize of the contained component, rather reposition in a sequence.

Cheers,
  Nik
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

Author Comment

by:troys
ID: 2569500

Thanks for you help.

When you say that the FlowLayout does not enforce resize of the contained component, where did you find this information out.  I looked at the Java API doc page and both FlowLayout and GridLayout both implement the LayoutManager.  I checked the class document for FlowLayout manager and didn't notice anything that would leave me to believe that it wouldn't work correctly in a JScrollPane.  I also looked at JScrollPane and JViewport and didn't find anything that would suggest that FlowLayout wouldn't work.

However, I agree that if you change the layout things beging to work.  I was able to get things to work with BorderLayout as well.  I think that from your original code, the only problem was that setLayout was never called, so the Panels were still using the default LayoutManager, which I think is Flow.

Thanks again for all of your help.  You've answered my original question but if you know exactly why FlowLayout manager doesn't work then I'll double the points.

Thanks
Troy

0
 
LVL 8

Expert Comment

by:diakov
ID: 2569585
http://java.sun.com/docs/books/tutorial/uiswing/layout/flow.html

says :

"FlowLayout puts components in a row, sized at their preferred size. If the horizontal space in the container is too small to put all the components in one row, FlowLayout uses multiple rows. Within each row, components are centered (the default), left-aligned, or right-aligned as specified when the FlowLayout is created. "

Which essentially means that if the FlowLayout won't resize the component if its container size changes. In respect to the example this means that the FlowLayout will use the preferred size of the JScrollPane which in his turn gets it's preferred size from its view port (if no preferred size is set explicitly). The afore mentioned FlowLayout would also resize the container panel (if no preferred size has been set) to host all its components (jscrollpane) in its visible area.

After reading this again, for me the question is solved. Hope this helps.

Cheers,
  Nik
0
 
LVL 8

Expert Comment

by:diakov
ID: 2569599
An addition to the sentence:
"The afore mentioned FlowLayout would also resize the container panel (if no preferred size has been set) to host all its components (jscrollpane) in its visible area."

This is the initial behaviour.

Nik
0
 

Author Comment

by:troys
ID: 2570512

I'm still a bit confused on why the FlowLayout won't work.  I don't understand why FlowLayout doesn't resize.  In the initial example all of the labels are put on one row.  When the space was reduced another row was not added, instead only one row was created and information would just be out of the visible region.

Also, I thought that I tried to catch the resize event and then reset the size of the Panel, that had a FlowLayout.  I also then did a call to invalidate, validate and repaint.  From the link that you listed, it seems like this should work.

I guess the question is, when you have a FlowLayout Panel and you add  components that together are larger than the Panel what does the FlowLayout do?  And what does a BoxLayout or GridLayout do that causes things to work?
0
 
LVL 8

Expert Comment

by:diakov
ID: 2570628
I think, this is because the FlowLayout is set to the outside container A, and not the the container B that directly contains the labels. Container B never gets resized and its initial size (if not set) is enough to host the labels. Try setting preferred size for the B container.
GridLayout resizes the contained component and arranges in a grid-like manner. That is why it works in the example.

Cheers,
  Nik
0
 

Author Comment

by:troys
ID: 2574393
I'm still confused on why FlowLayout doesn't yet other lay managers do.  I caught the resize events and it seems like the inner container is never resized.  I checked this with both  a flowLayout and a BorderLayout of the mainPanel.  But the BorderLayout still did the scroll bars accordingly.

Still a mystery as to exactly why Border and GridLayout work while FlowLayout doesn't.

Thanks,
Troy
0
 

Author Comment

by:troys
ID: 2574404

This code works and helps with the original problem  of the scroll bars not showing up. I don't think that we ever really found out why FlowLayout doesn't work and other Layout managers do.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now