如何在JScrollPane上禁用滚轮滚动事件的默认绘制行为

我最近购买了Filthy Rich Clients这本书,我发现它非常有用和有趣。 在本书的一个例子的基础上,我尝试实现一个自定义ScrollPane,它在要显示的组件的视图底部显示一个“阴影”。 我最终得到了以下代码。 它工作但不完美。 特别是当我通过拖动滚动条滚动窗格时,一切正常,绘画非常流畅。 但是当我用鼠标滚动滚动时,阴影闪烁,我不明白为什么。 谁能帮我?

编辑:滚动窗格中的任何组件都会发生同样的事情。 编辑代码以显示两个帧以查看问题。

编辑2:我已将问题与滚动窗格处理鼠标滚轮事件的方式隔离开来。 滚动滚动窗格时,根据滚动的方向稍微向上或向下复制视口的内容,然后绘制进入视图的区域。 我的代码使整个组件“脏”但是在组件移动了内容之后。 所以你会看到“影子”渐变不合适,直到发出重画。 有关如何禁用此function的任何想法?

import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Container; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.image.BufferedImage; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.RepaintManager; public class Test { public static void main(String[] args) { JFrame f = new JFrame("Table"); JFrame f1 = new JFrame("Text Area"); Object[] names = new Object[] { "Title", "Artist", "Album" }; String[][] data = new String[][] { { "Los Angeles", "Sugarcult", "Lights Out" }, { "Do It Alone", "Sugarcult", "Lights Out" }, { "Made a Mistake", "Sugarcult", "Lights Out" }, { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, { "Los Angeles", "Sugarcult", "Lights Out" }, { "Do It Alone", "Sugarcult", "Lights Out" }, { "Made a Mistake", "Sugarcult", "Lights Out" }, { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, { "Los Angeles", "Sugarcult", "Lights Out" }, { "Do It Alone", "Sugarcult", "Lights Out" }, { "Made a Mistake", "Sugarcult", "Lights Out" }, { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, { "Los Angeles", "Sugarcult", "Lights Out" }, { "Do It Alone", "Sugarcult", "Lights Out" }, { "Made a Mistake", "Sugarcult", "Lights Out" }, { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, { "Los Angeles", "Sugarcult", "Lights Out" }, { "Do It Alone", "Sugarcult", "Lights Out" }, { "Made a Mistake", "Sugarcult", "Lights Out" }, { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, { "Going Missing", "Maximo Park", "A Certain Trigger" } }; JTable table = new JTable(data, names); f.getContentPane().add(new ShadowScrollPane(table)); f1.getContentPane().add(new ShadowScrollPane(new JTextArea(20, 50))); RepaintManager.setCurrentManager(new RepaintManager(){ @Override public void addDirtyRegion(JComponent c, int x, int y, int w, int h) { Container con = c.getParent(); while (con instanceof JComponent) { if (!con.isVisible()) { return; } if (con instanceof ShadowScrollPane ) { c = (JComponent)con; x = 0; y = 0; w = con.getWidth(); h = con.getHeight(); } con = con.getParent(); } super.addDirtyRegion(c, x, y, w, h); } }); f.pack(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); f1.pack(); f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f1.setVisible(true); } } @SuppressWarnings("serial") class ShadowScrollPane extends JScrollPane { private final int h = 50; private BufferedImage img = null; private BufferedImage shadow = new BufferedImage(1, h, BufferedImage.TYPE_INT_ARGB); public ShadowScrollPane(JComponent com) { super(com); Graphics2D g2 = shadow.createGraphics(); g2.setPaint(new Color(50, 50, 50)); g2.fillRect(0, 0, 1, h); g2.setComposite(AlphaComposite.DstIn); g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h, new Color(1, 1, 1, 0.6f))); g2.fillRect(0, 0, 1, h); g2.dispose(); } @Override public void paint(Graphics g) { if (img == null || img.getWidth()!=getWidth() || img.getHeight() != getHeight()) { img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); } Graphics2D g2 = img.createGraphics(); super.paint(g2); Rectangle bounds = getViewport().getVisibleRect(); g2.scale(bounds.getWidth(), -1); int y = (getColumnHeader()==null)?0:getColumnHeader().getHeight(); g2.drawImage(shadow, bounds.x, -bounds.y - yh, null); g2.scale(1,-1); g2.drawImage(shadow, bounds.x, bounds.y + bounds.height-h+y, null); g2.dispose(); g.drawImage(img, 0, 0, null); } } 

您是否尝试在ScrollPane对象上调用setWheelScrollingEnabled(false)?

来自javadoc:

启用/禁用滚动以响应鼠标滚轮的移动。 轮盘滚动默认启用。

在Savvas下面的评论之后更新。

也许视口上的“setScrollMode(int)”方法可以帮助您。 此方法将确定swing如何滚动视口。

您可以使用getViewPort()方法直接从ScrollPane获取视口。 您有以下选择:

 BLIT_SCROLL_MODE BACKINGSTORE_SCROLL_MODE SIMPLE_SCROLL_MODE 

根据javadoc BLIT_SCROLL_MODE将使用Graphics.copyArea所以也许尝试其他一个。