【问题标题】:Difficulties in aligning ScrollPane in top-left corner在左上角对齐 ScrollPane 的困难
【发布时间】:2015-01-13 15:27:34
【问题描述】:

问题是,我如何在可调整大小的JPane 中对齐JScrollPane,使其对齐到左上角而不是中心?

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

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

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

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

当窗口很小时,滚动会按预期工作:


是否有可能同时拥有两个世界:JScrollPane 不会拉伸到超过最大首选大小,但不会丢失 滚动

如果有人需要源代码:

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;
    }

}

【问题讨论】:

  • In case someone needs the source code: - 我们无法执行该代码。发布一个正确的SSCCE 来证明问题。
  • 问题不是你的JScrollPane,而是GridBagLayout,如果它不能调整大小,它的内容会居中。如果您想了解发生了什么,请给每个组件一个可见的边框。
  • @camickr 谢谢。我修改了代码,以便可以在不进行更改的情况下运行。
  • @Holger 看起来像是向前迈出了一步。我将 GridBagLayout 面板包裹在 FlowLayout 面板内,现在它似乎给了我更多的控制权。我是否理解正确,解决方案将是:Frame -> TabbedPane -> ScrollPane -> JPane (Flow or other layout) -> JPane (GridBagLayout)?
  • 您可以使用嵌套面板来解决它。或者,您可以在GridBagLayout 中启用单元格调整大小(这并不自动意味着调整Components 的大小)。例如。在循环之前设置c.weightx=1; 并为 last 组件设置c.weighty=1; 应该可以解决问题。这可以调整单元格的大小,但不能调整包含的组件(因为fill 仍然是NONE),这就是anchor 发挥作用的情况......

标签: java swing layout


【解决方案1】:

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

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);

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

// 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 };

【讨论】:

    【解决方案2】:

    看看这是否是你想要达到的目标:

    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;
    }
    

    对更改进行了注释。

    【讨论】:

    • 谢谢。两个答案都有效,但我只能接受一个。
    猜你喜欢
    • 2021-11-12
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 2017-10-11
    相关资源
    最近更新 更多