-1

I hope you can help me!!! I have a JComboBox, when I click the button "search" a JTable appears. When I change the selection of the JComboBox and click "search" again, the table changes its model and shows me the new datas, but if I click in there, the old model appears again. The data are from a database by a query.

I try to use dtm.setRowCount(0) but didn't works. I have only one JTable and I use the same dtm (DefaultTableModel) for every query.


public class store extends JPanel{
    
    int WIDTH = 1000;
    int HEIGHT = 600;
    String[] columnnames = new String[] {"id", "type", "cost"};
    JComboBox jcb;
    JButton button;
    DataBaseConnection dbc = new DataBaseConnection();
    
    public store() {
        super();
        this.setVisible(true);
        this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        this.setBackground(new Color(224, 224, 224));
        
        
        GroupLayout gLayout = new GroupLayout(this);
        gLayout.setAutoCreateGaps(true);
        gLayout.setAutoCreateContainerGaps(true);
        this.setLayout(gLayout);
        
         this.jcb = new JComboBox();
         
         
         this.button=new JButton("Search");
         button.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent evt) {
                 showTable();
             }
         });
         
         try { 
                Connection conn;
                try {
                    Class.forName("org.postgresql.Driver");
                
                conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/Try", "postgres",
                        "******");
                String sql = "select distinct type from try";
                PreparedStatement ps = conn.prepareStatement(sql);
                ResultSet rs2 = ps.executeQuery();
                while (rs2.next()) {

                    String aS = rs2.getString(1);
                    jcb.addItem(aS);
                }

                conn.close();

            } catch (SQLException e) {
                // TODO Auto-generated catch block

                e.printStackTrace();
            }
         } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
         
         
         gLayout.setHorizontalGroup(gLayout.createSequentialGroup()
                 .addGap(400)
                 .addComponent(jcb).addGroup(
                    gLayout.createParallelGroup(GroupLayout.Alignment.CENTER).addComponent(button)

            )


            );
            gLayout.setVerticalGroup(gLayout.createSequentialGroup()
                    .addGap(250)
                    .addGroup(gLayout.createParallelGroup(GroupLayout.Alignment.CENTER).addComponent(jcb)
                            .addComponent(button)
                            )
                    .addGap(250)
                    

            );
        
        
    }
    
    public void showTable() {

        DefaultTableModel dtm = new DefaultTableModel();
        
        JTable t = new JTable();
        
        
        dtm.setColumnIdentifiers(columnnames);
        
        JScrollPane pane = new JScrollPane(t);
        pane.setBounds(25, 120, 850, 150);
        
        String ta = jcb.getSelectedItem().toString();

        try { 
            
            Class.forName("org.postgresql.Driver");
            Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/Try",
                    "postgres", "*****");
            PreparedStatement pstm = conn.prepareStatement(
                    "SELECT try.* FROM try WHERE type=?");
            pstm.setString(1, ta);
            ResultSet Rs = pstm.executeQuery();
            
            
            
            while (Rs.next()) {
                dtm.addRow(new Object[] { Rs.getString(1), Rs.getString(2), Rs.getString(3) });
            }

            conn.close();
            
            
            t.setModel(dtm);
            add(pane);      
                    
               
            
            
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        
        
        
        
    }
}
blink727_
  • 1
  • 3
  • 2
    [Avoid null layouts in Swing](https://technojeeves.com/index.php/aliasjava1/114-avoid-null-layouts-in-swing) We need to see more code. You really need to provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) – g00se Feb 22 '23 at 13:20
  • This is part of the code, I already have a layout and everything works, the only thing that is giving me problem is this bug. I don't know how to clear the dtm before the reuse, can you help me? I tried with dtm.setRowCount(0), but didn't works. – blink727_ Feb 22 '23 at 13:28
  • I always remove each and every row from the `DefaultTableModel` when I want to clear the model. I use a reverse `for` loop, deleting from the last row to the first row. – Gilbert Le Blanc Feb 22 '23 at 13:52
  • most probably something wrong in the code you are not showing ;) As already suggested in the first comment by @g00se: please provide a [mcve] demonstrating your problem. And remove that abominable null layout .. it's plain __wrong__ and shouldn't be spread! – kleopatra Feb 22 '23 at 13:57
  • @GilbertLeBlanc you did it like this? `for(int i=dtm.getRowCount(); i>0;i--) { dtm.removeRow(i); }` I tried to put it before the while but it didn't work. Any suggest about where write it? – blink727_ Feb 22 '23 at 14:03
  • I post the entire code of the class @kleopatra Hope it could help – blink727_ Feb 22 '23 at 14:45
  • 1
    please read the referenced help page and act accordingly - an example has to be stand-alone (which obviously must not contain database access, f.i. ;), runnable as-is (no change/addition/edit needed by the potential helper), minimal (nothing unrelated) and demonstrating the problem you describe. – kleopatra Feb 22 '23 at 14:50
  • unrelated: stick to java naming conventions when showing java code publicly – kleopatra Feb 22 '23 at 14:50
  • @GilbertLeBlanc, why would you remove one row at a time when the goal is to clear the model? This will generated multiple "tablerowsremoved" events which in turn will generate multiple requests to repaint the table. Using `setRowCount(0)` is more efficient. Removing rows from the end is an approach used when you need to only remove "highlighted" rows from the model. – camickr Feb 22 '23 at 15:07
  • @blink727_ *I have only one JTable* - no you don't. Your "search" method continually creates a new instance of JTable. Instead the table should be created and added to the frame when you create all your other components. The "search" method should just reset the data in the model. – camickr Feb 22 '23 at 15:10
  • @camickr Should I create the JTable outside the method and recall it? – blink727_ Feb 22 '23 at 15:12
  • Yes, you define your button and combo box as instance variables of the class. The table should be defined the same way. – camickr Feb 22 '23 at 15:14
  • @camickr it doesn't works :( It shows me the first table but no the next one. Doing a test I notice that if I have the JFrame and the JPanel in the same class, it seems to be ok, no bug. I can post the code if you want. – blink727_ Feb 22 '23 at 15:24
  • You should add the table right away and then change the model. Generally speaking, it's a bad idea to reconstruct your gui on the fly – g00se Feb 22 '23 at 15:34
  • @g00se I tried, it only works when the jtable and the model are created inside the method and if I add the table at the start of the method it's the same. I'm trying everything. – blink727_ Feb 22 '23 at 15:54
  • Strictly speaking, you shouldn't be doing this query in the EDT either. You should be doing it in a separate thread, maybe using `SwingWorker` – g00se Feb 22 '23 at 16:18
  • Basic example: https://stackoverflow.com/a/31764599/131872 – camickr Feb 22 '23 at 16:21

