You are not logged in.

#1 2005-04-13 08:13:04

arooaroo
Member
From: London, UK
Registered: 2005-01-13
Posts: 1,268
Website

Java - JScrollPane problem

Dear Java gurus,

I've been having an odd problem with the JScrollBar. I've made an example class that illustrates the issue. Imagine I have a panel containing a JScrollPane, and within that a component that is likely to be wider than the width of its container (hence the need of the scrollbar.), in this instance, I've put a JLabel with a very long text.

Now, for this app, if the component within the scrollpane is wider, I would like to have the component centered within the scrollpane. I have written a method to achieve this by essentially setting the "value" of the scrollbar so that it is in the middle of its range.

I added a JButton to the bottom of the main panel with an ActionListener added that will run the centering method. Testing this reveals that it does in fact work nicely.

However, what I really want to do if for the scroll pane to be centered without the need for the user to click the button (ie done automatically after the JScrollPane is added to the panel). Well, no problem I thought, as I have the method to center - I can just call this directly after I add the scrollpane. So I did, and this is where the problem occurs. It doesn't center!

Ok, let's have a look at some screenshots. Here is the default app where you see the long label within the scrollpane. No code has been run to try and center the scrollbar.

scroll1.png

If I hit the button to center, this is what happens:

scroll2.png

As you can see, the scroll bar is central. Now, if I amend the code so that I run the same method to center the scroll bar after it's been added to the panel, this is what it looks like:

scroll3.png

The scrollbar has shifted to the left slightly, but I can't see why it's not gone all the way. I can't see why this has happened. Is it some sort of threading issue?

Many thanks. The code is as follows:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class ScrollBarProblem extends JPanel {
    
    private JScrollPane sp;
    
    public ScrollBarProblem() {
        super(new BorderLayout());
        initialise();
    }
    
    private void initialise() {
        
        sp = new JScrollPane(new JLabel("A really really really really really really really really really really really really really really really really really really really really really long string!"));
        add(sp, BorderLayout.CENTER);
        
        JButton center = new JButton("Center scrollbar");
        center.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                centerScrollBar();
                
            }
            
        });
        
        add(center, BorderLayout.SOUTH);
        
        centerScrollBar(); // <-- why does this work here?!
        
    }
    
    private void centerScrollBar() {
        if (sp.getHorizontalScrollBar() != null) {
            int mid = ((sp.getHorizontalScrollBar().getMaximum() - sp.getHorizontalScrollBar().getVisibleAmount()) - sp.getHorizontalScrollBar().getMinimum()) / 2;
            sp.getHorizontalScrollBar().setValue(mid);
            //concScroll.revalidate();
        }

    }
    
    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
    
        JFrame frame = new JFrame("ScrollBar Problem");
        frame.getContentPane().add(new ScrollBarProblem());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 100);
        frame.setVisible(true);
        
        
    }
    
    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();
              }
          });
      }

}

Offline

#2 2005-04-13 09:32:50

sudman1
Member
From: Huntingdon, UK
Registered: 2005-02-18
Posts: 143

Re: Java - JScrollPane problem

The scrollbar has shifted to the left slightly, but I can't see why it's not gone all the way. I can't see why this has happened.

This happens because the JScrollPane has not been 'realized'. Because the frame has not been shown, the layout has not been set yet.

One way to fix it is execute centerScrollBar() after frame.setVisible(true). This works just fine, but I'm not sure it's technically thread-safe.  That being said, it's a quick, simple manipulation, so it should be ok not to run the thread in the Event Dispatch Thread.


v/r
Suds

Offline

#3 2005-04-13 09:45:34

arooaroo
Member
From: London, UK
Registered: 2005-01-13
Posts: 1,268
Website

Re: Java - JScrollPane problem

sudman1 wrote:

One way to fix it is execute centerScrollBar() after frame.setVisible(true). This works just fine, but I'm not sure it's technically thread-safe.  That being said, it's a quick, simple manipulation, so it should be ok not to run the thread in the Event Dispatch Thread.

Thanks for the reply. You are right, it's a threading issue. I did in fact remedy my problem about 10mins after posting (that's always the case with me!) whereby I wrapped my call to centerScrollBar with the SwingUtilities.invokeLater() method (like I did in main()).

Offline

Board footer

Powered by FluxBB