用户单击时将内容添加到单元格

时间:2013-11-28 19:53:37

标签: java swing jtable cell changelistener

我在JTable中有一个功能,当用户点击单元格时,它会删除其中的某些字符(例如当内容为- Hello时,当用户点击它时,它会显示Hello)。如果不再进行编辑,则会再次显示- Hello

我的问题是,当选择某个单元格(但尚未编辑)并且我开始键入Hi时,它不会删除该字符,因此可编辑单元格看起来像- Hello Hi。< / p>

同样的问题是当选择某个单元格并且用户按空格键时。

我想将功能添加到JTable中,以便在开始编辑单元格的内容时(以任何方式 - 选中时单击/键入/空格键/也许还有更多选项我不知道关于),我想先以编程方式更改内容。另一种选择是在选择单元格时删除它(但是我必须记住最后一个选定单元格的位置,以便可以将字符读回到它)。

我在类TableChangeListener中尝试了propertyChange:

 table.setValueAt(removeCharacter(table.getValueAt(row,column)), row, column);

但它不起作用,因为单元格已被编辑,我无法更改它。

3 个答案:

答案 0 :(得分:2)

  1. 您必须使用自己的Cell Editor实现来满足您自己的要求。
  2. 因此,请创建实施FocusLisetenerActionListener的自定义CellEditor,并实施FocusGainedFocusLost功能
  3. 实施actionPerformed功能以更新输入点击值。
  4. 处理Focus事件有点棘手。因为它倾向于错误地更新单元格。这就是为什么我必须将引用表作为构造函数参数传递给CellEditor并读取单元格行,聚焦焦点增益。
  5. 要反映- xxxx:在单元格值之前放置-,请尝试使用自定义CellRenderer。有关详细信息,请查看official tutorial page示例。而部分功劳归功于@mKobel。
  6. 用于方向的已实现的自定义单元格编辑器:将其分配给目标表列并进行测试。

    我测试结果的Giff:

    enter image description here

    <强>代码:

    class CustomRenderer extends DefaultTableCellRenderer {
    
         public void setValue(Object value) 
         {
             setText("- "+value);
          }
      }
    
    class MyCellEditor extends AbstractCellEditor
                             implements TableCellEditor,
                                        FocusListener,
                                        ActionListener
    {
        JTextField textFeild;
        String currentValue;
    
        JTable table;
        int row, col;
        public MyCellEditor(JTable table) {
            this.table = table;
            textFeild = new JTextField();
            textFeild.addActionListener(this);
            textFeild.addFocusListener(this);
        }
    
    
        @Override
        public Object getCellEditorValue() {
            return currentValue;
        }
    
        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
    
            currentValue = (String)value;
            return textFeild;
    
        }
    
        @Override
        public void focusGained(FocusEvent e) {
            textFeild.setText("");
            row = table.getSelectedRow();
            col = table.getSelectedColumn();
    
        }
    
        @Override
        public void focusLost(FocusEvent e) {
    
            if(!textFeild.getText().equals(""))
               //currentValue = textFeild.getText();
               table.setValueAt(textFeild.getText(), row, col);
    
            fireEditingStopped();
    
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
           if(!textFeild.getText().trim().equals(""))
               currentValue = textFeild.getText();
           fireEditingStopped();
        }
    
    
    }
    

答案 1 :(得分:1)

我认为你根本不应该更改单元格的内容。 你需要的是在表格上设置一个呈现单元格值的TableCellRenderer。实现单元格渲染器,使其显示值“ - Hello”(尽管您的实际数据可能只包含“Hello”)。渲染器只显示表中所需的任何组件。当用户开始编辑单元格时,不显示渲染器组件。实际上,您也可以使用TableCellEditor操作编辑组件。

答案 2 :(得分:1)

摘自this comment

  

该表显示价格“$ 5”“20€”以及用户点击单元格时的价格   为了改变价格,我希望这个标志消失。当用户   完成编辑(点击输入或通过其他方式),我想要符号   再次出现。

虽然@Sage帖子是一个非常好的通用解决方案(+1给你:),在这种特殊情况下,我会使用TableCellRenderer来实现TableCellEditorJFormattedTextField管理货币格式问题,如下:

