简体   繁体   English

自定义TableCellEditor仅适用于1列差异,并且已应用于所有

[英]Custom TableCellEditor only working on 1 Column Dispite applied to all

I have a rather complex JTable I'm working on. 我正在处理一个相当复杂的JTable。 The number of rows and columns are build off a list. 行和列的数量基于列表。 Then depending on what column of what row the cell editor needs to change out. 然后,根据单元格编辑器需要更改为哪一行的哪一列。 While Goggling for a solution I found this: http://www.java2s.com/Code/Java/Swing-Components/EachRowwithdifferentEditorExample.htm 搜寻解决方案时,我发现了这一点: http : //www.java2s.com/Code/Java/Swing-Components/EachRowwithdifferentEditorExample.htm

I took that code as it was and run it just to make sure it was working the current Java versions and it did. 我按原样使用该代码并运行它,以确保它可以在当前的Java版本上正常运行。 So i worked it into my JTable i had already build, but what seems to be happening is when I go to apply it to multiple columns it only ends up working for the first column. 因此,我将其应用于已经构建的JTable中,但是似乎正在发生的事情是,当我将其应用于多个列时,它只能在第一列中工作。

I put together a fully executable section of code that I have commented and set up to simulate my database data. 我整理了一段完全可执行的代码,并将其注释并设置为模拟数据库数据。 The code is pretty decently commented so should be easy to follow. 该代码是相当体面的注释,因此应该易于遵循。 This sample does at least for me still produces the problem. 这个样本至少对我而言仍然会产生问题。

If any of you can see whats wrong I would greatly appreciate the help. 如果您有任何发现错误的地方,我将不胜感激。

import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;


public class EachRowEditorExample extends JFrame {

    public EachRowEditorExample() {
        super("EachRow Editor Example");
        List<Membership> _Memberships = new ArrayList<Membership>();
        DefaultTableModel DataModel;

        //Lets Start by simluating the data.
        for (int z = -2; z < 10; z++)
        {
            Membership m = new Membership();
            m.setId(z);
            if (z == -2) 
            {
                m.setMembership("Employee");
                m.setEft(false);
            }
            else if (z == -1) 
            {
                m.setMembership("NONE");
                m.setEft(false);
            }
            else
            {
                m.setMembership("Membership " + z);
                if (z < 3 )
                    m.setEft(true);
                else
                    m.setEft(false);
            }
            _Memberships.add(m);
        }

        //*******************************************************
        // Starts Copy and paste from Program
        //*******************************************************
        //lets build our Data Model
        int size = _Memberships.size(); 
        Object[][] rows = new Object[size][];
        String[] cols = new String[size];
        int x = 0;
        for(Iterator<Membership> i = _Memberships.iterator(); i.hasNext(); )
        {
            Membership side = i.next();
            cols[x] = side.getMembership();
            Object[] row = new Object[size];
            int b = 0;
            for(Iterator<Membership> j = _Memberships.iterator(); j.hasNext(); )
            {
                Membership top = j.next();
                if (side.getId() == top.getId() && (side.isEft() && top.isEft()))
                {
                    row[b] = null;
                }
                else
                    row[b] = NUHPADX(side.getId(), top.getId());
                b++;
            }
            rows[x] = row;
            x++;
        }
        DataModel = new DefaultTableModel(rows,cols);


        //Now Lets create our JTable and configure it.
        JTable table = new JTable(DataModel) {
            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                Object t = getValueAt(rowIndex, rowIndex);
                if (t == null)
                    return false;
                else
                    return true;
            }

            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
            {
                Component c = super.prepareRenderer(renderer, row, column);

                Object t = getValueAt(row, column);
                if (t == null)
                {
                    c.setBackground(Color.black);
                }
                else
                {
                    Color PRIMARY_ROW_COLOR = Color.white; 
                    Color ALTERNATE_ROW_COLOR = new Color(0xA9F1ED);

                    //even index, selected or not selected
                    if (row % 2 == 0) 
                    {
                        if (column % 2 == 0) 
                            c.setBackground(PRIMARY_ROW_COLOR.darker());
                        else
                            c.setBackground(PRIMARY_ROW_COLOR);
                    }
                    else 
                    {
                        if (column % 2 == 0) 
                            c.setBackground(ALTERNATE_ROW_COLOR.darker());
                        else
                            c.setBackground(ALTERNATE_ROW_COLOR);
                    }
                }
                return c;
            }

        };
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.getTableHeader().setReorderingAllowed(false);
        JList rowHeader = new JList(cols);
        rowHeader.setCellRenderer(new RowHeaderRenderer(table));

