JScrollPane 不会截断 JLabel 文本

JScrollPane doesn't truncate JLabel text

所以我试图创建一个包含信息的 table,并且 table 中的行超过了 JFrame 的高度,因此我尝试使用 JScrollPane 作为解决方案.

当我将 JPanel 添加到框架时,如果它超出框架的边界,它会截断 JLabels 文本,如下图所示:

代码:

    public class TestApplication extends JPanel{
JPanel headers = new JPanel(new GridLayout(1, 5));

JPanel informationTable = new JPanel();
JPanel[] rows = new JPanel[30];

public TestApplication(){

    headers.add(new JLabel("Name"));
    headers.add(new JLabel("City"));
    headers.add(new JLabel("Adress"));
    headers.add(new JLabel("Phone"));
    headers.add(new JLabel("Mail"));

    informationTable.setLayout(new BoxLayout(informationTable, BoxLayout.Y_AXIS));

    //Populating the table with 20 rows
    for(int i = 0; i < 30; i++){
        rows[i] = new JPanel();

        rows[i].setLayout(new GridLayout(1, 6));

        rows[i].add(new JLabel("Undefined name"));
        rows[i].add(new JLabel("Undefined city"));
        rows[i].add(new JLabel("1529th Avenue street name"));
        rows[i].add(new JLabel("Undefined Phone"));
        rows[i].add(new JLabel("Undefined Mail"));

        informationTable.add(rows[i]);
    }
    super.setLayout(new BorderLayout());
    super.add(headers, BorderLayout.NORTH);
    super.add(informationTable, BorderLayout.CENTER);
}

但是,当我将带有行的 JPanel 放在 JScrollPane 中时,它不会截断 JLabel 文本,该文本随后超出了 JFrame,并且未对齐所有列,如下图所示: 代码:

    public class TestApplication extends JPanel{
JPanel headers = new JPanel(new GridLayout(1, 5));

JPanel informationTable = new JPanel();
JPanel[] rows = new JPanel[30];
JScrollPane scrollTable = new JScrollPane(informationTable);

public TestApplication(){

    headers.add(new JLabel("Name"));
    headers.add(new JLabel("City"));
    headers.add(new JLabel("Adress"));
    headers.add(new JLabel("Phone"));
    headers.add(new JLabel("Mail"));

    informationTable.setLayout(new BoxLayout(informationTable, BoxLayout.Y_AXIS));

    //Populating the table with 20 rows
    for(int i = 0; i < 30; i++){
        rows[i] = new JPanel();

        rows[i].setLayout(new GridLayout(1, 6));

        rows[i].add(new JLabel("Undefined name"));
        rows[i].add(new JLabel("Undefined city"));
        rows[i].add(new JLabel("1529th Avenue street name"));
        rows[i].add(new JLabel("Undefined Phone"));
        rows[i].add(new JLabel("Undefined Mail"));

        informationTable.add(rows[i]);
    }
    scrollTable.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

    super.setLayout(new BorderLayout());
    super.add(headers, BorderLayout.NORTH);
    super.add(scrollTable, BorderLayout.CENTER);
}

两个例子的主要方法是一样的。我认为这与问题无关,但可以在下面的代码中看到:

    public static void main(String[] args) {
    JFrame main = new JFrame("JScrollPane exceeds bounds");

    TestApplication app = new TestApplication();

    main.add(app);

    main.setSize(600, 513);
    main.setLocationRelativeTo(null);
    main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    main.setVisible(true);
}

我认为唯一的解决方案是覆盖您使用的 GridLayout。听起来不太好,但实际上很容易做到:

package scrollPaneAndBoxLayout;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;

public class MyGridLayout extends GridLayout {

    public MyGridLayout(int rows, int cols) {
        super(rows, cols);
    }

    public Dimension preferredLayoutSize(Container parent) {
        return new Dimension(parent.getWidth(), (int) super.preferredLayoutSize(parent).getHeight());
    }

}

解释一下,preferredLayoutSize() returns 应用布局的整个组件的大小(如果可能)(大多数情况下都是如此)。我将其宽度设置为父组件的宽度,因此您放置 table 的容器,而高度取自原始 GridLayout class.

另一种解决方案是使用 JTable 而不是 JPanel 构造,但是当您已经以这种方式实现它时,我怀疑修改整个概念是否会更容易。

When I add the JPanel to the Frame it truncates the JLabels text, if it exceeds the bounds of the frame

正确,因为布局管理器强制组件的大小设置为 space 可用。

However when I place the JPanel with the rows inside the JScrollPane it doesn't truncate the JLabel text, which then exceeds the JFrame

正确,因为使用 JScrollPane 的要点是允许每个组件以其首选大小显示。如果组件大小不合适,则会导致滚动。

如果您想控制面板的宽度以适合滚动窗格的宽度,那么您需要在面板上实现 Scrollable 接口并将 getScrollableTracksViewportWidth() 方法重写为 return Boolean.TRUE。阅读 API 了解有关 Scrollable 接口的更多信息。

一种简单的方法是使用 Scrollable Panel,它具有允许您控制可滚动属性的方法。