JTable getValueAt () behaving differently than expected

5

I have a JFrame where there is a JTable that displays some data. When the user selects some records and clicks a certain button, these selected records must be deleted.

When only one record is selected, everything works perfectly, but problems start from two records.

Let's say I decide to delete the following records:

WhenyouclickDeleteselectedrecord(s),theresultisthis:

Asyoucansee,theindexesareincreasingby2in2:1(0),3(2),5(4)...

ThisisthecodeI'musingtodothis:

publicclassNewJFrameextendsjavax.swing.JFrame{privateDefaultTableModeltbModelo;privateArrayList<String[]>tableData=newArrayList<String[]>();publicNewJFrame(){tbModelo=newDefaultTableModel(null,newString[]{"ID", "Sequência", "Chave"}){
            //Torna as celulas da tabela readonly. Para permitir alterações retorne true;
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        initComponents();

        //Impede que o usuário reposicione as colunas na tabela
        jTable1.getTableHeader().setReorderingAllowed(false);

        preencheTabela();
    }

    private void preencheTabela(){
        for(int i = 1; i < 10; i++){
            tbModelo.addRow(new String[]{String.valueOf(i),"0000", "1234"});
        }
    }

    //Desenha os elementos da UI
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);


        jTable1.setModel(tbModelo);
        jScrollPane1.setViewportView(jTable1);

        jButton1.setText("Excluir");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 452, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButton1))
                .addContainerGap(53, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 275, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton1)
                .addContainerGap(30, Short.MAX_VALUE))
        );

        pack();
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        int qtdLinhasSelecionadas = jTable1.getSelectedRowCount();

        if(qtdLinhasSelecionadas > 0){
            //Armazena os indices das linhas selecionadas
            int[] linhasSelecionadas = jTable1.getSelectedRows();

            for(int linha : linhasSelecionadas){

                //Extrai o valor da coluna 'ID' na JTable independente da sua posição na tela
                String user_id = (String) jTable1.getModel().getValueAt(jTable1.convertRowIndexToModel(linha), 0);

                tbModelo.removeRow(linha);

            }
        }

    }                                        

    private javax.swing.JButton jButton1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;

}

Additionally, when you select all records and click Delete , you receive an ArrayIndexOutOfBoundsException:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3 >= 2
at java.util.Vector.elementAt(Vector.java:474)
at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:648)
at leitorabntkey.GerarChave.btApagarSelecionadoActionPerformed(GerarChave.java:399)
at leitorabntkey.GerarChave.access$700(GerarChave.java:37)
at leitorabntkey.GerarChave$7.actionPerformed(GerarChave.java:227)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6533)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6298)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

According to the documentation of the getValueAt it should return the value of the cell row x column , as in an array, but apparently this is not what happens.

In Sage's answer is I can see that getValueAt returns the values of cells based on the JTable template (DefaultTableModel in my case) and in what I could identify here, both the model and the view are of the same structure (JTable is with the reorganization of columns disabled ).

Is there something I'm not noticing here? Or some other way to do what I want?

    
asked by anonymous 19.11.2016 / 02:22

1 answer

4

Try changing the following line:

String user_id =  (String)tableChavesRegistradas.getModel().getValueAt(tableChavesRegistradas.convertRowIndexToModel(linha), 0); 

What has to be converted is the internal table index for the equivalent in TableModel, you were using the method that does the opposite.

And to prevent the exception from popping up when deleting multiple lines, the solution to solving the ArrayIndexOutOfBoundsException problem follows:

if(qtdLinhasSelecionadas > 0){

    int[] linhasSelecionadas = jTable1.getSelectedRows();

    for(int i = linhasSelecionadas.length-1; i >= 0; i--){

        String user_id = (String) jTable1.getModel().getValueAt(jTable1.convertRowIndexToModel(linhasSelecionadas[i]), 0);

        tbModelo.removeRow(linhasSelecionadas[i]);
    }

}

Testing the change, the result was this:

The secret of this for is to remove the selected rows from the largest to the smallest indexes because internally DefaultTableModel rearranges the indexes of the remaining rows at each removal, popping up the displayed exception if you try to delete a larger index row . By always removing the larger index, this will not happen.

    
19.11.2016 / 03:02