        //Lets Place the new table in a Scroll Pane Since there could be alot of data.
        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setRowHeaderView(rowHeader);
        getContentPane().add(scrollPane, BorderLayout.CENTER);

        //Now lets Build the Cell Editors
        int c = 0;
        int r = 0;
        for(Iterator<Membership> a = _Memberships.iterator(); a.hasNext();)
        {
            Membership top = a.next();
            EachRowEditor rowEditor = new EachRowEditor(table);
            for(Iterator<Membership> b = _Memberships.iterator(); b.hasNext();)
            {
                Membership side = b.next();

                if (side.getId() == top.getId() && (side.isEft() && top.isEft()))
                {
                    //rowEditor.setEditorAt(r, null);
                }
                else if (side.getId() != top.getId() && (side.isEft() && top.isEft()))
                {
                    NuhpadxCell t = new NuhpadxCell(side, top, new DefaultComboBoxModel(new String[] {"N", "U", "D", "A"}));
                    t.setSelectedItem(NUHPADX(side.getId(), top.getId()));
                    rowEditor.setEditorAt(r, new DefaultCellEditor(t));
                }
                else 
                {
                    NuhpadxCell t = new NuhpadxCell(side, top, new DefaultComboBoxModel(new String[] {"N", "A", "H", "X", "P"}));
                    t.setSelectedItem(NUHPADX(side.getId(), top.getId()));
                    rowEditor.setEditorAt(r, new DefaultCellEditor(t));
                }
                r++;
            }
            table.getColumn(top.getMembership()).setCellEditor(rowEditor);
            table.revalidate();
            c++;
        }

        table.removeColumn(table.getColumn("NONE"));

        //*******************************************************
        // Ends Copy and paste from Program
        //*******************************************************
        setSize(1060, 600);
        setVisible(true);
    }

    //This function jsut simluates a entire class
    public String NUHPADX(int side, int top)
    {
        Random generator = new Random();
        int roll = generator.nextInt(7);
        switch (roll)
        {
            case 0:
                return "N";
            case 1:
                return "U";
            case 2:
                return "H";
            case 3:
                return "P";
            case 4:
                return "A";
            case 5:
                return "P";
            case 6:
                return "A";
            default:
                return "N";
        }

    }

    public static void main(String[] args) {
        EachRowEditorExample frame = new EachRowEditorExample();
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
}

//Example from http://www.crionics.com/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1) */
class EachRowEditor implements TableCellEditor {
    protected Hashtable editors;

    protected TableCellEditor editor, defaultEditor;

    JTable table;

    /**
     * Constructs a EachRowEditor. create default editor
     * 
     * @see TableCellEditor
     * @see DefaultCellEditor
     */
    public EachRowEditor(JTable table) {
        this.table = table;
        editors = new Hashtable();
        defaultEditor = new DefaultCellEditor(new JTextField());
    }

