You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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);
}

优化说明

  1. 提取重复逻辑到newFilter()方法,消除代码冗余,提升可维护性。
  2. 移除不必要的table.repaint()调用,TableRowSorter设置过滤器后会自动触发表格更新渲染。
  3. 添加正则语法异常捕获,避免输入非法正则字符导致程序崩溃。
  4. 简化过滤器创建逻辑,保留核心过滤功能的同时优化执行流程。

内容的提问来源于stack exchange,提问作者BitQueen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 12:19:55