1 Answers1

0

This is an example of how I treated an on-the-fly table model fill with lottery results some years ago. You can easily adapt the TableFiller class to get your results from the database:

import java.awt.EventQueue;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

import java.net.URL;

import java.util.List;
import java.util.Vector;
import java.util.Arrays;

import javax.swing.SwingWorker;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class LotteryResults extends JFrame {
    private static final String RESULTS_FILE = "https://www.national-lottery.co.uk/results/lotto/draw-history/csv";
    private static int NUM_SIGNIFICANT_FIELDS = 10;
    private JTable table;
    private DefaultTableModel tableModel;

    public void setGui() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        tableModel = new DefaultTableModel(new Vector<>(), makeColumnHeaders());
        table = new JTable(tableModel);

        JScrollPane sp = new JScrollPane(table);
        getContentPane().add(sp);
    }

    private Vector<String> makeColumnHeaders() {
        String headers = "Draw Date, Ball 1, Ball 2, Ball 3, Ball 4, Ball 5, Ball 6,  Bonus Ball, Ball Set, Machine";

        return new Vector<>(Arrays.asList(headers.split("\\s*,\\s*")));
    }

    public void start() {
        new TableFiller().execute();
    }

    public static void main(String[] args) {
        try {
            EventQueue.invokeAndWait(() -> {

                LotteryResults reader = new LotteryResults();
                reader.setGui();
                reader.setSize(600, 300);
                reader.setVisible(true);
                reader.start();
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private class TableFiller extends SwingWorker<Vector<Vector<String>>, Vector<String>> {
        @Override
        public Vector<Vector<String>> doInBackground() {
            Vector<Vector<String>> allRows = new Vector<>();
            String line = null;
            int rowCount = 0;
            try (BufferedReader in = new BufferedReader(new InputStreamReader(new URL(RESULTS_FILE).openStream()))) {

                while ((line = in.readLine()) != null) {
                    String[] tokens = line.split("\\s*,\\s*");
                    rowCount++;

                    if (tokens.length >= NUM_SIGNIFICANT_FIELDS) {
                        Vector<String> row = new Vector<>();
                        for (int i = 0; i < NUM_SIGNIFICANT_FIELDS; i++) {
                            row.add(tokens[i]);
                        }
                        // Ignore header
                        if (rowCount > 1) {
                            publish(row);
                        }
                    }
                }
                System.out.printf("%d row(s) found%n", rowCount);

            } catch (IOException e) {
                e.printStackTrace();
            }

            return allRows;
        }

        @Override
        protected void process(List<Vector<String>> x) {
            for (int i = 0; i < x.size(); i++) {
                tableModel.addRow(x.get(i));
            }
        }
    }
}
g00se
  • 3,207
  • 2
  • 5
  • 9
  • if I am in a class that extends JPanel, that is in a general frame, used for every panel I have, how can I recall the frame to add the jscrollpane? I think this is the problem, I change my test with a class extends JFrame and it doesn't give me problem. – blink727_ Feb 23 '23 at 08:00
  • Your problem on that front is that you're mixing presentation up with application functionality. A panel is for presentation. You should separate the filling of its components out really. You can then use that filling functionality in other contexts – g00se Feb 23 '23 at 12:45