Я недавно купил книгу Грязные богатые клиенты , и я нашел ее действительно полезной и веселой. Основываясь на одном примере из книги, я попытался реализовать пользовательскую панель ScrollPane, которая отображает «тень» в нижней части своего представления над отображаемым компонентом. Я закончил с кодом ниже. Это работает, но не идеально. В частности, когда я прокручиваю панель, перетаскивая полосу прокрутки, все работает хорошо, и картина действительно гладкая. Но когда я прокручиваю с помощью мыши, тень мерцает, и я понятия не имею, почему. Кто-нибудь может мне помочь?
РЕДАКТИРОВАТЬ: То же самое происходит для любого компонента на панели прокрутки. Отредактировал код для отображения двух кадров, чтобы увидеть проблему.
РЕДАКТИРОВАТЬ 2: Я выделил проблему в способ, которым панель прокрутки обрабатывает событие колеса мыши. При прокрутке панель прокрутки копирует содержимое порта просмотра немного вверх или вниз в зависимости от ориентации прокрутки, а затем рисует область, которая появляется в поле зрения. Мой код делает весь компонент «грязным», но это после того, как компонент сместил содержимое. Так что на мгновение вы видите «теневой» градиент не на своем месте, пока не будет выпущен перекрас. Любые идеи о том, как отключить эту функцию?
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 - y-h, 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);
}
}