简体   繁体   English

Java Swing:自定义单元格编辑器不返回最新值

[英]Java Swing: Custom Cell Editor does not return most recent value

I have created a custom cell editor which is attached to one of my JTable columns. 我创建了一个自定义单元格编辑器,该编辑器附加到我的JTable列之一。 The editor has either a JComboBox or a JTextField as component. 编辑器具有JComboBox或JTextField作为组件。 However, when I edit the value of the combo box manually and press "tab", the new - most recent - value is not attached to the JTable cell. 但是,当我手动编辑组合框的值并按“ tab”时,新的-最近-值未附加到JTable单元格。 Instead, the old value is replaced. 而是替换旧值。 (I have already implemented the "tab" behaviour with another code template but this works in general, because all other table cells are updated correctly) (我已经使用另一个代码模板实现了“ tab”行为,但这通常可以正常工作,因为所有其他表单元格均已正确更新)

The combo box, which causes the problem is set in "case C". 导致问题的组合框设置在“情况C”中。 If the user now selects the ITEM "Infinity", the value is successfully attached to the JTable. 如果用户现在选择ITEM“ Infinity”,则该值已成功附加到JTable。 However, if the user manually enters a value in the JTable and presses "tab", the new value is thrown away and the old value is rendered again in the table. 但是,如果用户在JTable中手动输入一个值并按下“ tab”,则新值将被丢弃,旧值将再次呈现在表中。 However, as a hotfix, if the user enters the value in the combobox, hits "ENTER" immediately after and THEN tabs, the value is written through jtable correctly! 但是,作为修补程序,如果用户在组合框中输入值,并在和THEN选项卡后立即单击“ ENTER”,则该值将通过jtable正确写入!

My custom cell editor implementation looks as follow: 我的自定义单元格编辑器实现如下所示:

public class CustomCellEditor extends AbstractCellEditor implements TableCellEditor {

    JFrame mParent                  = null;
    JFrame mPopup                   = null;
    String className                = "";

    protected int clickCountToStart = 2;

    private TableCellEditor mEditor = null;
    private JComboBox mComboBox     = null;

    public CustomCellEditor(JFrame parent, String className, JComboBox comboBox) {
        mParent             = parent;
        mClassName          = className;
        mComboBox           = comboBox;
    }

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

        if ( className.equals("case A") ) {

            mComboBox.setModel( new DefaultComboBoxModel(Constants.YES_NO_ARRAY) );
            mComboBox.setEditable(false);
            mEditor = new DefaultCellEditor(mComboBox);
        }
        else if ( className.equals("case B") ) {

            mComboBox.setModel( new DefaultComboBoxModel(Constants.LANG_ARRAY) );
            mComboBox.setEditable(false);
            mEditor = new DefaultCellEditor(mComboBox);
        }
        else if ( className.equals("case C") ) {

            // THIS is the case, when the Jcombobox become editable, so beside the pre-defined item "Constants.INFIINITY" any arbitrary input should be allowed!
            mComboBox.setModel ( new DefaultComboBoxModel(new String[]{Constants.INFINITY}) ) ;
            mComboBox.setEditable(true);
            mEditor = new DefaultCellEditor(mComboBox);
        }
        else {
            mEditor = new DefaultCellEditor(new JTextField());
        }

        return mEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
    }

    /**
    * Returns true if <code>anEvent</code> is <b>not</b> a
    * <code>MouseEvent</code>.  Otherwise, it returns true
    * if the necessary number of clicks have occurred, and
    * returns false otherwise.
    *
    * @param   anEvent         the event
    * @return  true  if cell is ready for editing, false otherwise
    * @see #setClickCountToStart
    * @see #shouldSelectCell
    */
    @Override
    public boolean isCellEditable(EventObject anEvent) {
        if (anEvent instanceof MouseEvent) {
            return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
        }
        return true;
    }

    @Override
    public Object getCellEditorValue() {
        if (mEditor != null) {

            return mEditor.getCellEditorValue();
        }
        return null;
    }

}

Does someone know what the reason could be that in case of "case C" i did not get the most reason value but the previous table value instead? 有人知道原因是什么吗?在“情况C”的情况下,我没有得到最多的原因值,而是得到了先前的表值?

Thank you 谢谢

Here is an example that allows you to use a different editor without creating a custom editor. 这是一个示例,允许您使用其他编辑器而无需创建自定义编辑器。 It overrides the getCellEditor(...) method of JTable: 它重写了JTable的getCellEditor(...)方法:

import java.awt.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;

public class TableComboBoxByRow extends JPanel
{
    List<String[]> editorData = new ArrayList<String[]>(3);

    public TableComboBoxByRow()
    {
        setLayout( new BorderLayout() );

        // Create the editorData to be used for each row

        editorData.add( new String[]{ "Red", "Blue", "Green" } );
        editorData.add( new String[]{ "Circle", "Square", "Triangle" } );
        editorData.add( new String[]{ "Apple", "Orange", "Banana" } );

        //  Create the table with default data

        Object[][] data =
        {
            {"Color", "Red"},
            {"Shape", "Square"},
            {"Fruit", "Banana"},
            {"Plain", "Text"}
        };
        String[] columnNames = {"Type","Value"};

        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        JTable table = new JTable(model)
        {
            //  Determine editor to be used by row
            public TableCellEditor getCellEditor(int row, int column)
            {
                int modelColumn = convertColumnIndexToModel( column );

                if (modelColumn == 1 && row < 3)
                {
                    JComboBox<String> comboBox1 = new JComboBox<String>( editorData.get(row));
                    return new DefaultCellEditor( comboBox1 );
                }
                else
                    return super.getCellEditor(row, column);
            }
        };

        JScrollPane scrollPane = new JScrollPane( table );
        add( scrollPane );

    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("Table Combo Box by Row");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new TableComboBoxByRow() );
        frame.setSize(200, 200);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

Your logic would be different because you are basing the editor on the class of the data in the cell, but the basic concept can be the same. 您的逻辑会有所不同,因为您将编辑器基于单元格中数据的类,但是基本概念可以相同。

你有尝试过吗?

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM