-1

I have a JTable inside a JPanel which in turn is in a Jframe. The JTable loads users from a table (database in MySQL).

I have a search engine using DNIs in which key-to-key, with a KeyTyped event, is updating the contacts in the table, and show only those that meet the browser pattern (JTextField). If there are only 2-3-4 clients, the table is not resized to the customer size, but fills the rest of the table with a gray background. (see image). How could the lower bound of the table be reset?

Code:

public class Listado_clientes1 extends javax.swing.JFrame{
    private TableRowSorter<DefaultTableModel> TRSFiltro;
    
    public Listado_clientes1() {
        this.getContentPane().setBackground(Color.orange);
        panel_top.setBackground(Color.orange);
        tabla_clientes.setPreferredScrollableViewportSize(
                new Dimension(tabla_clientes.getPreferredSize().width, tabla_clientes.getRowHeight()*20)
        );

        try {
            DefaultTableModel modelo = new DefaultTableModel();
            tabla_clientes.setModel(modelo);

            PreparedStatement ps = null;
            ResultSet rs = null;
            Connection con = Conexiones.conexion_a_BBDD("agenda");

            String sql = "SELECT dni, nombre, apellidos, telefono, direccion, ciudad, email FROM clientes";
            ps = con.prepareStatement(sql);
            rs = ps.executeQuery();

            ResultSetMetaData rsMd = (ResultSetMetaData) rs.getMetaData();
            int cantidadColumnas = rsMd.getColumnCount();

            modelo.addColumn("DNI");
            modelo.addColumn("NOMBRE");
            modelo.addColumn("APELLIDOS");
            modelo.addColumn("TLFONO");
            modelo.addColumn("DIRECCION");
            modelo.addColumn("CIUDAD");
            modelo.addColumn("EMAIL");
            
            while (rs.next()) {
                Object[] filas = new Object[cantidadColumnas];
                for (int i=0; i<cantidadColumnas; i++) {
                    filas[i] = rs.getObject(i+1);
                }
                modelo.addRow(filas);
            }
        } catch (SQLException ex) {
            System.err.println(ex.toString());
        }
    }

    /**
     * Filtrar: Buscar por DNI.
     */
    public void filtrar_dni() {
        int columna = 0; //Es la fila del DNI.
        TRSFiltro.setRowFilter(RowFilter.regexFilter(textfield_buscar.getText(), columna));
    }
    
    
    private void textfield_buscarKeyTyped(java.awt.event.KeyEvent evt) {                                          
        Character letra = evt.getKeyChar();
        evt.setKeyChar(Character.toUpperCase(letra));

        textfield_buscar.addKeyListener(new KeyAdapter(){
        public void keyReleased(final KeyEvent e){
            String texto = (textfield_buscar.getText());
            textfield_buscar.setText(texto);
            filtrar_dni();
        }
        });
        
        TRSFiltro = new TableRowSorter<DefaultTableModel>((DefaultTableModel) tabla_clientes.getModel());
        tabla_clientes.setRowSorter(TRSFiltro);
    }
}

Outline / Scheme:

enter image description here enter image description here

