我正在尝试在JScrollPane上绘制一个红色正方形。我下面的代码做得还不错,但有时当我快速滚动视口时,红色正方形会向上或向下跳动。
这让我感到奇怪,因为JScrollPane本身是静止的,所以我认为Swing不会试图移动其中绘制的组件。我猜想实际发生的是,红色正方形与视口关联,而视口显示的图形确实会移动。
无论如何,我该如何防止红色正方形跳来跳去并成功地在列表上绘制红色正方形?也许我完全采取了错误的方法。
这让我感到奇怪,因为JScrollPane本身是静止的,所以我认为Swing不会试图移动其中绘制的组件。我猜想实际发生的是,红色正方形与视口关联,而视口显示的图形确实会移动。
无论如何,我该如何防止红色正方形跳来跳去并成功地在列表上绘制红色正方形?也许我完全采取了错误的方法。
package components;
import java.awt.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.*;
@SuppressWarnings("serial")
public class DialogWithScrollPane extends JFrame {
public DialogWithScrollPane() {
super();
setResizable(false);
Container pane = getContentPane();
Vector<Object> listOfStuff = new Vector<Object>();
for (int i = 0; i < 100; i++) {
listOfStuff.add(Integer.toString(i));
}
final JScrollPane scrollPane = new JScrollPane() {
public void paint(Graphics g) {
System.out.println("JScrollPane.paint() called.");
super.paint(g);
g.setColor(Color.red);
g.fillRect(20, 50, 100, 200);
}
};
JList list = new JList(listOfStuff) {
public void paint(Graphics g) {
System.out.println("JList.paint() called.");
super.paint(g);
// Well, I could do this...
//
// scrollPane.repaint();
//
// ...and it would solve the problem, but it would also result in an
// infinite recursion since JScrollPane.paint() would call this
// function again.
}
};
// Repaint the JScrollPane any time the viewport is moved or an item in the
// list is selected.
scrollPane.getViewport().addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
scrollPane.repaint();
}
});
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
scrollPane.repaint();
}
});
scrollPane.setViewportView(list);
pane.add(scrollPane);
setMinimumSize(new Dimension(300, 300));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocation(500, 250);
setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new DialogWithScrollPane();
}
});
}
}