【问题标题】:Why doesn't frame.pack() work with a JTable?为什么 frame.pack() 不能与 JTable 一起使用?
【发布时间】:2022-02-03 21:48:20
【问题描述】:

我有一个超级基本的JTable,我将它添加到JFrame,但由于某种原因frame.pack() 不起作用。我将行高设置为列宽,以便表格的单元格是正方形,但是在调整窗口大小时这似乎不起作用。那么如何才能使表格的单元格始终为正方形,即使在调整大小时也是如此,并且框架已正确包装?这是窗口的代码:

package me.an.ar.window;

import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;

public class DayPlanner
{
    private JFrame frame;

    private void createAndShowGUI()
    {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container container = frame.getContentPane();

        Object[][] data = new Object[5][7];
        String[] columnNames = { "Day1", "Day2", "Day3", "Day4", "Day5", "Day6", "Day7" };
        JTable table = new JTable(data, columnNames);

        for (int col = 0; col < table.getColumnCount(); col++)
        {
            for (int row = 0; row < table.getRowCount(); row++)
            {
                int colWidth = table.getColumnModel().getColumn(col).getWidth();
                table.setRowHeight(row, colWidth);
            }
        }

        container.add(new JScrollPane(table));

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void show()
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    public DayPlanner()
    {
        show();
    }

    public static void main(String[] args)
    {
        new DayPlanner();
    }
}

【问题讨论】:

  • 1) 将滚动窗格添加到 BorderLayout 的 CENTER。 2)您需要定义JTable 的resize 行为。查看setAutoResizeMode(...) 方法。 那么我怎样才能使表格的单元格始终为正方形, - 只有宽度会调整大小。没有自动调整高度大小。
  • 我不认为JTable 是正确的组件。也许相反,请查看有关layout of a chess board 的这个问题。它包括我自己和@camickr 的答案,并讨论了(更多 camickr)当可用空间不能容纳相同大小的单元格时布局的缺陷。

标签: java swing jframe jtable


【解决方案1】:

您没有设置任何 LayoutManager。默认不是 FlowLayout 但至少不是 null:

默认内容窗格将设置一个 BorderLayout 管理器。 (Java 17 API)

这意味着通过调整窗口大小,您将不得不与滚动窗格的大小调整作斗争。如果你使用会发生什么

container.add(new JScrollPane(table), BorderLayout.CENTER);

这应该让滚动窗格随着框架而增长和缩小,并且表格内的行/列的数量可能会有所不同。这也可能会受到JTable.setAutoResizeMode() 的影响。

【讨论】:

  • 是的,但是容器默认没有FlowLayout吗?我以为没关系。
  • 好的,我尝试使用 BorderLayout,但它的工作原理完全相同。使用 FlowLayout 时,表格根本不会调整大小,而使用 BorderLayout 时,它的工作方式与以前完全相同。
【解决方案2】:

选项 1

您还没有真正提到您将如何使用此表(将保存哪些数据以及用户应该如何交互);但是,这听起来像是GridLayout(关于数据单元)和GridBagLayout(关于标题单元)的用例。示例如下:

public class DayPlanner {
    private JFrame frame;
    Dimension cellSize = new Dimension(75, 75);

    private void createAndShowGUI() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Create header cells
        JPanel p1 = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        String[] columnNames = { "Day 1", "Day 2", "Day 3", "Day 4", "Day 5", "Day 6", "Day 7" };
        int count = 0;
        for (int i = 0; i < columnNames.length; i++) {
            JLabel l = new JLabel(columnNames[i], SwingConstants.CENTER);
            l.setFont(new Font("Times New Roman", Font.BOLD, 14));
            l.setBackground(new Color(238, 238, 238));
            l.setOpaque(true);
            l.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, new Color(122, 138, 153)));
            c.fill = GridBagConstraints.HORIZONTAL;
            c.ipady = 5; // adjusts cell's height
            c.weightx = 0.5;
            c.gridx = count++;
            c.gridy = 0;
            p1.add(l, c);
        }

        // Create data cells
        JPanel p2 = new JPanel();
        p2.setLayout(new GridLayout(5, 7));
        for (int i = 0; i < 35; i++) {
            JLabel l = new JLabel("<html> This is some sample text " + i + "</html>"); // html tags allow text-wrapping
            l.setFont(new Font("Times New Roman", Font.PLAIN, 14));
            l.setVerticalAlignment(SwingConstants.TOP);
            l.setHorizontalAlignment(SwingConstants.LEFT);
            l.setPreferredSize(cellSize);
            l.setBackground(Color.WHITE);
            l.setOpaque(true);
            l.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 1, new Color(122, 138, 153)));
            p2.add(l);
        }


        JScrollPane sp = new JScrollPane(p2);
        sp.getVerticalScrollBar().setUnitIncrement((int) cellSize.getHeight() / 2); // adjusts scrolling speed
        sp.getViewport().setBackground(Color.WHITE);
        Container container = frame.getContentPane();
        container.add(p1, BorderLayout.NORTH);
        container.add(sp, BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new DayPlanner().createAndShowGUI();
            }
        });
    }
}

选项 2

如果您仍想使用问题中给出的JTable,您可以将ComponentListener 添加到您的JFrame,以便您可以收听“调整大小事件”,从而允许您重新调整单元格的大小并保持它们的方形。

frame.addComponentListener(new ComponentAdapter() {
    public void componentResized(ComponentEvent evt) {
        for (int row = 0; row < table.getRowCount(); row++) {
            int colWidth = table.getColumnModel().getColumn(0).getWidth();
            table.setRowHeight(row, colWidth);
        }
    }
});

对于pack()的问题,你可以根据你表中的列和行设置JFrame的初始大小(记得注释掉frame.pack();)。下面,虽然它会删除框架底部的空白区域,但是它不会阻止用户调整窗口大小并将其恢复。

int colWidth = table.getColumnModel().getColumn(0).getWidth();
frame.setSize(7 * colWidth, 5 * table.getRowHeight(0) + 25);
//frame.pack();

【讨论】:

    猜你喜欢
    • 2013-08-16
    • 2018-03-09
    • 2021-06-14
    • 2012-10-09
    • 2020-03-18
    • 2017-11-21
    • 2019-04-11
    • 2012-09-19
    • 2013-12-30
    相关资源
    最近更新 更多