使用GridBagLayout在JScrollPane中设置JList的宽度

时间:2015-05-31 23:48:36

标签: java swing layout-manager gridbaglayout

我在下面的示例Java Swing代码生成以下屏幕截图(屏幕截图已经过编辑以使其更小):

JList in JScrollPane not the expected width 这是代码:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;


public class Main extends JFrame {

    public Main() {
        JListTest theGui = new JListTest();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        add(theGui);
        pack();
        setVisible(true);
    }

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

    private class JListTest extends JPanel {
        private static final int PADDING = 3;
        private JLabel label;
        private JTextArea textarea;
        private String listOptions[] = 
            {"here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
             "here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text",
             "here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
             "here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text",
             "here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
             "here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text",
             "here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
             "here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text",
             "here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
             "here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text"};
        private JList<String> list;
        private JScrollPane scrollpane;
        private GridBagConstraints gbc;

        public JListTest() {
            super(new GridBagLayout());
            label = new JLabel("Here is a label:");
            textarea = new JTextArea(20, 50);
            list = new JList<String>(listOptions);
            scrollpane = new JScrollPane(list);

            gbc = new GridBagConstraints();
            gbc.gridheight = 1;
            gbc.insets = new Insets(PADDING, PADDING, PADDING, PADDING);
            gbc.anchor = GridBagConstraints.LINE_START;

            gbc.gridwidth = 4;
            gbc.gridx = 0;
            gbc.gridy = 0;
            add(label, gbc);

            // I want the scrollpane to take up 1/4 the width of the window.
            gbc.gridwidth = 1;
            gbc.gridx = 0;
            gbc.gridy = 1;
            add(scrollpane, gbc);

            // I want the textarea to take up 3/4 the width of the window.
            gbc.gridwidth = 3;
            gbc.gridx = 1;
            gbc.gridy = 1;
            add(textarea, gbc);
        }
    }
}

如您所见,我有一个JList,其中包含左侧JScrollPane内部文本非常长的项目,右侧是JTextArea。我希望JScrollPane / JList占据窗口宽度的1/4,并且当JList项目的文本太长时会出现水平滚动条。我希望JTextArea占据窗口宽度的3/4。

我尝试使用GridBagLayout执行此操作,但显然我没有正确执行,因为外观已关闭。

感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:1)

定义JScrollPane的首选大小,以保持最初宽度的1/4。然后为JTextArea添加weighX = 1,为pack()添加= 3.

$('span.trigger').on('click', function() { var trigger_el = $(this); trigger_el.parent().siblings('.section').children('.example').hide(); trigger_el.siblings('.example').fadeToggle(); });之后,您的初始状态将反映首选大小。如果宽度增加,则根据权重分配附加像素。

答案 1 :(得分:1)

GridBagLayout想要使用组件的首选大小,这是您认为可以做的以及您实际可以做什么冲突的奇怪点之一。

基本上,您想要做的是覆盖GridBagLayout使用您自己的逻辑做出的布局决策(您占据宽度的25%,然后占据宽度的75%)。问题是,GridBagLayout没有想到这一点,它更多地考虑,你可以有25%的空间在我计算好每个人之后遗留下来首选布局要求,你可以有75%。这并不总是像你最初想象的那样出现。

第一步是使用weightxweighty

// I want the scrollpane to take up 1/4 the width of the window.
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 0.25;
gbc.weighty = 1;
add(scrollpane, gbc);

// I want the textarea to take up 3/4 the width of the window.
gbc.gridx = 1;
gbc.gridy = 1;
gbc.weightx = 0.75;
add(textarea, gbc);

这为GridBagLayout提供了尺寸提示,说明它在完成初始布局后可能对剩余空间做了什么。

但是,等等,这似乎无法改变任何事情!不,实际上它并没有,除非你按照我说的那样足够大小调整窗口,所以组件的布局(尽可能最好)到他们喜欢的尺寸。所以JListJTextArea正在与我们争吵。

JScrollPane从视图组件中获取它的首选大小。 JList实现Scrollable接口,该接口提供getPreferredScrollableViewportSize方法,JScrollPane使用该方法作为首选大小(否则使用组件首选大小)

所以,我们现在可以稍微厚脸皮并修改首选的视口宽度......

list = new JList<String>(listOptions) {
    @Override
    public Dimension getPreferredScrollableViewportSize() {
        Dimension size = super.getPreferredScrollableViewportSize();
        size.width = 100;
        return size;
    }
};

(ps,我测试了setFixedCellWidthsetPrototypeCellValue,但这两个都阻止了水平滚动条的显示。)

好的,这效果好一点:P。有一段时间,最小尺寸将与首选尺寸竞争,因此请注意:P

请记住,weightx/y仅适用于剩余空间,不会影响初始布局:P