Java - Open JScrollPane with JScrollBar set to the right

2.1k views Asked by At

I'm looking to try and load up a JScrollPane with the horizontal JScrollBar set all the way to the right, i.e. like in this image:

https://i.stack.imgur.com/02BKi.png

However, no matter what I do, I end up with this image:

https://i.stack.imgur.com/Eh50d.png

This is the relevant snippet of my code

    JComponent graph = new TrendsForSuccLarge(wccScores, wccScoresTimes, graphStrings, maxScore, bgColour, iPadWidth);

    JScrollPane graphScrollPane = new JScrollPane(graph, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

    JScrollBar horizontal = graphScrollPane.getHorizontalScrollBar();
    horizontal.setValue( horizontal.getMaximum() );

    this.getContentPane().add(graphScrollPane, BorderLayout.CENTER);

Any ideas of what's going wrong?

Thanks in advance!

Kesh

SSCCE

import javax.swing.JFrame;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

class ForStackOverflow  {

    private static JFrame main;
    //opens up a line chart on full screen

    public static void main(String args[]) {

        TempGraph tg = new TempGraph(main);
        tg.setVisible(true);

    }
}

class TempGraph extends JDialog {

    private static final long serialVersionUID = 1L;

    //opens up a line chart on full screen

    public TempGraph(JFrame parent)
    {
        // load the frame
        super(parent,true);
        configureFrame();
    }

    private void configureFrame()
    {

        int iPadHeight = 644;
        int iPadWidth = 981;

        this.getContentPane().setLayout(new BorderLayout());

        JComponent graph = new TrendsForSuccLarge2(iPadWidth);

        JScrollPane graphScrollPane = new JScrollPane(graph, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        this.getContentPane().add(graphScrollPane, BorderLayout.CENTER);

        JPanel buttons = new JPanel();
        buttons.setLayout(new BorderLayout());

        JButton ok = new JButton("Done");
        ok.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                next();
            }
        });
        buttons.add(ok,BorderLayout.CENTER);
        JButton exit = new JButton("Exit");
        exit.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        buttons.add(exit,BorderLayout.WEST);

        this.getContentPane().add(buttons, BorderLayout.SOUTH);

        this.pack();        
        this.setSize(this.getWidth(), 750);
        this.setResizable(true);
        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        int widthFrame = iPadWidth;
        int heightFrame = iPadHeight;
        this.setSize(widthFrame, heightFrame);
        setBounds((screenSize.width - this.getWidth()) / 2,
                (screenSize.height - this.getHeight()) / 2, 
                getWidth(),
                getHeight());
    }

    private void next()
    {
        this.setVisible(false);
    }

}

class TrendsForSuccLarge2 extends JComponent {

    // basic parameters
    private static int PREF_W = 200;
    private static final int PREF_H = 200;
    private static final int BORDER_GAP = 10;
    private static final int GRAPH_GAP = BORDER_GAP + 20;

    private int graphWidth = 0;

    private static final long serialVersionUID = 1L;

    TrendsForSuccLarge2(int prefGraphWidth) {

        graphWidth = prefGraphWidth;

        paintComponent(null);
    }

    public void paint(Graphics g) { 

        int windowWidth = 2600;

        PREF_W = windowWidth;

        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g2.drawString("Hello", graphWidth/2, getHeight() - GRAPH_GAP);

        g2.drawString("Hello1", graphWidth - GRAPH_GAP, getHeight() - GRAPH_GAP);

        g2.drawString("Hello2", windowWidth - GRAPH_GAP - GRAPH_GAP, getHeight() - GRAPH_GAP);

        // create x and y axes 
        g2.setColor(Color.black);
        g2.drawLine(GRAPH_GAP, getHeight() - GRAPH_GAP, GRAPH_GAP, GRAPH_GAP);
        g2.drawLine(GRAPH_GAP, getHeight() - GRAPH_GAP, windowWidth - GRAPH_GAP, getHeight() - GRAPH_GAP);

    }

    public Dimension getPreferredSize() {
        return new Dimension(PREF_W, PREF_H);
    }

}
4

There are 4 answers

0
Keshava Murthy On BEST ANSWER

I solved this, apparently the issue was that my component had a preferred size that was too small. I rammed the preferred size up and everything sorted itself.

1
topher On

From the Javadoc :

javax.​swing.​JScrollBar
public void setValue(int i)
Sets the current value of the adjustable object. If the value supplied is less than minimum or greater than maximum - visibleAmount, then one of those values is substituted, as appropriate. Calling this method does not fire an AdjustmentEvent.
Parameters:
v - the current value, between minimum and maximum - visibleAmount

And I don't really know why it seems that the maximum value, using getMaximum() returns 100.
and the visible amount value, using getVisibleAmount() returns 10.
So, the scroll's value when you call setValue(9999) won't be greater than 90.

And my solution is, set the maximum with some high value first, then set the value :

myScrollPane.getHorizontalScrollBar().setMaximum(1500);
myScrollPane.getHorizontalScrollBar().setValue(1500);

2
arcy On

In answer to your question of whether I know what's going on, I'd have to say "only partially".

The problem appears to be that the scrollbar value is getting set before the UI is fully realized (or something similar -- I do not understand Swing internals enough to know just what all the various levels and terms are).

I got it to work by inserting the following code:

SwingUtilities.invokeLater
(
  new Runnable()
  {
    public void run()
    {
      graphScrollPane.getHorizontalScrollBar().setValue(1000);
    }
  }
);

just before the end of the configureFrame() method in TempGraph.

4
camickr On

the full code is here:

The code you posted doesn't compile since we don't have access to all your custom classes. Post a proper SSCCE when you have a question.

horizontal.setValue( horizontal.getMaximum() ); 

You need to invoke that code AFTER the dialog is visible.