Search code examples
javaswingjframejscrollpanejcomponent

JScrollPane scrollbars not scrollable


I have a class that draw some very simple graphics like lines, circles and rectangles. The lines are dynamically expandable and sometimes when they expand beyond the resolution, it is impossible to see without a scroll bar. Therefore, I've added JScrollPane to my JFrame but unfortunately, the scroll bar is not scrollable despite calling the Layout Manager already.

Here's what I have: - A class that draws components (lines, rectangles, circles) - A class that sets up the JFrame/JScrollPane

Here's an excerpt code of my GUI class:

    JFrame frame = new JFrame("GUIFrame");
    frame.setLayout(new BorderLayout()); // Layout already set
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    DrawComponent comp = new DrawComponent(); // Reference to class that draw components
    JScrollPane sp = new JScrollPane(comp, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
    sp.setPreferredSize(new Dimension(1000, 1000));

    frame.add(sp, BorderLayout.CENTER);
    frame.setSize(500,500);
    frame.setVisible(true);

With the code above, I've got Java to show me a JFrame with scrollpane containing my jcomponents. I have set the scrollbars to always appear as shown above but they are not scrollable, gray-ed out.

As suggested by Andrew, I took sometime to create a SSCCE to reflect what I'm trying to do:

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.util.Random;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;


public class DrawTest {
    public static void main(String[] args){
        JFrame frame = new JFrame("SSCCE");
        frame.setLayout(new BorderLayout());
        frame.setSize(1000, 1000);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       

        DrawComp d = new DrawComp();
        JScrollPane sp = new JScrollPane(d, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

        frame.add(sp);      
        frame.setVisible(true);
    }
}

class DrawComp extends JComponent {

    public void paintComponent(Graphics g){
        Graphics2D g2 = (Graphics2D)g;

        Random ran = new Random();
        int ranNum = ran.nextInt(10);
        System.out.println(ranNum);
        double length = 100 * ranNum;
        g2.draw(new Line2D.Double(10, 10, length, length));
    }
}

The code above draws a diagonal line based on a random input. What I intend to do is that when the line gets so long that it goes out of the frame size, I hope that I'll be able to scroll and have a view of the full line. Again I have added the line component to JScrollPane but it's not scroll-able.


Solution

  • My apologies. You are using JScrollPane the right way. I ran your code and I think I got the reason why JScrollPane is not working. Picture this, when your set the jframe's background to all red (by paiting a red dot everywhere) should the jscrollpane be scrollable? No, because painting the background color is in the background. The actual VIEW isnt changing and it is not bigger then the display size so the scrollpane does not see the point of scrolling. Your paint component method is doing something similar. It is just drawing something in the background. The actual VIEW didnt change so scrollpane wont work.

    public class DrawTest {
        public static void main(String[] args){
            JFrame frame = new JFrame("SSCCE");
            frame.setLayout(new BorderLayout());
            frame.setSize(500, 500);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       
    
            final DrawComp d = new DrawComp();
            final JScrollBar hbar,vbar;
            hbar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 1, 0, 500);
            vbar = new JScrollBar(JScrollBar.VERTICAL, 0, 1, 0, 500);
    
            frame.setLayout(null);
            frame.add(d);      
            frame.add(hbar);      
            frame.add(vbar);      
            d.setBounds(0, 0, 300, 300);
            vbar.setBounds(460, 0, 20, 480);
            frame.setVisible(true);
    
            vbar.addAdjustmentListener(new AdjustmentListener() 
            {
                public void adjustmentValueChanged(AdjustmentEvent e) 
                {
                    d.setLocation(d.getX(), -vbar.getValue());
                }
            });
        }
    }
    

    Here is the code for sliding a component vertically. I made some changes to your existing code. The DrawComp is still the same