我有JScrollPane
显示(作为其视口视图)MyPanel
,JPanel
的子类。
MyPanel
通过重载paintComponent
来实现自定义绘制。 MyPanel
的可显示内容的总大小通常很宽(意味着比JScrollPane
视口大50倍到200倍)并使用Timer
,我水平滚动查看不同基础MyPanel
的部分。我还允许使用滚动条滑块手动搜索MyPanel
的特定区域。
在我的paintComponent
实现中,我目前正在使用MyPanel
查找当前在视图端口中可见的JViewport#getVisibleRect
部分,并且每次查看端口位置时只绘制该部分改变。
这样可以正常工作 - 但我最终反复重新绘制MyPanel
的可见部分的一小部分,因为定时滚动一次只能移动视口大小的1/50视口。另外,我通常最终会滚动MyPanel
的整个水平范围,因此无论如何我必须至少绘制一次。
这让我想到只绘制一次MyPanel
的全部内容(到BufferedImage
?),然后让JScrollPane
(或JViewport
)处理裁剪blitting只有BufferedImage
所需的区域。
直觉上,在我看来,这是处理此问题的最有效方式,也是一种比较常见的方法。
当我研究Swing教程和其他资源时,我了解到Swing已经是双缓冲的。如果我试图强迫我自己的暴力,独立于Swing功能,听起来我最终会得到三重缓冲。
我没有找到利用JScrollPane
为我做这个的配方(如果存在)。
是否有可用的示例或指示如何执行此操作(如果可能)?
答案 0 :(得分:0)
Swing会自动为您绘制最小的必要组件区域。 repaint(4 args)
仅在组件部分更改且您不希望重新绘制整个可见区域时才有用。在实际操作中,它与repaint(no-args)
具有相同的效果。
如您在问题中所述,自动裁剪区域已经足够小,可以解决问题。您可以在程序中对其进行配置。
此外,您无需担心滚动 - JScrollPane会自动调用其子项的重绘。
您可以轻松地尝试这些:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Test extends JFrame {
private Random rnd = new Random();
private Color c = Color.WHITE;
public Test () {
final JPanel pnl = new JPanel() {
@Override
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.setColor(c);
g.fillRect(0, 0, getWidth(), getHeight());
Rectangle r = g.getClipBounds();
System.out.println(r.width + ", " + r.height);
}
};
pnl.setPreferredSize(new Dimension(10000, 10000));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setLocationRelativeTo(null);
add(new JScrollPane(pnl));
setVisible(true);
new Thread() {
@Override
public void run () {
while (true) {
c = new Color(rnd.nextInt(0xffffff));
pnl.repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
}
}.start();
}
public static void main (String args[]) {
new Test();
}
}