1

I'm using a scroll pane, with a JPanel inside that draws a grid of squares that are objects from a [][] array.

IF the array is [83][81] of size 18^2 rectangles it looks like: https://i.stack.imgur.com/MEBrt.png (Notice the white border at the edge of the grid)

However, same rectangles at [84][82]: https://i.stack.imgur.com/36WGm.png (The last rows get sliced).

Now, I've:

  • Increased the preferred and Max sizes of both the scroll pane and the Jpanel to well above what is needed.
  • Checked that the JPanel is the viewport of the scrollable object.

And it hasn't changed anything.

My Jpanel Class is:

package BlastRadius;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JPanel;

/**
 * Canvas Class Stuart Bradley 25-1-2013 Contains the paint component
 */
public class BlastRadiusCanvas extends JPanel {

    GridOfNodes grid = new GridOfNodes();

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        RenderingHints rh = g2d.getRenderingHints();
        rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHints(rh);

        //Draw space
        int pixelsAcross = 32;
        int pixelsDown = 0;
        int size = 18;
        for (int i = 0; i < grid.getRows(); i++) {
            for (int j = 0; j < grid.getColumns(); j++) {
                g2d.setColor(grid.getNodeGrid()[i][j].getColour());
                g2d.fillRect(pixelsAcross, pixelsDown, size, size);
                g2d.setColor(new Color(0, 0, 0));
                g2d.drawRect(pixelsAcross, pixelsDown, size, size);
                //Better Ovals maybe needed, try Ellipise2D class

                if (grid.getNodeGrid()[i][j].getHasOval() == true) {
                    g2d.setColor(new Color(255, 255, 255));
                    g2d.fillOval((pixelsAcross + (size / 2) - 1), (pixelsDown + (size / 2) - 1), size / 4, size / 4);
                }
                pixelsAcross += 18;
            }
            pixelsDown += 18;
            pixelsAcross = 32;
            //Draws gene string for first object in each row
            g2d.setColor(new Color(0, 0, 0));
            g2d.drawString(grid.getNodeGrid()[i][0].getGeneString(), 5, pixelsDown - 5);
        }
    }
}

Scroll pane and related, can post the entire GUI class if needed:

jScrollPane1 = new javax.swing.JScrollPane();
jScrollPane1.setPreferredSize(new java.awt.Dimension(10000, 10000));
jScrollPane1.setViewportView(drawingJPanel);

//Grouping 

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
        );

While I've done GUI's before, both via RAD environments and by hand, scrollable interfaces are somewhat new to me!

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Darkstarone
  • 4,590
  • 8
  • 37
  • 74

3 Answers3

5

The BlastRadiusCanvas needs to be providing information back to the scroll pane about how big it wants to be.

enter image description here

Based on my interpretation of what it is your trying to do, try adding the following to your BlastRadiusCanvas

@Override
public Dimension getPreferredSize() {
    return new Dimension((grid.getColumns() * 18) + 64, (grid.getRows() * 18) + 1);
}

Now really, you shouldn't rely on "magic" numbers, it would be better to use something like...

protected static final int GRID_SIZE = 18;
protected static final int H_GAP = 32;

@Override
public Dimension getPreferredSize() {
    return new Dimension((grid.getColumns() * GRID_SIZE) + (H_GAP * 2), (grid.getRows() * GRID_SIZE) + 1);
}

This would make your paintComponent method look more like...

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    RenderingHints rh = g2d.getRenderingHints();
    rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setRenderingHints(rh);

    //Draw space
    int pixelsAcross = H_GAP;
    int pixelsDown = 0;
    int size = GRID_SIZE;
    for (int i = 0; i < grid.getRows(); i++) {
        for (int j = 0; j < grid.getColumns(); j++) {
            g2d.setColor(grid.getNodeGrid()[i][j].getColour());
            g2d.fillRect(pixelsAcross, pixelsDown, size, size);
            g2d.setColor(new Color(0, 0, 0));
            g2d.drawRect(pixelsAcross, pixelsDown, size, size);
            //Better Ovals maybe needed, try Ellipise2D class

            if (grid.getNodeGrid()[i][j].getHasOval() == true) {
                g2d.setColor(new Color(255, 255, 255));
                g2d.fillOval((pixelsAcross + (size / 2) - 1), (pixelsDown + (size / 2) - 1), size / 4, size / 4);
            }
            pixelsAcross += size;
        }
        pixelsDown += size;
        pixelsAcross = H_GAP;
        //Draws gene string for first object in each row
        g2d.setColor(new Color(0, 0, 0));
        g2d.drawString(grid.getNodeGrid()[i][0].getGeneString(), 5, pixelsDown - 5);
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thanks, regardless of whatever I did below - this is a much more elegant solution to the problem. Also I'm well aware of how awful using the numbers are, and that was next on my to-do list for the program as a clean up before getting ready to import real data! Cheers! – Darkstarone Jan 29 '13 at 03:39
5

Because BlastRadiusCanvas contains no components of its own, you can override getPreferredSize() to return the optimal size to display the grid. See this related answer for more details. Also consider implementing the Scrollable interface to return a suitable Dimension from getPreferredScrollableViewportSize(). The image appears to have natural unit and block sizes.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I got that from Mad above, but doesn't Jpanel already implement Scrollable? Or have I been misled? – Darkstarone Jan 29 '13 at 03:40
  • 1
    No, `JPanel` is a `JComponent` with a default layout and minimal UI delegate. `Scrollable` is way to provide additional geometry to the scroll pane, over and above `getPreferredSize()`. – trashgod Jan 29 '13 at 03:48
0

Incase anyone else has the same issue - since hours of googling didn't fix it for me.

Check your JFrame preferred size. If it's too low, it maxes out the amount of grid - or any draw space - you have.

Darkstarone
  • 4,590
  • 8
  • 37
  • 74
  • 2
    Your problem has little/nothing to do with you frame's preferred size, you frame should be calculating it's preferred size based on the preferred size it's contents. Your problem deals with the fact that (as far as I can tell) your `BlastRadiusCanvas` isn't providing sizing hints back to the scroll pane... – MadProgrammer Jan 29 '13 at 03:15
  • I figured as much, but when I changed it, it fixed the issue, didn't give proper sizing like your answer, but it showed everything + lots of extra space. – Darkstarone Jan 29 '13 at 03:37