滚动时停止 JScrollPane 大量重绘

Stop JScrollPane from high amount of redraws when scrolling

我将文本区中的长文本放置到滚动窗格中。我注意到当我旋转鼠标滚轮时,文本会被严重重绘,甚至可能完全重绘。

这是演示应用程序:

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class TextArea {
  public static void main(String[] args) {
    final JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    final JTextArea textArea = new JTextArea();
    textArea.setColumns(80);
    textArea.setRows(20);
    textArea.setLineWrap(true);
    final JScrollPane scrollPane = new JScrollPane(textArea);
    textArea.append("1234567890 ".repeat(20000));  // Java 11
    frame.add(scrollPane);
    frame.pack();
    frame.setVisible(true);
  }
}

如果您在 sun.java2d.SunGraphics2D.drawString(String, float, float) 方法上放置一个记录断点,则可以很容易地检测到重绘。对我来说,当我将鼠标滚轮旋转一个单位时,它会记录几千次点击(点击次数取决于帧的大小)。如果我在断点处停止,我会看到要绘制的字符串的 y 位置有很大差异,并且差异远远超过我的屏幕高度。

我认为最好只重绘可见的线,或者甚至是新出现的线。

能否以某种方式设置JScrollPane以优化绘制调用的数量?还是Swing中没有优化的东西?

当我 运行 此代码并旋转鼠标滚轮时,GUI 根本不会闪烁或改变。我看到我的滚轮做某事的唯一原因是 JScrollPane 选项卡向上移动。

我使用 Java 14.0.2 编译为 Java 8 标准。我的计算机 运行s 在 Windows 10.

不足为奇,因为文本是相同的。

试试这个完整的运行可用代码,看看它是否有所作为。

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class LargeTextArea implements Runnable {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new LargeTextArea());
    }

    @Override
    public void run() {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        final JTextArea textArea = new JTextArea();
        textArea.setColumns(80);
        textArea.setRows(20);
        textArea.setLineWrap(true);
        textArea.append("1234567890 ".repeat(20000)); // Java 11
        
        final JScrollPane scrollPane = new JScrollPane(textArea);
        frame.add(scrollPane);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}

JTextArea 确实为一条长线生成了过多的绘制调用,似乎它完全重绘了它并且由于软包装,它被拆分了。

然而,更深入一点,可以看出在滚动时,裁剪区域的设置非常严格(对于新可见的 space),因此 Graphics2D 能够跳过裁剪之外的所有字符串的绘制.

所以不用担心,因为实际上应该执行的绘图不多。