使用JTextField和DocumentListener过滤JTable响应迟缓卡顿问题
JTable过滤功能响应缓慢问题排查与解决
问题描述
我开发了一款基于JTable存储数据的应用,通过绑定DocumentListener的JTextField输入文本实现表格过滤,但每次输入字符时应用都会短暂冻结,响应极慢。起初怀疑是自定义CellRenderer导致性能下降,但注释掉所有自定义渲染器后问题依然存在。
原始监听器创建代码
private void initListener() { this.searchField.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) { String text = searchField.getText(); if (text.trim().length() == 0) { table.getRowSorter().setRowFilter(null); } else { table.getRowSorter().setRowFilter(RowFilter.regexFilter("(?i)" + text)); } table.repaint(); } public void removeUpdate(DocumentEvent e) { String text = searchField.getText(); if (text.trim().length() == 0) { table.getRowSorter().setRowFilter(null); } else { table.getRowSorter().setRowFilter(RowFilter.regexFilter("(?i)" + text)); } } public void insertUpdate(DocumentEvent e) { String text = searchField.getText(); if (text.trim().length() == 0) { table.getRowSorter().setRowFilter(null); } else { table.getRowSorter().setRowFilter(RowFilter.regexFilter("(?i)" + text)); } } }); }
表格类配置代码
private void initializeUI() { this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); this.getColumn("INTERVAL").setPreferredWidth(20); } private void setCustomRowSorter() { this.rowSorter = new TableRowSorter<>(model); this.setRowSorter(rowSorter); } private void setTableCellRenderers() { this.setDefaultRenderer(Object.class, new DefaultTickerTableRenderer()); this.getColumnModel().getColumn(6).setCellRenderer(new RSICellRenderer()); this.getColumnModel().getColumn(7).setCellRenderer(new SMACellRenderer()); this.getColumnModel().getColumn(8).setCellRenderer(new SMACellRenderer()); this.getColumnModel().getColumn(9).setCellRenderer(new SMACellRenderer()); }
自定义CellRenderer代码
public class DefaultTickerTableRenderer extends DefaultTableCellRenderer { private final JCheckBox ckb = new JCheckBox(); public DefaultTickerTableRenderer() { setOpaque(true); //必须设置此属性才能显示背景色 } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JComponent c = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); c.setBorder(new MatteBorder(0, 0, 1, 0, Color.BLACK)); if (!isSelected) { if (row % 2 == 0) { c.setBackground(AppColors.TICKER_TABLE_DEFAULT_BG); } else { c.setBackground(AppColors.TICKERTABLE_STRIPE_BG); } } return c; } } public class SMACellRenderer extends DefaultTableCellRenderer { private Market market; public SMACellRenderer() { setOpaque(true); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setBorder(new MatteBorder(0, 0, 1, 0, Color.BLACK)); float closePrice = Float.parseFloat(table.getModel().getValueAt(row, 5).toString()); float smaValue = Float.parseFloat(value.toString()); if (smaValue < closePrice) { setBackground(AppColors.TICKERTABLE_GREEN); } else if (smaValue > closePrice) { setBackground(AppColors.TICKERTABLE_RED); } else { setBackground(AppColors.TICKERTABLE_NEUTRAL); } if (isSelected) { setBackground(table.getSelectionBackground()); } setText(value.toString()); return this; } } public class RSICellRenderer extends DefaultTableCellRenderer { private Market market; public RSICellRenderer() { setOpaque(true); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setBorder(new MatteBorder(0, 0, 1, 0, Color.BLACK)); float rsiValue = Float.parseFloat(value.toString()); if (rsiValue < TechnicalAnalytics.RSI_OVERSOLD_THRESHOLD) { setBackground(AppColors.TICKERTABLE_GREEN); } else if (rsiValue > TechnicalAnalytics.RSI_OVERBOUGHT_THRESHOLD) { setBackground(AppColors.TICKERTABLE_RED); } else { setBackground(AppColors.TICKERTABLE_NEUTRAL); } if (isSelected) { setBackground(table.getSelectionBackground()); } setText(value.toString()); return this; } }
优化后的解决方案
通过以下方式优化后,性能问题得到解决:
private void initListener() { searchField.getDocument().addDocumentListener( new DocumentListener() { public void changedUpdate(DocumentEvent e) { newFilter(); } public void insertUpdate(DocumentEvent e) { newFilter(); } public void removeUpdate(DocumentEvent e) { newFilter(); } }); } private void newFilter() { RowFilter<TickerTableModel, Object> rf = null; try { rf = RowFilter.regexFilter(searchField.getText(), 0); } catch (java.util.regex.PatternSyntaxException e) { return; } table.getRowSorter().setRowFilter(rf); }
优化说明
- 提取重复逻辑到
newFilter()方法,消除代码冗余,提升可维护性。 - 移除不必要的
table.repaint()调用,TableRowSorter设置过滤器后会自动触发表格更新渲染。 - 添加正则语法异常捕获,避免输入非法正则字符导致程序崩溃。
- 简化过滤器创建逻辑,保留核心过滤功能的同时优化执行流程。
内容的提问来源于stack exchange,提问作者BitQueen
相关产品推荐
相关产品推荐

