0

I have a JScrollPanel and a JPanel added to it. I would like to draw to the JPanel and make the scrollbars of the JScrollPane appear whenever the drawing exceeds the size of the panel and be able to scroll the drawing both vertically and horizontally.

I have tried consulting with various forums and the official docs and tried a few things (setting the borders, the preferred size, etc.) but none seems to yield the desired effects.

I have a JFrame (with GridBagLayout, btw.) :

            JFrame frame1 = new JFrame("Application");
            frame1.setVisible(true);
            frame1.setMinimumSize(new Dimension(580,620));
            frame1.setResizable(false);
            frame1.setLocationRelativeTo(null);
            frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

The relevant components are :

            JPanel panel1 = new JPanel();
            JScrollPane scrollPane = new JScrollPane(panel1);
            frame1.add(scrollPane, gbc_panel1); //added with layout constraints

JPanel :

            panel1.setBackground(Color.BLACK);
            panel1.setPreferredSize(new Dimension(500,500));
            panel1.setMinimumSize(new Dimension(360,360));
            panel1.setMaximumSize(new Dimension(1000,1000));

JScrollPane :

            scrollPane.setAutoscrolls(true);

The relevant code from the action event of a button that does the drawing :

            Graphics g;
            g = panel1.getGraphics();
            panel1.paint(g);
            g.setColor(new Color(0,128,0));

            /* this is followed by some more code that 
            does the drawing of a maze with g.drawLine() methods */

The code does the drawing perfectly, I just can't seem to figure it out how to make the scrolling and dynamic resizing happen.

I would appreciate any helpful comments or remarks!

Thank you!

dice2289
  • 51
  • 3
  • 2
    `g = panel1.getGraphics();` is an incredibly bad idea and you should never do this, nor should you ever do `panel1.paint(g);` for that matter, this shows that you clearly don't understand how custom painting should be done in Swing. You should start by reading [Performing Custom Painting](https://docs.oracle.com/javase/tutorial/uiswing/painting/index.html) and [Painting in AWT and Swing](https://www.oracle.com/technetwork/java/painting-140037.html) works and how you're suppose to work with it. In fact just about any of the Swing tutorials is going to give you more help the posting on SO – MadProgrammer Jan 20 '19 at 23:36
  • [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?](https://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi) (yes) – MadProgrammer Jan 20 '19 at 23:37
  • The size of your component should be determined via the `getPreferredSize` method and you should use some kind of callback to the parent container to tell them when the size of your component changes – MadProgrammer Jan 20 '19 at 23:38
  • Hi! Thanks for the remark! Could you please tell me why is it a bad idea? Is it causing the problem? Thanks! – dice2289 Jan 21 '19 at 05:31
  • Thank you @MadProgrammer! Ultimately rewriting the paint method did the trick - I was just hoping that I could do the painting without having to define my custom JPanel class, but looks like it doesn't work that way. The child class' overridden method is as follows: `public void paintComponent(Graphics g) { super.paintComponent(g); drawMaze(g); }` A separate drawMaze(Graphics g) method contains the fine details of the drawing – dice2289 Jan 21 '19 at 13:03

1 Answers1

0

Ultimately rewriting the paint method did the trick as @MadProgrammer suggested. I was just hoping that I could do the painting without having to define my custom JPanel class, but looks like it doesn't work that way.

The custom class looks like this:

class Drawing extends JPanel {

int mazeSize;

public Drawing(JTextField jtf)
{
    try {
    this.mazeSize = Integer.parseInt(jtf.getText());
    }

    catch (Exception e) 
    {
        JOptionPane.showMessageDialog(this, "ERROR!  Invalid size value!");
    }
} // the constructor gets the size of the drawing from a textField

public Dimension getPreferredSize() {
    return new Dimension(mazeSize*10,mazeSize*10);
} //getPreferredSize - this method is used by the scroll pane to adjust its own size automatically

public void drawMaze (Graphics g) 
{
    /* some irrelevant code that does the desired drawing to the panel by calling g.drawLine()*/

} // drawMaze method that does the de facto drawing

@Override
public void paintComponent(Graphics g) 
{
    super.paintComponent(g);
    drawMaze(g);        
}// paintComponent() @Override method - this was the tricky part

}//Drawing JPanel subclass

It is also worth noting (if some noob like myself happens to stumble upon this question), that after instantiating the new JPanel subclass in the action event, I had to add it to the JScrollPanel in the following way, instead of just simply using its add() method:

Drawing drawPanel = new Drawing(textfield1);
scrollPane.getViewport().add(drawPanel);

Again, thanks for the suggestion!

Once finished with the program (a random maze generator that uses a recursive backtracking algorithm), I will make the source code available at my github profile.

dice2289
  • 51
  • 3
  • Actually, the last bit of code with `scrollPane.getViewport().add(drawPanel);` is what really did the trick! :-) – dice2289 Jan 21 '19 at 13:19