在 top-left 角对齐 ScrollPane 时遇到困难

Difficulties in aligning ScrollPane in top-left corner

问题是,如何在 resizeble JPane 中对齐 JScrollPane,使其对齐 top-left 角而不是中心?

这似乎是一项显而易见的任务,但我花了几个小时尝试所有不同的布局和属性。

沮丧可以表达,因为我只有两个选择:

  1. 使用尊重儿童最大偏好尺寸的布局,例如FlowLayout。副作用 - ScrollPane 开始表现得像普通的 Panel:

  1. 使用可伸缩布局,例如 BorderLayout 并将元素放入 BorderLayout.CENTERBorderLayout.PAGE_START 导致 1.)。我对面板的位置失去了控制,它在中心:

当 window 较小时,滚动会按预期工作:


是否有可能同时拥有两个世界:JScrollPane 不会超出最大首选大小,但不会丢失 Scroll

如果有人需要源代码:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;

public class MainPanelTest extends JFrame {


    public static void main(String[] args)  {
        new MainPanelTest().setVisible(true);
    }

    public MainPanelTest()  {
        super();
        this.setLayout(new BorderLayout());

        setupGUI();
    }

    private void setupGUI() {
        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
        this.add(tabbedPane, BorderLayout.CENTER);

        JComponent filesPanel = setupFilesPanel();
        tabbedPane.addTab("Files", filesPanel);

        JPanel secondPanel = new JPanel();
        tabbedPane.addTab("Placeholder", secondPanel);

    }

    private JComponent setupFilesPanel() {
        JPanel filesPanel = new JPanel();
        filesPanel.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.NORTHWEST;
        for(int i=0; i<15; i++) {
            c.gridy = i;
            filesPanel.add(new JLabel("Test row " + i), c);
        }       

        JScrollPane scrollFilesPane = new JScrollPane(filesPanel);
        scrollFilesPane.setMaximumSize(scrollFilesPane.getPreferredSize());
        return scrollFilesPane;
    }

}

看看这是否是您要实现的目标:

private JComponent setupFilesPanel() {
    JPanel filesPanel = new JPanel();
    filesPanel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.anchor = GridBagConstraints.NORTHWEST;
    for(int i=0; i<15; i++) {
        c.gridy = i;
        filesPanel.add(new JLabel("Test row " + i), c);
    }       

    // ---- Add this
    JPanel newPanel = new JPanel(new GridBagLayout());
    c.weightx = 1;
    c.weighty = 1;
    newPanel.setBackground(Color.yellow);
    newPanel.add(filesPanel, c);
    // ----

    // ---- change the panel you pass to JScrollPanel constructor:
    JScrollPane scrollFilesPane = new JScrollPane(newPanel); // <--------- newPanel
    scrollFilesPane.setMaximumSize(scrollFilesPane.getPreferredSize());
    return scrollFilesPane;
}

更改已发表评论。

GridBagLayout 将 space 划分为组件所在的逻辑单元。 anchor 仅在逻辑单元格大于其组件时才相关。如果同一 row/column 中的组件需要更大的尺寸,或者如果有额外的 space 并且关联的 weightxweighty 值不为零,则可能会发生这种情况。由于您想要的行为是关于额外的 space,因此您必须相应地设置权重值。唯一列的 weightx 将是非零的,但最后一行的 weighty 将是非零的,只会占据它下面的整个 space:

GridBagLayout gridBagLayout = new GridBagLayout();
JPanel filesPanel = new JPanel(gridBagLayout);
GridBagConstraints c = new GridBagConstraints();
c.gridx = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.NORTHWEST;

c.weightx = 1; // for the column
for(int i=0; i<15; i++)
    filesPanel.add(new JLabel("Test row " + i), c);

// now change the last row:
c.weighty = 1;
gridBagLayout.setConstraints(
  filesPanel.getComponent(filesPanel.getComponentCount()-1), c);

或者,您可以不修改单元格,但通过添加额外的空白行和列来操纵整个布局,消耗额外的 space,这将有效地将原始行和列移动到左上角:

// add all visible components which should not grow
GridBagLayout gridBagLayout = new GridBagLayout();
JPanel filesPanel = new JPanel(gridBagLayout);
GridBagConstraints c = new GridBagConstraints();
c.gridx = GridBagConstraints.REMAINDER;
for(int i=0; i<15; i++)
    filesPanel.add(new JLabel("Test row " + i), c);

// add an extra row consuming vertical extra space
int nRows=filesPanel.getComponentCount();
gridBagLayout.rowHeights=new int[nRows+1];
gridBagLayout.rowWeights=new double[nRows+1];
gridBagLayout.rowWeights[nRows]=1;
// add an extra column consuming extra horizontal space
gridBagLayout.columnWidths=new int[] { 0, 0 };
gridBagLayout.columnWeights=new double[] { 0, 1 };