Re: JScrollPane resize /
To: comp.lang.java.gui
So, I finally managed to write an SSCCE for this problem. Actually two
of them, which are almost identical. The first one creates a frame
with a scrollpane in its center and two zoom buttons at the bottom.
The user can zoom in and out, which causes the panel that is the
content of the scrollpane to be resized (double size or half size).
Both SSCCEs try to center the content after the user performed a zoom
in or a zoom out. The first SSCCE completely fails, because the call
to the center() method comes to early. The revalidation of the resized
panel happens asynchronously, so the center() method works on old
values. The second SSCCE uses a component listener so that the
centering can happen AFTER the panel has actually been resized. What
you will notice is that the revalidation causes a repaint and
scrollbar adjustment and then the centering causes another repaint and
scrollbar adjustment. This results in flickering behaviour. I was
wondering whether there is any better way, so that the resizing and
the repositioning can happen in one step. Any help is much
appreciated.
Dirk
1. SSCCE ------------------------------------------
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
public class ScrollPaneTest {
/**
* Constructs the frame with the scrollpane in its center and a
button
* panel, which contains the zoom buttons, in its bottom location.
*/
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
final TestPanel testPanel = new TestPanel();
JScrollPane pane = new JScrollPane(testPanel);
frame.add(pane);
JPanel buttonPanel = new JPanel();
JButton zoomIn = new JButton("Zoom In");
JButton zoomOut = new JButton("Zoom Out");
buttonPanel.add(zoomIn);
buttonPanel.add(zoomOut);
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
testPanel.zoomIn();
}
});
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
testPanel.zoomOut();
}
});
buttonPanel.add(zoomIn);
buttonPanel.add(zoomOut);
frame.add(BorderLayout.SOUTH, buttonPanel);
frame.pack();
frame.setVisible(true);
}
}
/**
* This panel is the content of the scrollpane.
*/
class TestPanel extends JPanel {
private Dimension ps = new Dimension(300, 300);
@Override
protected void paintComponent(Graphics g) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
super.paintComponent(g);
g.drawLine(0, 0, getWidth() - 1, getHeight() - 1);
g.drawLine(0, getHeight() - 1, getWidth() - 1, 0);
}
@Override
public Dimension getPreferredSize() {
return ps;
}
public void zoomIn() {
ps.setSize(ps.getWidth() * 2, ps.getHeight() * 2);
revalidate();
center();
}
public void zoomOut() {
ps.setSize(ps.getWidth() / 2, ps.getHeight() / 2);
revalidate();
center();
}
private void center() {
JViewport viewPort = (JViewport) getParent();
viewPort.setViewPosition(new Point(ps.width -
viewPort.getSize().width, ps.height - viewPort.getSize().height));
}
}
2. SSCCE ------------------------------------------
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
public class ScrollPaneTestWithListener {
/**
* Constructs the frame with the scrollpane in its center and a
button
* panel, which contains the zoom buttons, in its bottom location.
*/
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
final TestPanelWithListener testPanel = new TestPanelWithListener();
JScrollPane pane = new JScrollPane(testPanel);
frame.add(pane);
JPanel buttonPanel = new JPanel();
JButton zoomIn = new JButton("Zoom In");
JButton zoomOut = new JButton("Zoom Out");
buttonPanel.add(zoomIn);
buttonPanel.add(zoomOut);
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
testPanel.zoomIn();
}
});
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
testPanel.zoomOut();
}
});
buttonPanel.add(zoomIn);
buttonPanel.add(zoomOut);
frame.add(BorderLayout.SOUTH, buttonPanel);
frame.pack();
frame.setVisible(true);
}
}
/**
* This panel is the content of the scrollpane. It implements a
component
* listener. It will cause a change of the viewport position when it
receives an
* event letting it know that its own size has changed.
*/
class TestPanelWithListener extends JPanel implements
ComponentListener {
private Dimension ps = new Dimension(300, 300);
public TestPanelWithListener() {
// listens for changes to itself
addComponentListener(this);
}
@Override
protected void paintComponent(Graphics g) {
try {
// Artifically decrease repaint performance to simulate
// real world application behaviour.
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
super.paintComponent(g);
g.drawLine(0, 0, getWidth() - 1, getHeight() - 1);
g.drawLine(0, getHeight() - 1, getWidth() - 1, 0);
}
@Override
public Dimension getPreferredSize() {
return ps;
}
public void zoomIn() {
ps.setSize(ps.getWidth() * 2, ps.getHeight() * 2);
revalidate();
}
public void zoomOut() {
ps.setSize(ps.getWidth() / 2, ps.getHeight() / 2);
revalidate();
}
private void center() {
JViewport viewPort = (JViewport) getParent();
viewPort.setViewPosition(new Point(
(ps.width - viewPort.getSize().width) / 2,
(ps.height - viewPort.getSize().height) / 2));
}
public void componentHidden(ComponentEvent e) {
}
public void componentMoved(ComponentEvent e) {
}
public void componentResized(ComponentEvent e) {
center();
}
public void componentShown(ComponentEvent e) {
}
}
---
* Synchronet * The Whitehouse BBS --- whitehouse.hulds.com --- check it out free usenet!
--- Synchronet 3.15a-Win32 NewsLink 1.92
Time Warp of the Future BBS - telnet://time.synchro.net:24