问题描述
我在“文本区域”中的长文本放置在“滚动窗格”中。我注意到,当我旋转鼠标滚轮时,文本会被重绘,甚至可能会全部重绘。
这是演示应用程序:
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能够跳过剪切之外的所有字符串的绘制。
因此不必担心,因为实际上不应执行太多绘图。