If you create a JScrollPane that has a viewport larger than the JScrollPane\'s component, it displays that component in the upper left.
Is there any way to change this b
JPanel
into the scroll-paneGridBagLayout
.This is the technique used in the Nested Layout Example, which places the red/orange image into the center of the parent.
I simply added a JPanel
to the JScrollPane
to which I added the THINGY JPanel
. Hope this is what you wanted :
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class SimpleScroller extends JFrame {
static class Thingy extends JPanel
{
private double size = 20.0;
@Override public Dimension getPreferredSize() {
int isize = (int) this.size;
return new Dimension(isize, isize);
}
@Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
int[] x = {0, 100, 100, 0, 0, 75, 75, 25, 25, 50};
int[] y = {0, 0, 100, 100, 25, 25, 75, 75, 50, 50};
Graphics2D g2d = (Graphics2D) g;
AffineTransform at0 = g2d.getTransform();
g2d.scale(size/100, size/100);
g.drawPolyline(x, y, x.length);
g2d.setTransform(at0);
}
public void setThingySize(double size) {
this.size = size;
revalidate();
repaint();
}
public double getThingySize() { return this.size; }
}
public SimpleScroller(String title) {
super(title);
final Thingy thingy = new Thingy();
setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.add(thingy);
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(panel);
add(scroll, BorderLayout.CENTER);
final SpinnerNumberModel spmodel =
new SpinnerNumberModel(thingy.getThingySize(),
10.0, 2000.0, 10.0);
spmodel.addChangeListener(new ChangeListener() {
@Override public void stateChanged(ChangeEvent e) {
thingy.setThingySize((Double) spmodel.getNumber());
}
});
add(new JSpinner(spmodel), BorderLayout.NORTH);
}
public static void main(String[] args) {
new SimpleScroller("simple scroller").start();
}
private void start() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
}
}
Here is the output :
With the suggestion from Andrew, you can't have the view smaller than the viewport (and still centered).
The cleanest way is doing it directly from the layout manager, overriding ViewportLayout. There is an implementation in the source of:
http://www.randelshofer.ch/multishow
Look for the class ZoomableViewportLayout, which does the job perfectly.
Accepting your both comments, but
yes... although I'd really like to arbitrarily position it
there are
important methods to avoiding flickering or jumping on the JViewport
JViewport.setScrollMode(JViewport.BLIT_SCROLL_MODE); JViewport.setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE); JViewport.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
and
I don't want to paint to the JViewport, at least not directly -- My real code is a component subclassed from JPanel, as in my example, but it also has other GUI elements in it.
you can use JXLayer (Java6) or parts of methods from JXLayer implemented to the JLayer (Java7) directly
could be too hard, but in all cases you can overlay whatever with JLabel
Notice
all my suggestion to consume MouseEvent by default, J(X)Layer and JLabel with KeyEvents too, but there no issue with redispatch events from ---> to another JComponent
EDIT
wait: no, I don't want to paint the spiral (what you called "snake") in the center of the JScrollPane; I want to paint my component and have my component be displayed in the center of the JScrollPane.
a) JPanel returns Dimension
b) JViewport return Dimension
a) you can centering Dimmension from JPanel (Point) to the center of JViewport (Point)
b) if is there JComponent you can move the JViewport to any getBounds() tha returned JComponent or Point from JPanel inside JScrollPane