    /**
     * @param row
     *            table row
     * @param editor
     *            table cell editor
     */
    public void setEditorAt(int row, TableCellEditor editor) {
        editors.put(new Integer(row), editor);
    }

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        editor = (TableCellEditor) editors.get(new Integer(row));
        if (editor == null) {
            editor = defaultEditor;
        }
        return editor.getTableCellEditorComponent(table, value, isSelected, row, column);
    }

    public Object getCellEditorValue() {
        return editor.getCellEditorValue();
    }

    public boolean stopCellEditing() {
        return editor.stopCellEditing();
    }

    public void cancelCellEditing() {
        editor.cancelCellEditing();
    }

    public boolean isCellEditable(EventObject anEvent) {
        selectEditor((MouseEvent) anEvent);
        return editor.isCellEditable(anEvent);
    }

    public void addCellEditorListener(CellEditorListener l) {
        editor.addCellEditorListener(l);
    }

    public void removeCellEditorListener(CellEditorListener l) {
        editor.removeCellEditorListener(l);
    }

    public boolean shouldSelectCell(EventObject anEvent) {
        selectEditor((MouseEvent) anEvent);
        return editor.shouldSelectCell(anEvent);
    }

    protected void selectEditor(MouseEvent e) {
        int row;
        if (e == null) {
            row = table.getSelectionModel().getAnchorSelectionIndex();
        } else {
            row = table.rowAtPoint(e.getPoint());
        }
        editor = (TableCellEditor)editors.get(new Integer(row));
        if (editor == null) {
            editor = defaultEditor;
        }
    }
}

//*******************************************************
// Starts Copy and paste from Program
//*******************************************************
class RowHeaderRenderer extends JLabel implements ListCellRenderer {
    private static final long serialVersionUID = 4619707414623897299L;

    public RowHeaderRenderer(JTable table) {
        JTableHeader header = table.getTableHeader();
        setOpaque(true);
        setBorder(UIManager.getBorder("TableHeader.cellBorder"));
        setHorizontalAlignment(CENTER);
        setForeground(header.getForeground());
        setBackground(header.getBackground());
        setFont(header.getFont());
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        setText((value == null) ? "" : value.toString());
        return this;
    }
}

class NuhpadxCell extends JComboBox {
    private static final long serialVersionUID = -4464709511574911230L;

    private Membership _side;
    private Membership _top;

    public NuhpadxCell(Membership s, Membership t, DefaultComboBoxModel aModel)
    {
        _side = s;
        _top = t;
        addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                DoUpdate();
            }

        });

        setModel(aModel);
    }

    private void DoUpdate() {
        // I would then update my database useing the ID of the side and top memberships as keys.
    }
}

//*******************************************************
// Ends Copy and paste from Program
//*******************************************************

//A bare Skeleton of the membership class needed to run this code.
class Membership {

    protected int id;
    protected String membership;
    protected boolean eft;

    public int getId() {
        return id;
    }
    public void setId(int value) {
        this.id = value;
    }

    public String getMembership() {
        return membership;
    }
    public void setMembership(String value) {
        this.membership = value;
    }

    public boolean isEft() {
        return eft;
    }
    public void setEft(boolean value) {
        this.eft = value;
    }
}

1.issue came from code line, 1.问题来自代码行,

table.removeColumn(table.getColumn("NONE"));

2.then JTables view returns different column index as are stored into TableModel , you have to call table.convertColumnIndexToModel() in the prepareRenderer and Editor too 2.然后JTables view返回存储在TableModel不同column index ,您也必须在prepareRendererEditor调用table.convertColumnIndexToModel()

3.remove isCellXxx from JTable to the Model ei 3.将isCellXxxJTable isCellXxxModel ei

DataModel = new DefaultTableModel(rows, cols) {

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        Object t = getValueAt(rowIndex, rowIndex);
        if (t == null) {
            return false;
        } else {
            return true;
        }
    }
};

4.call table.setPreferredScrollableViewportSize(table.getPreferredSize()); 4.调用table.setPreferredScrollableViewportSize(table.getPreferredSize()); then you can to change setSize(1060, 600); 然后您可以更改setSize(1060, 600); to pack(); pack();

5.add there setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 5.在其中添加setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); too

6.don't extends JFrame , create an local variable 6.不要扩展JFrame ,创建局部变量

