Update a Jtable within a Jframe through another Jframe

Asked

Viewed 1,699 times

3

I own a JFrame, where inside it has a JTable and a JButton (Change) that makes the call from another Jframe. In this other Jframe, a data change is made according to the row selected in the table and saved in the BD by clicking on a Jbutton (Save).

My problem is that the data is not automatically updated in my Jtable when saving the change, so how do I call a function of a Jframe that is already open?

It doesn’t work to do the following:

public class JFAltera extends javax.swing.JFrame {
    ...
    private void jbSalvarActionPerformed(java.awt.event.ActionEvent evt) {
        JFrameTabela jFrameTabela = new JFrameTabela();
        jFrameTabela.atualizaJTable();
    }
    ...
}

public class JFrameTabela extends javax.swing.JFrame {
    ...
    public void atualizaJTable(){
        ...
    }
    ...
}

Because I don’t want to instantiate a new Jframe but call the (public) function of a Jframe that is already open.

Verifiable example of class:

Class Jframetable:

import javax.swing.table.DefaultTableModel;

public class JFrameTabela extends javax.swing.JFrame {

    public JFrameTabela() {
        initComponents();
        readJTable(); // Atualiza os dados na tabela
    }

    public void readJTable(){

        DefaultTableModel tableModel = (DefaultTableModel) jTable.getModel();

        //Inicia a tabela com 0 linhas novamente
        tableModel.setNumRows(0);

        //Inserir 10 Linhas
        for(int i = 0; i < 10; i++){
            tableModel.addRow(new Object[]{
                "Teste 1",
                "Teste 2",
                "Teste 3",
                "Teste 4"
            });
        }
    }

    @SuppressWarnings("unchecked")                        
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTable = new javax.swing.JTable();
        jbAlterar = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        jScrollPane1.setViewportView(jTable);

        jbAlterar.setText("Alterar");
        jbAlterar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbAlterarActionPerformed(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()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(226, 226, 226)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(426, 426, 426)
                        .addComponent(jbAlterar)))
                .addContainerGap(401, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(28, 28, 28)
                .addComponent(jbAlterar)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 70, Short.MAX_VALUE)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 228, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(89, 89, 89))
        );

        pack();
    }                      

    private void jbAlterarActionPerformed(java.awt.event.ActionEvent evt) {                                          
        //Abro o meu JFrameAltera e envio os dados da linha selecionada
        JFrameAltera obj = new JFrameAltera();
        obj.setVisible(true);
        obj.preencheDados(jTable.getValueAt(jTable.getSelectedRow(),0).toString(),
                jTable.getValueAt(jTable.getSelectedRow(),1).toString(),
                jTable.getValueAt(jTable.getSelectedRow(),2).toString(),
                jTable.getValueAt(jTable.getSelectedRow(),3).toString());
    }                                         

    public static void main(String args[]) {

        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(JFrameTabela.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(JFrameTabela.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(JFrameTabela.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(JFrameTabela.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }

        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new JFrameTabela().setVisible(true);
            }
        });
    }

    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable;
    private javax.swing.JButton jbAlterar;                 
}

Class Jframealtera:

public class JFrameAltera extends javax.swing.JFrame {


    public JFrameAltera() {
        initComponents();
    }

