JTP中的setPreferredScrollableViewportSize()vs setFillsViewportHeight()

时间:2013-08-16 13:52:35

标签: java swing jtable

在Java Swing中,有人能告诉我在JTable实例中将JTable放入JScrollPane并调用setFillsViewportHeight(true)后使用setPreferredScrollableViewportSize()之间的区别吗?我想知道哪一个是好习惯。 Herbert Schildt建议使用setPreferredScrollableViewportSize(),而Horstmann和Cornell建议使用setFillsViewportHeight()。 以下是我所愚弄的简短样本。

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", "Wendy@HerbSchildt.com", 
                "Hello Herb", new Integer(287) }, 
                { "Alex", "Alex@HerbSchildt.com", 
                    "Check this out!", new Integer(308) }, 
                    { "Hale", "Hale@HerbSchildt.com", 
                        "Found a bug", new Integer(887) }, 
                        { "Todd", "Todd@HerbSchildt.com", 
                            "Did you see this?", new Integer(223) }, 
                            { "Steve", "Steve@HerbSchildt.com", 
                                "I'm back", new Integer(357) }, 
                                { "Ken", "Ken@HerbSchildt.com", 
                                    "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();
            }
        });
    }
}

2 个答案:

答案 0 :(得分:4)

  • 这只是关于如何避免使用setPreferredSize,setSize,setBounds的理论,我很熟悉

  • JTable无法从API中实现的方法返回合理的PreferredSize,例如JTextArea(10,20); JList #setPrototypeDisplayValue和可见Ites的数量

  • 只有setPreferredScrollableViewportSize,setPreferredSize和setSize(ev setBounds)可以为LayoutManager返回关于Dimension原型的通知,否则从API使用默认的PreferredSize for JScrollPane

  • setPreferredScrollableViewportSize,setPreferredSize和setSize with pack()或witout for JFrame.setSize / setBounds

enter image description here

  • JTable.setFillsViewportHeight(true)和正确的JFrame.pack()

  • 之间没有区别
  • setPreferredScrollableViewportSize是关于良好的实践,

  • table.setPreferredScrollableViewportSize(table.getPreferredSize());是错误的用法,并且可以将JViewport for JTables放大到极限尺寸,正确的尺寸可以从假定的行数计算,注意并非所有行都可以具有相同的高度

enter image description here

  • 使用可调整大小的LayoutManager for JScrollPane而不是FlowLayout

  • 不要使用Jframe.setSize,覆盖PreferredScrollableViewportSize的正确Dimension(这里有几次讨论)

来自代码

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", "Wendy@HerbSchildt.com", "Hello Herb", new Integer(287)},
        {"Alex", "Alex@HerbSchildt.com", "Check this out!", new Integer(308)},
        {"Hale", "Hale@HerbSchildt.com", "Found a bug", new Integer(887)},
        {"Todd", "Todd@HerbSchildt.com", "Did you see this?", new Integer(223)},
        {"Steve", "Steve@HerbSchildt.com", "I'm back", new Integer(357)},
        {"Ken", "Ken@HerbSchildt.com", "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();
            }
        });
    }
}

答案 1 :(得分:1)

这取决于你想做什么。 您可以同时使用它们,但JScrollPane不会(至少在通常情况下)创建大于表格首选大小的视口。

这可能取决于LayoutManagers以及滚动窗格旁边可能的其他组件。