滚动时停止 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 能够跳过裁剪之外的所有字符串的绘制.
所以不用担心,因为实际上应该执行的绘图不多。
我将文本区中的长文本放置到滚动窗格中。我注意到当我旋转鼠标滚轮时,文本会被严重重绘,甚至可能完全重绘。
这是演示应用程序:
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 能够跳过裁剪之外的所有字符串的绘制.
所以不用担心,因为实际上应该执行的绘图不多。