3

在 Java Swing 中,有人可以告诉我在将我的 JTable 放入 JScrollPane 之后使用 setPreferredScrollableViewportSize() 与在 JTable 实例上调用 setFillsViewportHeight(true) 之间的区别吗?我想知道哪个是好的做法。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();
            }
        });
    }
}
4

2 回答 2

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

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

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

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

在此处输入图像描述

  • JTable.setFillsViewportHeight(true) 和正确的 JFrame.pack() 之间没有区别

  • setPreferredScrollableViewportSize 是关于良好实践的,

  • table.setPreferredScrollableViewportSize(table.getPreferredSize());错误使用并且可以将 JTables 的 JViewport 扩大到极端尺寸,可以根据假定的行数计算适当的 Dimension,注意并非所有行都可以具有相同的高度

在此处输入图像描述

  • 对 JScrollPane 使用可调整大小的 LayoutManager 而不是 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();
            }
        });
    }
}
于 2013-08-16T14:37:43.917 回答
1

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

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

于 2013-08-16T13:59:42.460 回答