Java 过滤JTable后的问题

Java 过滤JTable后的问题,java,swing,jtable,rowfilter,Java,Swing,Jtable,Rowfilter,我对我正在做的一个项目有意见。简单地解释一下,我有一个包含多个列和行的JTable。更改值时,特定列具有可编辑字段,其他列值根据输入的数据进行更改。但是,当我在JTable中添加了一个filter选项时,对一个可编辑列所做的更改不会在应用过滤器后按预期更改其他列的值。我附上了一些图片来说明这个问题 第一幅图显示未过滤的表工作正常。更改折扣列值将使GPL列中存储的相应价格降低输入折扣的百分比,并显示在SP列的相应行中。更改“数量”列的值会将相应的SP列价格与输入的数量相乘,并显示在“总计”列的相应

我对我正在做的一个项目有意见。简单地解释一下,我有一个包含多个列和行的JTable。更改值时,特定列具有可编辑字段,其他列值根据输入的数据进行更改。但是,当我在JTable中添加了一个filter选项时,对一个可编辑列所做的更改不会在应用过滤器后按预期更改其他列的值。我附上了一些图片来说明这个问题

第一幅图显示未过滤的表工作正常。更改折扣列值将使GPL列中存储的相应价格降低输入折扣的百分比,并显示在SP列的相应行中。更改“数量”列的值会将相应的SP列价格与输入的数量相乘,并显示在“总计”列的相应行中

第二幅图显示过滤后的表未按预期工作。更改折扣或数量列中的值不会更改预期列

我在下面添加了SSCCE代码,其中包含2个类。第一个是表本身,第二个是表的侦听器

编辑我根据camickr的答案更改了课程代码,现在完全可以使用了