    public void preencheDados(String string1, String string2, String string3, String string4){

        //Preenche os campos com as informações das linha selecionada no "JFrameTabela"
        jf1.setText(string1);
        jf2.setText(string2);
        jf3.setText(string3);
        jf4.setText(string4);
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jf1 = new javax.swing.JTextField();
        jf2 = new javax.swing.JTextField();
        jf3 = new javax.swing.JTextField();
        jf4 = new javax.swing.JTextField();
        jbSalvar = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jbSalvar.setText("Salvar");
        jbSalvar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbSalvarActionPerformed(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()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(117, 117, 117)
                        .addComponent(jf1, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(32, 32, 32)
                        .addComponent(jf2, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(36, 36, 36)
                        .addComponent(jf3, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jf4, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(241, 241, 241)
                        .addComponent(jbSalvar)))
                .addContainerGap(458, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(69, 69, 69)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jf1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jf2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jf3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jf4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(63, 63, 63)
                .addComponent(jbSalvar)
                .addContainerGap(292, Short.MAX_VALUE))
        );

        pack();
    }                      

    private void jbSalvarActionPerformed(java.awt.event.ActionEvent evt) {                                         

        //Aqui eu gravo as informações no BD (Funcionando)

        //***********É aqui que eu preciso chamar minha função "readJTable" do "JFrameTabela" que já está aberto.
    }                                        


    public static void main(String args[]) {

        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(JFrameAltera.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(JFrameAltera.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(JFrameAltera.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(JFrameAltera.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new JFrameAltera().setVisible(true);
            }
        });
    }

    private javax.swing.JButton jbSalvar;
    private javax.swing.JTextField jf1;
    private javax.swing.JTextField jf2;
    private javax.swing.JTextField jf3;
    private javax.swing.JTextField jf4;

}
  • Please present a [mcve] so that it is possible to test the problem and suggest a solution.

  • 2

    You said "nesse outro JFrame é realizado a alteração dos dados no BD", if you are mixing GUI code with BD code (for example, putting code that directly accesses the BD within an actionPerformed() ) this is considered bad practice (as far as I know) and you may have problems with coupling issues, violation of the DRY, etc..

  • Not to mention that if you want to change data from one screen through another, using 2 Jframes is a very wrong approach. That is exactly what Jdialog exists for, as suggested in the other answer.

  • private void jbSalvarActionPerformed(java.awt.event.ActionEvent evt) { unless the language has new features that I am not aware of, this method is not implementing the actionPerformed() because his name is different. Try putting a @Override on top of it and see if an error appears in the IDE. Also, to listen to events your class would have to be a ActionListener, and I don’t see you implementing that interface. Finally, to be able to access an instantiated Jframe, just have an instance variable (or static) with this Jframe, and call it later.

  • 1

    @Douglas using variable static swing components is a bad practice. Swing components should always be manipulated within the EDT, being static, this can cause problems.

  • @Article This method is to get my fields to start with the line information that was selected in Jframetable

  • @Article in my project I am working with Object, but for verifiable version, I did with String same.

  • @Lucash.Pink the ideal is you work with abstraction, what does each row of this table represent? If you have to keep exchanging data and have to pick up text fields, your code is gonna be a mess.

  • @Article Each line of this jTable represents a record in my database.

  • Well I will try to answer with what I can answer, but I do not guarantee that it can serve for your real code, since you did not present an example of it, but a totally different generic example.

  • @Thanks for your attention, anything tells me I pass more details. I can also post my code here, but since you’re communicating with the comic, it won’t be verifiable, but I believe it might help you understand what I want to do. I tried to get as close as possible in the verifiable example. VLW Abs

Show 7 more comments

1 answer

2


When working with more than one screen, the ideal is always to use only one JFrame as main screen and create JDialogs as secondary screens, because beyond the modal feature, you can link all to the main frame.

As the code presented is very generic, I will try to respond on top of it. Following the previous tip, I recommend you change the class JFrameAltera to be a JDialog class-dependent JFrameTabela, so it becomes much easier to exchange information between them.

Then the class signature would look like this:

public class JFrameAltera extends javax.swing.JDialog {

Another detail is that on the button that opens the new window, you are passing the sequence between 1 and 4 as number of columns, when in fact the numbering of rows and columns in java always starts from 0, therefore the numbering for 4 columns goes from 0 to 3. Another problem is that you do not check if there is actually any row selected in the table before recovering the data, and this will burst ArrayIndexOutOfBoundsException, for the method getSelectedRow() returns -1 when there is no selection, and -1 is not part of the row range of a table.

In your class JFrameAltera, after changing to JDialog, the builder will be like this:

public JFrameAltera(Frame parent, boolean isModal) {
    super(parent, isModal);
    initComponents();
}

The first parameter represents which frame the screen originated from, and the second parameter makes the modal screen (i.e., while it is open, the original screen is locked for change).

In the save button event, you will continue saving the new data in the database, and close the screen by adding this.dispose();.

Based on the code presented, you will create a method where you will abstract the data saved in an object and return it, I used the class Object here just to demonstrate:

 public Object[] recuperaDados(){

    Object[] obj = {
     jf1.getText(),
     jf2.getText(),
     jf3.getText(),
     jf4.getText()
    };

     return obj;
 }

Now in the main class, in the same method where you open the change window, you will change as below:

private void jbAlterarActionPerformed(java.awt.event.ActionEvent evt) {

    if (jTable.getSelectedRow() != -1) {
        JFrameAltera tela2 = new JFrameAltera(this, true);
        tela2.preencheDados(jTable.getValueAt(jTable.getSelectedRow(), 0).toString(),
                jTable.getValueAt(jTable.getSelectedRow(), 1).toString(),
                jTable.getValueAt(jTable.getSelectedRow(), 2).toString(),
                jTable.getValueAt(jTable.getSelectedRow(), 3).toString());
        tela2.setVisible(true);

        Object[] obj = tela2.recuperaDados();
        for (int i = 0; i < obj.length && i < jTable.getColumnCount(); i++) {
            jTable.setValueAt(obj[i], jTable.getSelectedRow(), i);
        }
    }
}

The method now checks if there is a line selected before opening the screen(getSelectedRow() != -1), and as soon as the screen is closed, already recovers the data and saved in the table.

With these changes, the method readtable loses its meaning and can be removed.

  • It worked perfectly; Thank you!

  • @Lucash.Rosa good that even the answer being a little Generica, helped you. You can conclude the doubt by accepting the answer by clicking on v her left :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.