更新:所以我发现了这个问题的原因 当我的Java窗口最小化时,我的表将呈现每一行。有人知道如何防止这种情况发生吗?
我有一个JXTable,它每秒都在不断地更新、删除和添加行数据。我们讨论的是平均每秒修改10-20行。
通常,CPU使用率在5%到10%之间。当我们每秒更新数百次时,它可以达到15%。
然而,我们注意到,当我们的Java窗口最小化时,每当任何更新通过时,我们的CPU使用率每次都会达到25%。我们设置了一个脚本,每5秒添加一行,当这一行通过时,我们看到CPU使用率达到25%。
我能想到的唯一解释是使用SwingUtilities.invokeAndWait()。我正在后台线程中修改行数据,并使用invokeAndWait来处理各种fireTableDataChanged()方法。
我使用invokeAndWait是因为我需要按顺序启动事件。例如,我删除一些行,调用fireTableRowsDeleted(),然后添加一些行,并调用fireTableRowsInserted()。
有什么想法吗?为什么只有在表更新和窗口最小化时,我的CPU使用率才会达到25%?
我使用invokeAndWait,因为我需要按顺序启动我的事件
不需要使用invokeAndWait()。您可以使用invokeLater()。事件仍将按接收顺序执行。
各种fireTableDataChanged()方法。
您不应该调用fireTableDataChanged。TableModel将调用相应的fireXXX()方法。既然只能更改几行,为什么还要重新绘制整个表呢。RepaintManager将在必要时将多个绘制请求合并为一个。
编辑:
这是我随身携带的一些代码。所有更新都是在EDT上对模型进行的,代码不会调用fireXXX(…)方法:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableThread extends JFrame
implements ActionListener, Runnable
{
JTable table;
DefaultTableModel model;
int count;
public TableThread()
{
String[] columnNames = {"Date", "String", "Integer", "Decimal", "Boolean"};
Object[][] data =
{
{new Date(), "A", new Integer(1), new Double(5.1), new Boolean(true)},
{new Date(), "B", new Integer(2), new Double(6.2), new Boolean(false)},
{new Date(), "C", new Integer(3), new Double(7.3), new Boolean(true)},
{new Date(), "D", new Integer(4), new Double(8.4), new Boolean(false)}
};
model = new DefaultTableModel(data, columnNames);
table = new JTable( model );
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.setIgnoreRepaint(false);
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
JButton button = new JButton( "Start Thread to Update Table" );
button.addActionListener( this );
getContentPane().add(button, BorderLayout.SOUTH );
}
public void actionPerformed(ActionEvent e)
{
new Thread( this ).start();
table.requestFocus();
}
public void run()
{
Random random = new Random();
while (true)
{
final int row = random.nextInt( table.getRowCount() );
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
table.setValueAt( new Integer(count++), row, 2);
table.setRowSelectionInterval(row, row);
Object[] aRow = { new Date(), "f", row, new Double(123), new Boolean(true) };
model.addRow( aRow );
}
});
try { Thread.sleep(500); }
catch(Exception e) {}
}
}
public static void main(String[] args)
{
TableThread frame = new TableThread();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}
}
无论帧是可见的还是最小化的,CPU都是一致的。
如果您需要更多帮助,请发布适当的SSCCE,如上面的代码,以演示问题。
JTable
使用蝇量级模式只渲染可见的单元格,但主机操作系统可能会进行干扰,例如尝试为最小化的图标设置动画;个人资料。无论是什么原因,publish()
都会更新为SwingWorker
的doInBackground()
实现中的TableModel
,如图所示。工作人员将合并更新,并以可持续的速率(约30 Hz)将其发送到process()
。然后,TableModel
可以以对应用程序有意义的方式推迟触发更新事件。
在JXTable中,每当模型发生变化时都会调用此方法:
protected void postprocessModelChange(TableModelEvent e) {
if (forceRevalidate && filteredRowCountChanged) {
resizeAndRepaint();
}
filteredRowCountChanged = false;
forceRevalidate = false;
}
resizeAndRepaint()
调用似乎是在最小化窗口时强制每一行重新绘制的。如下覆盖似乎可以解决问题:
@Override
protected void resizeAndRepaint()
{
JFrame window = (JFrame) SwingUtilities.getAncestorOfClass(JFrame.class, this);
if(window != null && window.getState() != JFrame.ICONIFIED)
{
super.resizeAndRepaint();
}
}