TableCellChange类

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.math.MathContext;
import java.text.DecimalFormat;
import java.util.Locale;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public final class TableCellChange extends JPanel {  

    private static JFrame frameTableCellChange;
    private JPanel panelTable, panelButtons;
    private JButton buttonResetDiscounts, buttonResetQuantities, buttonExit;
    private JTextField textFilterBox, quantityField, discountField;
    private JLabel labelFilter;
    private DefaultTableModel tableModel;
    private JTable table;
    private TableRowSorter<DefaultTableModel> sorter;
    private TableColumn columnDiscount, columnTotal, columnQuantity;
    private TableCellListener tableCellListener;
    private String checkForNull;
    private DecimalFormat decimalFormatUS;
    private Locale localeUSFormat;    
    private BigDecimal valueDiscount, valueGPL, resultDiscount, resultSP, resultTotal,
            backupDiscount = new BigDecimal("0"); 
    private int selectedColumnIndex, selectedRowIndex, valueQuantity, backupQuantity = 1;

    public TableCellChange() {

        super(); 

        panelTable = new JPanel();
        panelButtons = new JPanel();
        setLayout(new BorderLayout());

        createTable();
        createButtons();
        add(panelTable, BorderLayout.NORTH);
        add(panelButtons, BorderLayout.CENTER);

        // Always focus on the JTextField when opening the window
        SwingUtilities.invokeLater(new Runnable()  {
           @Override
           public void run() {  
               textFilterBox.requestFocusInWindow();
           }
        });
    } // -> TableCellChange()

    // Create the buttons for the query result window
    public void createButtons() {
        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints gridcons = new GridBagConstraints();
        gridcons.fill = GridBagConstraints.HORIZONTAL;
        panelButtons.setLayout(gridbag);

        labelFilter = new JLabel("Quick search:");
        gridcons.insets = new Insets(5,0,0,0);
        gridcons.gridx = 0;
        gridcons.gridy = 0;
        gridcons.gridwidth = 2;
        gridbag.setConstraints(labelFilter, gridcons);
        labelFilter.setHorizontalAlignment(JLabel.CENTER);
        panelButtons.add(labelFilter);

        // Create text field for filtering
        textFilterBox = new JTextField();
        gridcons.insets = new Insets(5,0,0,0);
        gridcons.gridx = 0;
        gridcons.gridy = 1;
        gridcons.gridwidth = 2;
        gridbag.setConstraints(textFilterBox, gridcons);
                textFilterBox.getDocument().addDocumentListener(
                new DocumentListener() {
                    @Override
                    public void changedUpdate(DocumentEvent e) {
                        tableFilter();
                    }
                    @Override
                    public void insertUpdate(DocumentEvent e) {
                        tableFilter();
                    }
                    @Override
                    public void removeUpdate(DocumentEvent e) {
                        tableFilter();
                    }
                }); // -> DocumentListener()
        panelButtons.add(textFilterBox);

        // Create the button to reset the discount column to 0%
        buttonResetDiscounts = new JButton("Reset all discounts");
        buttonResetDiscounts.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e)
            {          
                BigDecimal valueGPL, valueTotal;
                int valueQuantity;
                for (int i = 0; i < table.getModel().getRowCount(); i++) {
                    valueGPL = new BigDecimal( table.getModel().
                            getValueAt(i, 2).toString().replaceAll("[$,]", "") );
                    table.getModel().setValueAt("0%", i, 3);   
                    table.getModel().setValueAt(DecimalFormat
                            .getCurrencyInstance(localeUSFormat).format(valueGPL), i, 4);
                    valueQuantity = Integer.parseInt( table.getModel().
                            getValueAt(i, 5).toString() );
                    valueTotal = valueGPL.multiply(new BigDecimal(valueQuantity),
                            new MathContext(BigDecimal.ROUND_HALF_EVEN));
                    table.getModel().setValueAt(DecimalFormat
                            .getCurrencyInstance(localeUSFormat).format(valueTotal), i, 6);
                }
            }
        });         
        gridcons.insets = new Insets(10,0,0,0);
        gridcons.gridx = 0;
        gridcons.gridy = 3;
        gridcons.gridwidth = 1;
        gridbag.setConstraints(buttonResetDiscounts, gridcons);
        panelButtons.add(buttonResetDiscounts);

        // Create button to reset the quantity column to 1 
        buttonResetQuantities = new JButton("Reset all quantities");
        buttonResetQuantities.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e)
            {             
                BigDecimal valueSP;
                for (int i = 0; i < table.getModel().getRowCount(); i++) {                    
                    valueSP = new BigDecimal( table.getModel().
                            getValueAt(i, 4).toString().replaceAll("[$,]", "") );
                    table.getModel().setValueAt("1", i, 5); 
                    table.getModel().setValueAt(DecimalFormat.
                            getCurrencyInstance(localeUSFormat).format(valueSP), i, 6);   
                }
            }          
        });         
        gridcons.insets = new Insets(10,0,0,0);
        gridcons.gridx = 1;
        gridcons.gridy = 3;
        gridcons.gridwidth = 1;
        gridbag.setConstraints(buttonResetQuantities, gridcons);
        panelButtons.add(buttonResetQuantities);

        // Create button for closing the window and releasing resources
        buttonExit = new JButton("Exit");
        buttonExit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e)
            {                
                System.exit(0);
            }
        }); 
        gridcons.insets = new Insets(5,0,0,0);
        gridcons.gridx = 0;
        gridcons.gridy = 5;
        gridcons.gridwidth = 2;
        gridbag.setConstraints(buttonExit, gridcons);
        panelButtons.add(buttonExit);    

    } // -> createButtons()


    // Filters the JTable based on user input
    private void tableFilter() {
        RowFilter<DefaultTableModel, Object> tableRowFilter;// = null;
        // If current expression doesn't parse, don't update
        try {
            tableRowFilter = RowFilter.regexFilter("(?i)" + textFilterBox.
                    getText(), 0, 1, 2);
        } catch (java.util.regex.PatternSyntaxException e) {
            return;
          }
        sorter.setRowFilter(tableRowFilter);       
    } // -> tableFilter

    // Method that creates the JTable
    public void createTable() {

        // Create listener for selecting all text when a text field gains focus
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
        .addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener() {
        @Override
           public void propertyChange(final PropertyChangeEvent e) {
               if (e.getNewValue() instanceof JTextField) {
                   SwingUtilities.invokeLater(new Runnable() {
                       @Override
                       public void run() {
                           JTextField textField = (JTextField)e.getNewValue();
                           textField.selectAll();
                       }
                   });
               }
           }
        });

        String[] columnNames = {"Model", "Description", "GPL", "Discount", "SP",
                "Quantity", "Total"};

        Object[][] data = {
            {"MR16", "desc1", "$649.00", "0%", "$649.00", new Integer(1), "$649.00"},
            {"MR24", "desc2", "$1,199.00", "0%", "$1,199.00", new Integer(1), "1,199.00"},
            {"MR62", "desc3", "$699.00", "0%", "$699.00", new Integer(1), "$699.00"},
            {"MR66", "desc4", "$1,299.00", "0%", "$1,299.00", new Integer(1), "$1,299.00"},
            {"MX80", "desc5", "$1,995.00", "0%", "$1,995.00", new Integer(1), "$1,995.00"},
            {"MX90", "desc6", "$3,995.00", "0%", "$3,995.00", new Integer(1), "$3,995.00"},
            {"MX400", "desc7", "$15,995.00", "0%", "$15,995.00", new Integer(1), "$15,995.00"},
            {"MX600", "desc8", "$31,995.00", "0%", "$31,995.00", new Integer(1), "$31,995.00"},
            {"MS22-HW", "desc9", "$1,999.00", "0%", "$1,999.00", new Integer(1), "$1,999.00"},
            {"MS42-HW", "desc10", "$3,499.00", "0%", "$3,499.00", new Integer(1), "$3,499.00"},

        };

        // Create the TableModel and populate it  
        tableModel = new DefaultTableModel(data, columnNames) {
            Class [] classes = {String.class, String.class, String.class,
                String.class, String.class, int.class, String.class, Boolean.class};                
            @Override
            public Class getColumnClass(int column) {
                return classes[column];
            }
        };

        // Create a JTable and populate it with the content of the TableModel
        table = new JTable(tableModel) {
            @Override
            public boolean isCellEditable(int row, int column) {
                if (column == 0 || column == 1 || column == 2 || column == 4 ||
                        column == 6) {
                    return false;
                }
                return true;
            }
        };

        // This sorter is used for text filtering
        sorter = new TableRowSorter<>(tableModel);
        for (int column = 3; column < 6; column++) {
            sorter.setSortable(column, false);
        }
        table.setRowSorter(sorter);

        columnTotal= table.getColumnModel().getColumn(6);
        columnTotal.setPreferredWidth(100);

        // Filter user input in the quantity text field to only allow digits
        discountField =new JTextField();
        discountField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e)
            {
                if(!Character.isDigit(e.getKeyChar()) && e.getKeyChar() !=KeyEvent.VK_BACK_SPACE) {
                    discountField.setEditable(false);
                    discountField.setBackground(Color.WHITE);
                } else {
                    discountField.setEditable(true);
                }
            }
        });

        // Set the text field to the cells of the quantity column 
        columnQuantity = table.getColumnModel().getColumn(5);
        columnQuantity.setCellEditor(new DefaultCellEditor (discountField));

        // Filter user input in the discount text field to only allow digits
        quantityField =new JTextField();
        quantityField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e)
            {
                if(!Character.isDigit(e.getKeyChar()) && e.getKeyChar() !=KeyEvent.VK_BACK_SPACE) {
                    quantityField.setEditable(false);
                    quantityField.setBackground(Color.WHITE);
                    //JOptionPane.showMessageDialog(null,"Only digit input is allowed!");
                } else {
                    quantityField.setEditable(true);
                }
            }
        });

        // Set the text field to the cells of the quantity column 
        columnDiscount = table.getColumnModel().getColumn(3);
        columnDiscount.setCellEditor(new DefaultCellEditor(discountField));

        // Create an US number format
        localeUSFormat = Locale.US;
        decimalFormatUS = (DecimalFormat) DecimalFormat.getInstance(localeUSFormat);
        decimalFormatUS.setMaximumFractionDigits(2);

        // Create abstract action which listens for changes made in the JTable  
        Action actionTableListener = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {

                TableCellListener tcl = (TableCellListener)e.getSource();
                // Get the current row and column index of the table
                selectedRowIndex = tcl.getRow();
                selectedColumnIndex = tcl.getColumn();  
                TableModel model = tcl.getTable().getModel();

                // Have a string variable check for null cell value 
                checkForNull = model.getValueAt(selectedRowIndex,selectedColumnIndex).toString();

                // Change the discounted and total price values 
                if (selectedColumnIndex == 3) {

                    // Check if the discount value is null and replace with 
                    // last used value if true                   
                    if (checkForNull.equals("")) {
                        model.setValueAt(backupDiscount + "%",selectedRowIndex, selectedColumnIndex);
                        return;
                    }

                    // Get the discount value and replace the '%' with nothing
                    valueDiscount = new BigDecimal(( model
                            .getValueAt(selectedRowIndex,selectedColumnIndex)
                            .toString().replaceAll("[%]","") ));
                    // 
                    model.setValueAt(valueDiscount + "%",selectedRowIndex, selectedColumnIndex);

                    // Check if the discount value is greater than 100
                    if ( (valueDiscount.compareTo(new BigDecimal(100)) == 1 ) ) {
                        model.setValueAt(backupDiscount + "%",selectedRowIndex, selectedColumnIndex);
                        JOptionPane.showMessageDialog(null,"Discount cannot be more than 100%.");
                    } else {
                        backupDiscount = valueDiscount;
                        valueDiscount = valueDiscount.divide(new BigDecimal(100)
                                , 2, BigDecimal.ROUND_HALF_EVEN);

                        // Calculate SP and Total values based on the discount input
                        valueGPL = new BigDecimal( ( model
                                .getValueAt(selectedRowIndex,selectedColumnIndex - 1)
                                .toString().replaceAll("[$,]","") ) );
                        // Get the quantity value
                        valueQuantity = Integer.parseInt( ( model
                                .getValueAt(selectedRowIndex,selectedColumnIndex + 2)
                                .toString() ) );
                        // Calculate the new discount value
                        resultDiscount = valueGPL.multiply(valueDiscount, 
                                new MathContext(BigDecimal.ROUND_HALF_EVEN));
                        // Calculate the new SP value
                        resultSP = valueGPL.subtract(resultDiscount, 
                                new MathContext(BigDecimal.ROUND_HALF_EVEN));
                        // Calculate the new result value
                        resultTotal = resultSP.multiply(new BigDecimal(valueQuantity), 
                                new MathContext(BigDecimal.ROUND_HALF_EVEN));
                        // Display the new SP value
                        model.setValueAt(DecimalFormat.getCurrencyInstance(localeUSFormat)
                                .format(resultSP),selectedRowIndex, selectedColumnIndex + 1);
                        // Display the new Total value
                        model.setValueAt(DecimalFormat.getCurrencyInstance(localeUSFormat)
                                .format(resultTotal),selectedRowIndex, selectedColumnIndex + 3);
                      }
                }
                // Change the total price values based on the quantity column 
                if (selectedColumnIndex == 5) {
                    // Check if the quantity value is null and replace with 
                    // last used value if true
                    if (checkForNull.equals("")) {
                        model.setValueAt(backupQuantity,selectedRowIndex, selectedColumnIndex);
                        return;
                    }

                    // Change total price value based on the quantity column
                    resultSP = new BigDecimal( ( model.
                            getValueAt(selectedRowIndex,
                            selectedColumnIndex - 1).toString().replaceAll("[$,]","") ) );
                    valueQuantity = Integer.parseInt( ( model.getValueAt(selectedRowIndex,
                            selectedColumnIndex).toString() ) );

                    // Check if the value quantity is over a certain limit
                    if (valueQuantity <= 0 || valueQuantity >= 999999) {
                        model.setValueAt(backupQuantity,selectedRowIndex, selectedColumnIndex);
                        JOptionPane.showMessageDialog(null,"Quantity value is too high or invalid!");
                    } else {

                        // If the value is under the limit: backup the new quantity
                        // value, calculate the new total value and display it
                        backupQuantity = valueQuantity;
                        resultTotal = resultSP.multiply(new BigDecimal(valueQuantity),
                                new MathContext(BigDecimal.ROUND_HALF_EVEN));
                        model.setValueAt(DecimalFormat.getCurrencyInstance(localeUSFormat)
                                .format(resultTotal), selectedRowIndex, selectedColumnIndex + 1);
                      }
                } 

            }
        }; // -> AbstractAction() 

        tableCellListener = new TableCellListener(table, actionTableListener);
        table.setPreferredScrollableViewportSize(table.
               getPreferredSize());       
        table.setRowHeight(22);

        setVisibleRowCount(table,10);

        table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
        table.setFillsViewportHeight(true);
        table.getTableHeader().setReorderingAllowed(false);
        table.getTableHeader().setResizingAllowed(false);
        panelTable.add(new JScrollPane(table));
    } // -> createTable() 

    // Method to display a fixed number of rows in the JTable viewport
    public static void setVisibleRowCount(JTable table, int rows){ 
        int height = 0; 
        for(int row=0; row<rows; row++) {
            height += table.getRowHeight(row);
        } 
        table.setPreferredScrollableViewportSize(new Dimension( 
            table.getPreferredScrollableViewportSize().width, height )); 
     }

      // Create and display the contents of the frame
      public static void showGUI() {
        // Disable boldface controls
        UIManager.put("swing.boldMetal", Boolean.FALSE);

        // Create the frame
        frameTableCellChange = new JFrame("Table frame");
        frameTableCellChange.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     
        frameTableCellChange.addWindowListener(new WindowAdapter() {
            @Override
                public void windowClosing(WindowEvent we) {
                System.exit(0);
            }
        });

        // Create and set up the content pane.
        TableCellChange newContentPane = new TableCellChange();
        newContentPane.setOpaque(true); //content panes must be opaque
        frameTableCellChange.setContentPane(newContentPane);

        // Arrange and display the window.
        frameTableCellChange.pack(); //must be called first 
        frameTableCellChange.setLocationRelativeTo(null); //center window
        frameTableCellChange.setResizable(false); 
        frameTableCellChange.setVisible(true);        
      } //-> showQueryResultGUI() 

   public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
         try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.
                    UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException |
                IllegalAccessException |
                javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(TableCellChange.class.getName()).
                    log(java.util.logging.Level.SEVERE, null, ex);
        }
        // Display the frame and it's contents      
        TableCellChange.showGUI();
            }
        });
    } //-> main(String[] args)      

} //-> TableCellChange class

