JScrollPane的滚动事件
奇怪的是, JScrollPane
没有方法addAdjustmentListener()
。 然而,adjustListener据说与滚动条一起使用。 每当JScrollPane
以任何一种方式滚动时,我都希望发生一些事情。 怎么实现这样的事情?
为什么不获得实际的滚动条,然后向它们添加调整侦听器? JScrollBar
有一个名为addAdjustmentListener()
的方法。
您可以使用getVerticalScrollBar()
和getHorizontalScrollBar()
从JScrollPane
获取JScrollBar
而不是尝试从JScrollPane侦听更改,获取该滚动窗格的视口添加更改侦听器:
根据Jesse Barnum的说法:
// requiring that you already have JPanel additionsPane inside // JScrollPane additionsScrollPane inside JFrame frame ... additionsScrollPane.getViewport().addChangeListener(new ListenAdditionsScrolled()); public class ListenAdditionsScrolled implements ChangeListener{ public void stateChanged(ChangeEvent e){ additionsPane.revalidate(); frame.repaint(); } }
例如(old.good.forums.sun.com)
import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; import javax.swing.*; public class TilePainter extends JPanel implements Scrollable { private static final long serialVersionUID = 1L; private final int TILE_SIZE = 50; private final int TILE_COUNT = 100; private final int visibleTiles = 10; private final boolean[][] loaded; private final boolean[][] loading; private final Random random; public TilePainter() { setPreferredSize(new Dimension(TILE_SIZE * TILE_COUNT, TILE_SIZE * TILE_COUNT)); loaded = new boolean[TILE_COUNT][TILE_COUNT]; loading = new boolean[TILE_COUNT][TILE_COUNT]; random = new Random(); } public boolean getTile(final int x, final int y) { boolean canPaint = loaded[x][y]; if (!canPaint && !loading[x][y]) { loading[x][y] = true; Timer timer = new Timer(random.nextInt(500), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { loaded[x][y] = true; repaint(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE); } }); timer.setRepeats(false); timer.start(); } return canPaint; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Rectangle clip = g.getClipBounds(); int startX = clip.x - (clip.x % TILE_SIZE); int startY = clip.y - (clip.y % TILE_SIZE); for (int x = startX; x < clip.x + clip.width; x += TILE_SIZE) { for (int y = startY; y < clip.y + clip.height; y += TILE_SIZE) { if (getTile(x / TILE_SIZE, y / TILE_SIZE)) { g.setColor(Color.GREEN); } else { g.setColor(Color.RED); } g.fillRect(x, y, TILE_SIZE - 1, TILE_SIZE - 1); } } } @Override public Dimension getPreferredScrollableViewportSize() { return new Dimension(visibleTiles * TILE_SIZE, visibleTiles * TILE_SIZE); } @Override public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { return TILE_SIZE * Math.max(1, visibleTiles - 1); } @Override public boolean getScrollableTracksViewportHeight() { return false; } @Override public boolean getScrollableTracksViewportWidth() { return false; } @Override public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { return TILE_SIZE; } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame("Tiles"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.getContentPane().add(new JScrollPane(new TilePainter())); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } }