Bonjour à tous,

J'ai un problème un peu perturbant, voilà le code, je vous expliquerais en dessous le problème que je rencontre (lisez le code avant histoire que je ne vous influence pas).

Member.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
public class Member
{
    private int id;
    private String firstname;
    private String lastname;
 
    public Member()
    {
    }
 
    public Member(int id, String firstname, String lastname)
    {
        this.id = id;
        this.firstname = firstname;
        this.lastname = lastname;
    }
 
    public int getId()
    {
        return this.id;
    }
 
    public Member setId(int id)
    {
        this.id = id;
        return this;
    }
 
    public String getFirstname()
    {
        return this.firstname;
    }
 
    public Member setFirstname(String firstname)
    {
        this.firstname = firstname;
        return this;
    }
 
    public String getLastname()
    {
        return this.lastname;
    }
 
    public Member setLastname(String lastname)
    {
        this.lastname = lastname;
        return this;
    }
}
MemberTable.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
 
public class MemberTable extends JPanel
{
    // Buttons
    protected JButton action_add = new JButton("Ajouter");
    protected JButton action_delete = new JButton("Supprimer");
 
    // Titles
    protected JLabel title_top = new JLabel("Membres");
 
    // Content
    protected AbstractTable<Member> gui_content = new AbstractTable<Member>();
    protected MemberModelTable content;
 
     public MemberTable()
     {
        this.setLayout(new GridBagLayout());
        content = new MemberModelTable(this.gui_content);
 
        // Listeners
        this.action_add.addActionListener(new AddTableListener<Member>(this.gui_content));
        this.action_delete.addActionListener(new DeleteTableListener<Member>(this.gui_content));
        new CellListenerTable(this.gui_content.getContent(), new UpdateTableListener<Member>(this.gui_content));
 
        // GUI construction
        this.add(this.title_top, new GridBagConstraints(0,0,2,1, 0, 0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
        this.add(this.gui_content, new GridBagConstraints(0,1,2,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
        this.add(this.action_add, new GridBagConstraints(0,2,1,1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
        this.add(this.action_delete, new GridBagConstraints(1,2,1,1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
    }
 }
MemberModelTable.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 
import java.util.ArrayList;
 
public class MemberModelTable extends AbstractModelTable<Member>
{
 
    public MemberModelTable(AbstractTable<Member> content)
    {
        super(content, new ArrayList<String>(), new ArrayList<Member>());
        this.headers.add("Prénom");
        this.headers.add("Nom");
        this.content.setModel(this);
        this.content.getContent().getColumnModel().getColumn(0).setCellEditor(new TextColumnEditor());
        this.content.getContent().getColumnModel().getColumn(1).setCellEditor(new TextColumnEditor());
    }
 
    public Object getValueAt(int rowIndex, int columnIndex)
    {
        switch (columnIndex)
        {
            case 0:
                return this.lines.get(rowIndex).getFirstname();
            case 1:
                return this.lines.get(rowIndex).getLastname();
            default:
                return "";
        }
    }
 
    public void setValueAt(Object aVal, int rowIndex, int columnIndex)
    {
        if (rowIndex < 0)
            return;
 
        switch (columnIndex)
        {
            case 0:
                this.lines.get(rowIndex).setFirstname(aVal.toString());
                break;
            case 1:
                this.lines.get(rowIndex).setLastname(aVal.toString());
                break;
            default:
                break;
        }
    }
 
    @Override
    public Class getColumnClass(int columnIndex)
    {
        return Object.class;
    }
 
    @Override
    public Member getModel(int line, int column)
    {
        return null;
    }
 
    @Override
    public Member getModel(int line)
    {
        return this.lines.get(line);
    }
 
    public boolean isCellEditable(int row, int column)
    {
       return true;
    }
 
    @Override
    public MemberModelTable newLine()
    {
        this.lines.add(new Member());
        return this;
    }
 
    @Override
    public int getNextRequiredColumn(int row)
    {
        Member c = this.getModel(row);
        if (c != null)
        {
            if (c.getFirstname() == null || c.getFirstname().length() == 0)
                return 0;
 
            if (c.getLastname() == null || c.getLastname().length() == 0)
                return 1;
        }
 
        return -1;
    }
 
    @Override
    public void save(int row)
    {
    }
}
AbstractTable.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 
 
import java.awt.Dimension;
 
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
 
public class AbstractTable extends JScrollPane
{
    private AbstractModelTable<N> model;
    private JTable content;
    public AbstractTable()
    {
        super();
    }
 
    public AbstractTable<N> setModel(AbstractModelTable<N> model)
    {
        this.model = model;
        this.content = new JTable(this.model);
        this.content.setRowHeight(28);
        this.setViewportView(this.content);
        return this;
    }
 
    public AbstractModelTable<N> getModel()
    {
        return this.model;
    }
 
    public JTable getContent()
    {
        return this.content;
    }
}
AbstractModelTable :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 
 
 
import java.util.List;
 
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
 
 
public abstract class AbstractModelTable<N> extends AbstractTableModel
{
    protected AbstractTable<N> content;
    protected List<N> lines;
    protected List<String> headers;
 
    public AbstractModelTable(AbstractTable<N> content, List<String> headers, List<N> lines)
    {
        super();
        this.content = content;
        this.lines = lines;
        this.headers = headers;
    }
 
    public int getRowCount()
    {
        return lines.size();
    }
 
    public int getColumnCount()
    {
        return headers.size();
    }
 
    public String getColumnName(int columnIndex)
    {
        return headers.get(columnIndex);
    }
 
    public Object getValueAt(int rowIndex, int columnIndex)
    {
        return lines.get(rowIndex);
    }
 
    public AbstractModelTable<N> setLines(List<N> lines)
    {
        this.lines = lines;
        this.fireTableDataChanged();
        return this;
    }
 
    public List<N> getLines()
    {
        return this.lines;
    }
 
    public void removeRow(int row)
    {
        this.lines.remove(row);
 
    }
 
    public AbstractTable<N> getContent()
    {
        return content;
    }
 
    public abstract AbstractModelTable<N> newLine();
 
    public abstract N getModel(int line, int column);
    public abstract N getModel(int line);
    public abstract int getNextRequiredColumn(int row);
    public abstract void save(int row);
}

AddTableListener :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
 
/**
 * @author gdifolco
 *
 */
public class AddTableListener<N> extends AbstractTableListener implements ActionListener
{
    public AddTableListener(AbstractTable<N> obs)
    {
        super(obs);
    }
 
    @Override
    public void actionPerformed(ActionEvent e)
    {
        this.obs.getModel().newLine().fireTableDataChanged();
        int sel = this.obs.getModel().getNextRequiredColumn(this.obs.getModel().getLines().size() - 1);
 
        if (sel == -1)
            sel = 0;
 
        if (this.obs.getContent().editCellAt(this.obs.getModel().getLines().size() - 1, sel))
            this.obs.getContent().getEditorComponent().requestFocus();
        else if (this.obs.getContent().editCellAt(this.obs.getModel().getLines().size() - 1, sel))
            this.obs.getContent().getEditorComponent().requestFocus();
 
    }
}
DeleteTableListener :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 
 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
 
public class DeleteTableListener extends AbstractTableListener implements ActionListener
{
    public DeleteTableListener(AbstractTable obs)
    {
        super(obs);
    }
 
    @Override
    public void actionPerformed(ActionEvent e)
    {
        int[] rows = this.obs.getContent().getSelectedRows();
        for (int i = rows.length - 1; i >= 0; --i)
          this.obs.getModel().removeRow(rows[i]);
 
        this.obs.getModel().fireTableDataChanged();
 
        if (rows.length > 0)
        {
            Integer nb_lines = this.obs.getModel().getLines().size();
            if (nb_lines > 0)
            {
                if (rows[0] < nb_lines)
                    this.obs.getContent().getSelectionModel().addSelectionInterval(rows[0], rows[0]);
                else
                    this.obs.getContent().getSelectionModel().addSelectionInterval(nb_lines-1, nb_lines-1);
            }
        }
    }
}

AbstractTableListener :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
 
public class AbstractTableListener
{
 
    protected AbstractTable obs;
    public AbstractTableListener(AbstractTable obs)
    {
        this.obs = obs;
    }
}
UpdateTableListener :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
 
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
 
import javax.swing.AbstractCellEditor;
import javax.swing.Action;
import javax.swing.DefaultCellEditor;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellEditor;
 
public class UpdateTableListener<N> extends AbstractTableListener implements Action
{
    protected boolean enabled;
    public UpdateTableListener(AbstractTable<N> obs)
    {
        super(obs);
        this.enabled = true;
    }
 
    @Override
    public void actionPerformed(ActionEvent e)
    {
        CellListenerTable tcl = (CellListenerTable)e.getSource();
        this.obs.getModel().setValueAt(tcl.getNewValue(), tcl.getRow(), tcl.getColumn());
        int sel = this.obs.getModel().getNextRequiredColumn(tcl.getRow());
 
        if (sel == -1)
            this.obs.getModel().save(tcl.getRow());
        else
            this.obs.getContent().editCellAt(tcl.getRow(), sel);
    }
 
    @Override
    public void addPropertyChangeListener(PropertyChangeListener arg0)
    {
        // TODO Auto-generated method stub
    }
 
    @Override
    public Object getValue(String arg0)
    {
        // TODO Auto-generated method stub
        return null;
    }
 
    @Override
    public boolean isEnabled()
    {
        return this.enabled;
    }
 
    @Override
    public void putValue(String arg0, Object arg1)
    {
        // TODO Auto-generated method stub
 
    }
 
    @Override
    public void removePropertyChangeListener(PropertyChangeListener arg0)
    {
        // TODO Auto-generated method stub
 
    }
 
    @Override
    public void setEnabled(boolean arg0)
    {
        this.enabled = arg0;
 
    }
 
}

CellListenerTable :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
 
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
 
/*
 *  This class listens for changes made to the data in the table via the
 *  TableCellEditor. When editing is started, the value of the cell is saved
 *  When editing is stopped the new value is saved. When the oold and new
 *  values are different, then the provided Action is invoked.
 *
 *  The source of the Action is a TableCellListener instance.
 */
public class CellListenerTable implements PropertyChangeListener, Runnable
{
    private JTable table;
    private Action action;
 
    private int row;
    private int column;
    private Object oldValue;
    private Object newValue;
 
    /**
     *  Create a TableCellListener.
     *
     *  @param table   the table to be monitored for data changes
     *  @param action  the Action to invoke when cell data is changed
     */
    public CellListenerTable(JTable table, Action action)
    {
        this.table = table;
        this.action = action;
        this.table.addPropertyChangeListener( this );
    }
 
    /**
     *  Create a TableCellListener with a copy of all the data relevant to
     *  the change of data for a given cell.
     *
     *  @param row  the row of the changed cell
     *  @param column  the column of the changed cell
     *  @param oldValue  the old data of the changed cell
     *  @param newValue  the new data of the changed cell
     */
    private CellListenerTable(JTable table, int row, int column, Object oldValue, Object newValue)
    {
        this.table = table;
        this.row = row;
        this.column = column;
        this.oldValue = oldValue;
        this.newValue = newValue;
    }
 
    /**
     *  Get the column that was last edited
     *
     *  @return the column that was edited
     */
    public int getColumn()
    {
        return column;
    }
 
    /**
     *  Get the new value in the cell
     *
     *  @return the new value in the cell
     */
    public Object getNewValue()
    {
        return newValue;
    }
 
    /**
     *  Get the old value of the cell
     *
     *  @return the old value of the cell
     */
    public Object getOldValue()
    {
        return oldValue;
    }
 
    /**
     *  Get the row that was last edited
     *
     *  @return the row that was edited
     */
    public int getRow()
    {
        return row;
    }
 
    /**
     *  Get the table of the cell that was changed
     *
     *  @return the table of the cell that was changed
     */
    public JTable getTable()
    {
        return table;
    }
//
//  Implement the PropertyChangeListener interface
//
    @Override
    public void propertyChange(PropertyChangeEvent e)
    {
        //  A cell has started/stopped editing
 
        if ("tableCellEditor".equals(e.getPropertyName()))
        {
            if (table.isEditing())
                processEditingStarted();
            else
                processEditingStopped();
        }
    }
 
    /*
     *  Save information of the cell about to be edited
     */
    private void processEditingStarted()
    {
        //  The invokeLater is necessary because the editing row and editing
        //  column of the table have not been set when the "tableCellEditor"
        //  PropertyChangeEvent is fired.
        //  This results in the "run" method being invoked
 
        SwingUtilities.invokeLater( this );
    }
    /*
     *  See above.
     */
    @Override
    public void run()
    {
        row = table.convertRowIndexToModel( table.getEditingRow() );
        column = table.convertColumnIndexToModel( table.getEditingColumn() );
        oldValue = table.getModel().getValueAt(row, column);
        newValue = null;
    }
 
    /*
     *  Update the Cell history when necessary
     */
    private void processEditingStopped()
    {
        newValue = table.getModel().getValueAt(row, column);
 
        //  The data has changed, invoke the supplied Action
 
        if (newValue != null && !newValue.equals(oldValue))
        {
            //  Make a copy of the data in case another cell starts editing
            //  while processing this change
 
            CellListenerTable tcl = new CellListenerTable(
                getTable(), getRow(), getColumn(), getOldValue(), getNewValue());
 
            ActionEvent event = new ActionEvent(
                tcl,
                ActionEvent.ACTION_PERFORMED,
                "");
            action.actionPerformed(event);
        }
    }
}

TextColumnEditor :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
import javax.swing.DefaultCellEditor;
import javax.swing.JTextField;
 
public class TextColumnEditor extends DefaultCellEditor
{
 
    public TextColumnEditor()
    {
        super(new JTextField());
    }
 
    public boolean stopCellEditing()
    {
        String v = this.getCellEditorValue().toString();
        if(v == null || v.length() == 0)
        {
            this.fireEditingCanceled();
            return false;
        }
        return super.stopCellEditing();
    }
}
Bref, ça me donne une belle table avec deux colonnes, le hic c'est que ma première colonne est modifiable (c'est à dire que le setValueAt du TableModel est appelé correctement), mais lorsqu'il s'agit de ma seconde colonne, setValueAt a -1 en tant que rowIndex et columnIndex. Le gros soucis c'est que ça vient du CellEditor, même si je désactive l'appel à fire* et le return false j'ai le soucis, en gros dès que j'appelle (ou pour être précis dès que je tente un instruction (de type test)) j'ai le problème...

Ca me rend fou, avez-vous déjà eu ce problème ? avez vous une idée du soucis ? ais-je fait quelque chose de mal ?

Pour votre aide,
Par avance,
Merci.