我知道在筛选表时,表视图的索引会发生变化,并且必须与基础模型的索引同步。如何才能使筛选后的表正常工作?

您可能需要执行从视图到模型的转换。查看“如何使用表格”教程的一部分:

当表格使用分拣机时,用户看到的数据可能在一个表格中 与数据模型指定的顺序不同,并且可能不会 包括数据模型指定的所有行。用户可以使用数据 “实际查看”称为“视图”,它有自己的一组 协调。JTable提供了从模型转换的方法 要查看坐标的坐标-convertColumnIndexToView和 convertRowIndexToView-将视图坐标转换为 模型坐标-convertColumnIndexToModel和 convertRowIndexToModel

编辑:从视图(表格)转换为模型:

替换这些行:

row = table.convertRowIndexToView(table.getEditingRow());
row = table.getEditingRow();
与:

row = table.convertRowIndexToModel(table.getEditingRow());

您错误地实现了TableCellListener的操作。无法使用选定的行/列,因为这些值位于表视图中。TableCellListener在模型上工作

查看随附的示例操作。要获取已更改的行/列,必须引用TableCellListener本身

编辑:

下面是我的简单文本示例。更改“价格”时,“价格更改”和“价值”列将自动更新

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableCellListenerTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI()
    {
        String[] columnNames = {"Stock", "Shares", "Price", "Price Change", "Value"};
        Object[][] data =
        {
            {"IBM",    new Integer(100),  new Double(85),  new Double(0), new Double(8500)},
            {"Apple",  new Integer(300),  new Double(30),  new Double(0), new Double(9000)},
            {"Sun",    new Integer(1500), new Double(5),   new Double(0), new Double(7500)},
            {"Google", new Integer(100),  new Double(100), new Double(0), new Double(10000)}
        };

        DefaultTableModel model = new DefaultTableModel(data, columnNames)
        {
            public Class getColumnClass(int column)
            {
                return getValueAt(0, column).getClass();
            }

            public boolean isCellEditable(int row, int column)
            {
                return column == 2;
            }
        };

        JTable table = new JTable(model);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);

        //  Add a sorter

        TableRowSorter<DefaultTableModel> sorter = new TableRowSorter<DefaultTableModel>(model);
        table.setRowSorter(sorter);

        //  Filter

        try
        {
            RowFilter<DefaultTableModel, Object> rf = RowFilter.regexFilter("l", 0);
            sorter.setRowFilter(rf);
        }
        catch (java.util.regex.PatternSyntaxException e) {}

        Action action = new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                TableCellListener tcl = (TableCellListener)e.getSource();
                int column = tcl.getColumn();

                if (column == 2)
                {
                    int row = tcl.getRow();
                    double oldPrice = ((Double)tcl.getOldValue()).doubleValue();
                    double newPrice = ((Double)tcl.getNewValue()).doubleValue();
                    TableModel model = tcl.getTable().getModel();

                    double priceChange = new Double(newPrice - oldPrice);
                    model.setValueAt(priceChange, row, 3);

                    double shares = ((Integer)model.getValueAt(row, 1)).doubleValue();
                    Double value = new Double(shares * newPrice);
                    model.setValueAt(value, row, 4);
                }
            }
        };

      TableCellListener tcl = new TableCellListener(table, action);

        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("Table Cell Listener");
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( scrollPane );
        frame.setSize(400, 160);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}