SrCantabri
  • 37
  • 5
  • You can change background of jpanel same as your frame background. By:===> jScrollPane1.getViewport().setBackground(Color.white); – Vatsal Dholakiya May 12 '21 at 16:01
  • @VatsalDholakiya I added your recommendation to my code but you still see the edges of the original JTable. – SrCantabri May 12 '21 at 16:14
  • Post a proper [mre] demonstrating your problem. Your application is irrelevant to the question. All you need is a JFrame with a JTable. You can set a model on the JTable using `table.setModel( new DefaultTableMoel(rows, columns) )`. Then you add a JTextField to the frame with an ActionListener. In the text field you enter a number between 1 - 15. Then when you press Enter you recreate the TableModel using the number entered and invoke the suggested logic.. This will simulate your requirement of filtering a table. Once you get this working then you fix your real application. – camickr May 13 '21 at 14:40
  • To filter a table when text is changed in a JTextField you should NOT be using a KeyListener. Instead use a `DocumentListener`. Read the section from the Swing tutorial on [Sorting and Filtering](https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#sorting) for a complete working example. – camickr May 14 '21 at 01:36
  • (1-) @SrCantabri *I haven't been able to fix the problem yet* - Does my example work??? It does for me so that indicates the problem is with your code. The issue is with your frame construction and the layout managers you are using. Did you play with my code and add another panel with buttons at the bottom? The point of the MRE is to start simple with code that works then you make a change and retest. When it stops working you have identified the issue and you have your [mre] to post. Without the MRE there is nothing we can do to help. – camickr May 14 '21 at 18:31
  • @camickr I tried your code but in my programa its doesnt work. Compile correctly but not resize the table – SrCantabri May 18 '21 at 09:36
  • *I retyped my current code in question. Where is the problem?* - Where is your [mre]??? How can I copy/paste/compile/test that code??? The issue is with the structure of your code and the layout managers you use. We can't begin to guess what you are doing. You have been given working code!!! It is your job to demonstrate the difference between the working code and what your are doing. In any case you have been give a working example and still have not yet "accepted" the answer. – camickr May 18 '21 at 14:11
  • @camickr I've only found Javascript/HTML/CSS snippet by creating the problem/question. My code is in Java. – SrCantabri May 18 '21 at 14:24
  • I asked you a simple question. Did you copy/paste/compile and test the complete example code I provided? Did it work? There is no trick to pasting code in the forum. You have already pasted code. This issue is that you have NOT pasted an MRE. I am NOT interested in your application. I gave you working code. It is your job to modify that code to reflect your application code. You are probably using different layout managers. So you restructure my code to use your layout managers to see if it still works. It is your job to isolate the problem because I've proven that the code works as posted. – camickr May 18 '21 at 14:35
  • The data is loaded from a table in the database, so you won't be able to test the MRE. Still, I just updated the question code as small as possible. Now? – SrCantabri May 18 '21 at 15:32

1 Answers1

1

Any time the number of rows in the view of the table changes you need to recalculate the preferred scrollable viewport size of the table. Once this size is recalculated you need to invoke the layout manager of the panel containing the table:

A reusable method would be something like:

public void resetTablePreferredScrollableViewportSize(JTable table, int maxRows)
{
    Dimension size = table.getPreferredSize();
    int displayRows = Math.min(table.getRowCount(), maxRows);
    size.height = displayRows * table.getRowHeight();

    table.setPreferredScrollableViewportSize( size );

    Container parent = SwingUtilities.getAncestorOfClass(JPanel.class, table);
    parent.revalidate();
    parent.repaint();
}

So after setting the row filter you could use:

tabla_clientes.setRowSorter(TRSFiltro);
resetTablePreferredScrollableViewportSize(tabla_clientes, 10);

Now the scroll pane should be sized to display up to 10 rows after which the scrollbar of the scroll pane will appear.

Edit:

I don't know how to put a reproducible example

Then you don't understand what your problem is.

Your question is that you want to:

Reset JTable (size) depending on number of rows

So the data is irrelevant, only the number of rows is relevant.

It is easy to test this because you can create a DefaultTableModel with a specified number of rows.

Below is a simple MRE. To test you:

  1. enter a number in the text field
  2. press enter

The table will be resized to display the specified number of rows. If the number is greater that 10 the table size will be fixed and a scrollbar will appear:

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

public class SSCCE extends JPanel
{
    JTextField textField;
    JTable table;

    public SSCCE()
    {
        setBackground(Color.YELLOW);

        textField = new JTextField(5);
        add(textField);

        table = new JTable(new DefaultTableModel(0, 4));
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        add( new JScrollPane(table) );

        textField.addActionListener((e) ->
        {
            int rows = Integer.parseInt( textField.getText() );

            table.setModel( new DefaultTableModel(rows, 4) );
            resetTablePreferredScrollableViewportSize(table, 10);
        });
    }

    public void resetTablePreferredScrollableViewportSize(JTable table, int maxRows)
    {
        Dimension size = table.getPreferredSize();
        int displayRows = Math.min(table.getRowCount(), maxRows);
        size.height = displayRows * table.getRowHeight();

        table.setPreferredScrollableViewportSize( size );

        Container parent = SwingUtilities.getAncestorOfClass(JPanel.class, table);
        parent.revalidate();
        parent.repaint();
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE());
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//      frame.pack();
        frame.setSize(500, 250);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args) throws Exception
    {
        java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288
  • I reededed my code with your help, but I still have the same problem. See the question. I don't know how to put a reproducible example in Java but I did edit the question as best I could finally. – SrCantabri May 14 '21 at 01:02
  • @SrCantabri, see edit for an [mre]. You can copy/paste/compile and test so see that the proposed solution works. If it doesn't work in your application then you have some other issue that we are not aware of because you haven't posted your own MRE. – camickr May 14 '21 at 01:29
  • Thanks for the help but I haven't been able to fix the problem yet... Dont understand my mistake. Why does it fill the contents with gray and not reduce the height of the jtable? – SrCantabri May 14 '21 at 16:23
  • I retyped my current code in question. Where is the problem? – SrCantabri May 18 '21 at 10:02