这样,当显示单元格时,将显示货币符号,但在编辑单元格时,货币符号将“消失”。

看看这个实施的例子:

import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.text.NumberFormat;
import java.util.EventObject;
import java.util.Locale;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.JFormattedTextField;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.text.NumberFormatter;

public class CurrencyEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {

    JFormattedTextField editor;
    JFormattedTextField renderer;
    Integer clickCountToStart = 2;

    public CurrencyEditor(Locale locale) {
        initEditor(locale);
        initRenderer(locale);
    }

    private void initRenderer(Locale locale) {
        NumberFormat format = locale != null ? 
                                        NumberFormat.getCurrencyInstance(locale) : NumberFormat.getCurrencyInstance();

        NumberFormatter formatter = new NumberFormatter(format);
        formatter.setMinimum(Double.MIN_VALUE);
        formatter.setMaximum(Double.MAX_VALUE);
        formatter.setAllowsInvalid(false);
        renderer = new JFormattedTextField(formatter);
    }

    private void initEditor(Locale locale) {
        NumberFormat format = locale != null ? 
                                        NumberFormat.getNumberInstance(locale) : NumberFormat.getNumberInstance();

        NumberFormatter formatter = new NumberFormatter(format);
        formatter.setMinimum(Double.MIN_VALUE);
        formatter.setMaximum(Double.MAX_VALUE);
        formatter.setAllowsInvalid(false);
        editor = new JFormattedTextField(formatter);
        editor.setBorder(UIManager.getBorder("Tree.editorBorder"));
    }

    @Override
    public Object getCellEditorValue() {
        return editor.getValue();
    }

    @Override
    public boolean isCellEditable(EventObject anEvent) {
        if (anEvent instanceof MouseEvent) {
            return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
        }
        return true;
    }

    @Override
    public boolean shouldSelectCell(EventObject anEvent) {
        return true;
    }

    @Override
    public boolean stopCellEditing() {
        fireEditingStopped();
        return true;
    }


    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        if(value instanceof Double){
            editor.setValue(value);
        }
        return editor;
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

        if(value instanceof Double) {            
            Color background = isSelected ? UIManager.getColor("Table.selectionBackground") : UIManager.getColor("Table.background");
            Color foreground = isSelected ? UIManager.getColor("Table.selectionForeground") : UIManager.getColor("Table.foreground");
            Border border = hasFocus ? UIManager.getBorder("Table.focusCellHighlightBorder") : BorderFactory.createEmptyBorder();

            renderer.setBackground(background);
            renderer.setForeground(foreground);
            renderer.setBorder(border);

            renderer.setValue(value);
            return renderer;

        } else {
            String message = String.format("Not supported for %1$1s class!", value.getClass());
            throw new IllegalArgumentException(message);
        }
    }

}

免责声明:由于UIManager属性命名不同,因此可能无法正常使用Nimbus外观。我使用Metal,Windows,Windows Classic和Motif进行了测试。

以下是我用来测试它的代码:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Locale;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

public class Demo {

    private void initGUI(){

        DefaultTableModel model = new DefaultTableModel(new Object[]{"Item", "Price USD", "Price EUR"}, 0);
        model.addRow(new Object[]{"Fender stratocaster", 1599.99d, 1176.46d});
        model.addRow(new Object[]{"Gibson Les Paul", 1299.99d, 955.87d});
        model.addRow(new Object[]{"Pual Reed Smith Standard 24", 1999.99d, 1470.58d});

        JTable table = new JTable(model);
        table.setPreferredScrollableViewportSize(new Dimension(500, 300));

        TableColumn priceUSD = table.getColumn("Price USD");
        priceUSD.setCellRenderer(new CurrencyEditor(Locale.US));
        priceUSD.setCellEditor(new CurrencyEditor(Locale.US));

        TableColumn priceEUR = table.getColumn("Price EUR");
        priceEUR.setCellRenderer(new CurrencyEditor(Locale.GERMANY));
        priceEUR.setCellEditor(new CurrencyEditor(Locale.GERMANY));

        JPanel content = new JPanel(new BorderLayout());
        content.add(new JScrollPane(table));

        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(content);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Demo().initGUI();                
            }
        });
    }    
}

截图

enter image description here