import java.awt.*;
导入java.awt.event.*;
导入java.io.*;
导入java.net。*;
导入javax.swing.*;
导入javax.swing.table.*;
公共类TableCellListenerTest
{
公共静态void main(字符串[]args)
{
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
公共静态void createAndShowGUI()
{
String[]columnNames={“股票”、“股票”、“价格”、“价格变化”、“价值”};
对象[][]数据=
{
{“IBM”、新整数(100)、新双精度(85)、新双精度(0)、新双精度(8500)},
{“苹果”、新整数(300)、新双精度(30)、新双精度(0)、新双精度(9000)},
{“Sun”、新整数(1500)、新双精度(5)、新双精度(0)、新双精度(7500)},
{“谷歌”,新整数(100),新双精度(100),新双精度(0),新双精度(10000)}
};
DefaultTableModel=新的DefaultTableModel(数据、列名)
{
公共类getColumnClass(int列)
{
返回getValueAt(0,列).getClass();
}
公共布尔值可编辑(int行,int列)
{
返回列==2;
}
};
JTable table=新的JTable(模型);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane=新的JScrollPane(表);
//添加一个分拣机
TableRowSorter分拣机=新的TableRowSorter(型号);
表.SetRow分拣机(分拣机);
//滤器
尝试
{
RowFilter rf=RowFilter.regexFilter(“l”,0);
分拣机。设置行过滤器(rf);
}
catch(java.util.regex.PatternSyntaxException e){}
Action Action=newAbstractAction()
{
已执行的公共无效操作(操作事件e)
{
TableCellListener tcl=(TableCellListener)e.getSource();
int column=tcl.getColumn();
如果(列==2)
{
int row=tcl.getRow();
double-oldPrice=((double)tcl.getOldValue()).doubleValue();
double newPrice=((double)tcl.getNewValue()).doubleValue();
TableModel model=tcl.getTable().getModel();
双倍价格变动=新双倍(新价格-旧价格);
model.setValueAt(价格变化,第3行);
double shares=((整数)model.getValueAt(行,1)).doubleValue();
双倍价值=新的双倍(股票*新价格);
model.setValueAt(值,第4行);
}
}
};
TableCellListener tcl=新的TableCellListener(表,动作);
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame=新的JFrame(“表格单元格侦听器”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(滚动窗格);
框架设置尺寸(400160);
frame.setLocationRelativeTo(空);
frame.setVisi
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableCellListenerTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI()
    {
        String[] columnNames = {"Stock", "Shares", "Price", "Price Change", "Value"};
        Object[][] data =
        {
            {"IBM",    new Integer(100),  new Double(85),  new Double(0), new Double(8500)},
            {"Apple",  new Integer(300),  new Double(30),  new Double(0), new Double(9000)},
            {"Sun",    new Integer(1500), new Double(5),   new Double(0), new Double(7500)},
            {"Google", new Integer(100),  new Double(100), new Double(0), new Double(10000)}
        };

        DefaultTableModel model = new DefaultTableModel(data, columnNames)
        {
            public Class getColumnClass(int column)
            {
                return getValueAt(0, column).getClass();
            }

            public boolean isCellEditable(int row, int column)
            {
                return column == 2;
            }
        };

        JTable table = new JTable(model);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);

        //  Add a sorter

        TableRowSorter<DefaultTableModel> sorter = new TableRowSorter<DefaultTableModel>(model);
        table.setRowSorter(sorter);

        //  Filter

        try
        {
            RowFilter<DefaultTableModel, Object> rf = RowFilter.regexFilter("l", 0);
            sorter.setRowFilter(rf);
        }
        catch (java.util.regex.PatternSyntaxException e) {}

        Action action = new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                TableCellListener tcl = (TableCellListener)e.getSource();
                int column = tcl.getColumn();

                if (column == 2)
                {
                    int row = tcl.getRow();
                    double oldPrice = ((Double)tcl.getOldValue()).doubleValue();
                    double newPrice = ((Double)tcl.getNewValue()).doubleValue();
                    TableModel model = tcl.getTable().getModel();

                    double priceChange = new Double(newPrice - oldPrice);
                    model.setValueAt(priceChange, row, 3);

                    double shares = ((Integer)model.getValueAt(row, 1)).doubleValue();
                    Double value = new Double(shares * newPrice);
                    model.setValueAt(value, row, 4);
                }
            }
        };

      TableCellListener tcl = new TableCellListener(table, action);

        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("Table Cell Listener");
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( scrollPane );
        frame.setSize(400, 160);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}