问题
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: http://i.imgur.com/fwJ9LV6.png (Notice the white border at the edge of the grid)
However, same rectangles at [84][82]: http://i.imgur.com/PZ2rNY3.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!
回答1:
The BlastRadiusCanvas
needs to be providing information back to the scroll pane about how big it wants to be.

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);
}
}
回答2:
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.
回答3:
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.
来源:https://stackoverflow.com/questions/14574770/jscrollpane-not-scrolling-past-a-set-size