7.then your main class should be including InitialThread 7,那么你的主类应该包括InitialThread

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            EachRowEditorExample frame = new EachRowEditorExample();
        }
    });
}

EDIT 编辑

1, I just wanted to hide that column not actually completely remove it from the Model, which is what that code should be doing (according to Java Docs). 1,我只是想隐藏该列,而实际上并没有完全将其从Model中删除,这正是该代码应该执行的操作(根据Java Docs)。

table.removeColumn(table.getColumn("NONE")); remove concrete Column only from JTables View more in the API and JTables tutorial , this Column is still presents in the XxxTableModel , better would be to test that on your side 仅从JTables View删除具体的ColumnAPIJTables tutorial JTables View更多内容 ,该Column仍存在于XxxTableModel ,最好是在您这一边进行测试

as for 2, not sure why that really applies. 至于2,不确定为什么真的适用。

this is already answered, more is described in the JTable tutorial (read the next section too) 这已经得到解答, JTable教程中对此进行了更多描述(也请阅读下一节)

Your solution seems awfully complicated for something that looks quite simple. 对于看起来很简单的问题,您的解决方案似乎非常复杂。 You actually only have two different CellEditor which are both based on a JComboBox. 实际上,您只有两个不同的CellEditor,它们都基于JComboBox。

So, a simpler solution would be to extend DefaultCellEditor with a JComboBox and override getTableCellEditorComponent(), depending on which row you are on, you update the JComboBox with the appropriate model and you return the call to super . 因此,一个更简单的解决方案是使用JComboBox扩展DefaultCellEditor并重写getTableCellEditorComponent(),具体取决于您所在的行,使用适当的模型更新JComboBox并将调用返回给super

Eventually, you set this cell editor on all your columns of the table. 最终,您在表格的所有列上都设置了该单元格编辑器。

Also consider following Java coding conventions (variables and methods starts with a lower case letter, classes starts with an upper case letter, etc...) 还请考虑遵循以下Java编码约定(变量和方法以小写字母开头,类以大写字母开头,等等。)

EDIT: 编辑:

    class MyTableCellEditor extends DefaultCellEditor {
        private DefaultCellEditor defaultEditor;
        private DefaultComboBoxModel nudaModel = new DefaultComboBoxModel(new String[] { "N", "U", "D", "A" });
        private DefaultComboBoxModel nahxpModel = new DefaultComboBoxModel(new String[] { "N", "A", "H", "X", "P" });

        public MyTableCellEditor() {
            super(new JComboBox());
            defaultEditor = new DefaultCellEditor(new JTextField());
        }

        private JComboBox getComboBox() {
            return (JComboBox) editorComponent;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            Membership top = _Memberships.get(column);
            Membership side = _Memberships.get(row);

            if (side.getId() == top.getId() && side.isEft() && top.isEft()) {
                return defaultEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
            } else if (side.getId() != top.getId() && side.isEft() && top.isEft()) {
                getComboBox().setModel(nudaModel);
            } else {
                getComboBox().setModel(nahxpModel);
            }
            return super.getTableCellEditorComponent(table, NUHPADX(side.getId(), top.getId()), isSelected, row, column);
        }
    }

And here is implementation of what your TableModel could look like: 这是TableModel看起来的实现:

    class MyDataModel extends AbstractTableModel{

        @Override
        public int getRowCount() {
            return _Memberships.size();
        }

        @Override
        public int getColumnCount() {
            return _Memberships.size();
        }

        @Override
        public String getColumnName(int column) {
            // Here feel free to return the appropriate column names.
            return super.getColumnName(column);
        }

        @Override
        public Object getValueAt(int row, int column) {
            return NUHPADX(_Memberships.get(row).getId(), _Memberships.get(column).getId());
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            // Here you can do whatever you want to say that is editable or not
            // If it is editable, you need to override setValueAt
            return true;
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            // Here you need to implement the update of your model
        }

    }

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

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