我构建了一个登录JTextArea组件的简单Java程序。
JTextArea _log = new JTextArea();
_log.setEditable(false);
JScrollPane scrollLog = new JScrollPane(_log);
scrollLog.setPreferredSize(getMaximumSize());
add(scrollLog);
问题是这样的记录平均需要 15ms :
public void log(String info) {
_log.append(info + "\n");
}
这比使用System.out.println
记录要慢得多(!)。记录比算法的整个运行时间花费更多的时间!
为什么JTextArea这么慢?有没有办法改善它?
我正在为算法使用单独的线程,并使用SwingUtilities.invokeLater
更新UI中的日志。
该算法平均在130ms后完成了他的工作,但JTextArea在平均6000ms后完成了他的append
。
我试图通过使用包含2500个字符的字符串的setText
来测试它。在这种情况下,操作平均需要1000毫秒。
我尝试使用另一个控制器,然后使用JTextArea,我得到相同的结果。
Swing组件难以处理大字符串吗?我该怎么办呢?
我只是用这段代码测试:
public class Test extends JFrame {
public Test() {
final JTextArea log = new JTextArea();
log.setEditable(false);
log.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
JScrollPane scrollLog = new JScrollPane(log);
scrollLog.setPreferredSize(getMaximumSize());
JButton start = new JButton("Start");
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
long start = System.nanoTime();
for (int i = 0; i < 2500; i++) {
log.append("a\n");
}
long end = System.nanoTime();
System.out.println((end - start) / 1000000.0);
}
});
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2, 1));
panel.add(scrollLog);
panel.add(start);
add(panel);
}
public static void main(String[] args) {
Test frame = new Test();
frame.setSize(600,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
for循环的时间是平均1870毫秒。
这是我运行的唯一代码(在问题的顶部包含_log
的声明)
答案 0 :(得分:3)
JTextArea并不慢。
远离System.out.println远(!)。
System.out.println()在单独的Thread上执行。
日志比算法的空洞运行时间花费更多时间!
因此,您的算法可能正在Event Dispatch Thread (EDT)
上执行,这与将文本附加到文本区域的逻辑相同。因此,文本区域不能重新绘制,直到算法结束。
解决方案是为长时间运行的算法使用单独的线程。
或许更好的选择是使用SwingWorker
,这样您就可以运行算法并且&#34;发布&#34;结果到文本区域。
阅读Concurrency上的Swing教程中的部分,了解更多信息以及SwingWorker
的工作示例。
编辑:
//log.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
以上行导致了问题。我第一次测试时得到125,当我一直点击按钮时得到45次。
不需要该属性。文本仍显示在文本窗格的左侧。如果您想要右对齐文本,则需要使用JTextPane
并将文本窗格的属性设置为右对齐。
这就是为什么你应该总是张贴MCVE
。我们无法从您的原始问题中猜到您正在使用该方法。
EDIT2:
使用JTextPane的对齐功能:
SimpleAttributeSet center = new SimpleAttributeSet();
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
textPane.getStyledDocument().setParagraphAttributes(0, doc.getLength(), center, false);
现在,您添加到文档中的任何新文本都应居中对齐。您可以将其更改为正确。