Mahmoud
Mahmoud

Reputation: 251

setPreferredScrollableViewportSize() vs setFillsViewportHeight() in JTable

In Java Swing, could someone tell me the difference between using setPreferredScrollableViewportSize() after putting my JTable in JScrollPane vs. calling setFillsViewportHeight(true) on the JTable instance? I want to know which one is the good practice. Herbert Schildt suggests using setPreferredScrollableViewportSize() while Horstmann and Cornell suggest setFillsViewportHeight(). Here is a short sample of what I am fooling around with.

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class TableDemo {
    JTable jtabEmail;
    String[] headings = {"From", "Address", "Subject", "Size"};
    Object[][] data = {
            { "Wendy", "[email protected]", 
                "Hello Herb", new Integer(287) }, 
                { "Alex", "[email protected]", 
                    "Check this out!", new Integer(308) }, 
                    { "Hale", "[email protected]", 
                        "Found a bug", new Integer(887) }, 
                        { "Todd", "[email protected]", 
                            "Did you see this?", new Integer(223) }, 
                            { "Steve", "[email protected]", 
                                "I'm back", new Integer(357) }, 
                                { "Ken", "[email protected]", 
                                    "Arrival time change", new Integer(512) }   
    };
    JLabel jl;
    public TableDemo() {
        JFrame jfrm = new JFrame("Table Demo");
        jfrm.setSize(500, 160);
        jfrm.getContentPane().setLayout(new FlowLayout());
        jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jl = new JLabel("");

        jtabEmail = new JTable(data, headings);
        jtabEmail.setFillsViewportHeight(true);
        JScrollPane jsp = new JScrollPane(jtabEmail);
        //jtabEmail.setPreferredScrollableViewportSize(new Dimension(450, 80));

        jtabEmail.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                StringBuilder sb = new StringBuilder("Selected Rows: ");
                int[] rowsArray = jtabEmail.getSelectedRows();
                for (int i = 0; i < rowsArray.length; i++) {
                    sb.append((rowsArray[i]+1) + " ");
                }
                jl.setText(sb.toString());
            }
        });

        jfrm.getContentPane().add(jsp);
        jfrm.getContentPane().add(jl);

        //jfrm.pack();
        jfrm.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TableDemo();
            }
        });
    }
}

Upvotes: 3

Views: 9381

Answers (2)

mKorbel
mKorbel

Reputation: 109823

  • this is only theory about how to avoiding setPreferredSize, setSize, setBounds, I'm quite familair with

  • JTable can't returns reasonable PreferredSize from methods implemented in API, e.g JTextArea(10, 20); JList#setPrototypeDisplayValue and number of visible Ites

  • only setPreferredScrollableViewportSize, setPreferredSize and setSize (ev setBounds) can returns notifier for LayoutManager about prototype for Dimension, otherwise is used default PreferredSize for JScrollPane from API

  • setPreferredScrollableViewportSize, setPreferredSize and setSize with pack() or witout for JFrame.setSize/setBounds

enter image description here

  • there isn't difference betweens JTable.setFillsViewportHeight(true) and with proper JFrame.pack()

  • setPreferredScrollableViewportSize is about good practicies,

  • table.setPreferredScrollableViewportSize(table.getPreferredSize()); is wrong usage of and can to enlarge JViewport for JTables to extreme sizes, proper Dimension could be calculated from assummed number of rows, note not all rows can have got the same height

enter image description here

  • use resizable LayoutManager for JScrollPane not FlowLayout

  • don't to use Jframe.setSize, override proper Dimension for PreferredScrollableViewportSize (a few times discused here)

from code

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class TableDemo {

    private JFrame jfrm = new JFrame("Table Demo");
    private String[] headings = {"From", "Address", "Subject", "Size"};
    private Object[][] data = {
        {"Wendy", "[email protected]", "Hello Herb", new Integer(287)},
        {"Alex", "[email protected]", "Check this out!", new Integer(308)},
        {"Hale", "[email protected]", "Found a bug", new Integer(887)},
        {"Todd", "[email protected]", "Did you see this?", new Integer(223)},
        {"Steve", "[email protected]", "I'm back", new Integer(357)},
        {"Ken", "[email protected]", "Arrival time change", new Integer(512)}
    };
    private JTable table = new JTable(data, headings);
    private JScrollPane jsp = new JScrollPane(table);
    private JLabel jl;

    public TableDemo() {
        jl = new JLabel("whatever but not empty JLabel");
        jsp.getViewport().setBackground(Color.ORANGE);
        table.setOpaque(false); //
        table.setFillsViewportHeight(true);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jfrm.add(jsp);
        jfrm.add(jl, BorderLayout.NORTH);
        jfrm.pack();
        jfrm.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TableDemo();
            }
        });
    }
}

Upvotes: 4

Kayaman
Kayaman

Reputation: 73568

It depends what you want to do. You can use them both, but JScrollPane will not (at least in usual situations) create a viewport larger than the preferred size of the table.

This may depend on LayoutManagers and possible other components next to the scrollpane.

Upvotes: 1

Related Questions