滚动时阻止JScrollPane进行大量重绘

问题描述

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

这是演示应用程序:

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标准。我的计算机在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的确会产生过多的长线绘制调用,似乎完全重绘了该绘制,并且由于软包装的缘故,它被拆分了。

但是,更深入地说,可以看到,在滚动时,剪切区域设置得非常严格(设置为新可见的空间),因此Graphics2D能够跳过剪切之外的所有字符串的绘制。

因此不必担心,因为实际上不应执行太多绘图。