提问者:小点点

设置GridBagLayout网格的大小


我正在尝试使用Java Swing (GridBagLayout)创建一个控制台。

我不知道为什么,但正如您在左边距看到的那样,网格没有正确的大小。

其中浅蓝色是列表,绿色是图像,橙色是文本面板,黄色是文本字段。

我不知道如何使列表更大,图像更小。同样,文本字段的网格绑定到列表 1,即使列表在 y 1 上,文本字段在 y 2 上。

下面是一些代码。

// Command List
DefaultListModel<String> listInput = new DefaultListModel<String>();
JList<String> list = new JList<String>(listInput);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane scrollPane = new JScrollPane(list);
list.setBackground(new Color(160, 160, 160));
list.setSelectionBackground(new Color(150, 150, 150));
scrollPane.setPreferredSize(new Dimension(20, 20));
manager.setCommandList(listInput);

    c.insets = new Insets(2, 2, 2, 2);
    c.ipady = 0;
    c.ipadx = 100;
    c.gridx = 0;
    c.gridy = 1;
    c.gridwidth = 1;
    c.gridheight = 2;
    c.weightx = 0.1;
    c.weighty = 0.6;
    c.fill = GridBagConstraints.BOTH;
console.add(scrollPane, c);

// Image Displayer
JLabel image = new JLabel(new ImageIcon());
manager.setImageField(image);

    c.insets = new Insets(0, 0, 0, 0);
    c.ipady = 0;
    c.ipadx = 0;
    c.gridx = 0;
    c.gridy = 0;
    c.gridwidth = 1;
    c.gridheight = 1;
    c.weightx = 0.1;
    c.weighty = 0.3;
    c.fill = GridBagConstraints.BOTH;
console.add(image, c);

其中'c'是网格包约束并控制主JPanel。如您所见,列表的网格高度为2,权重为0.6,图像的网格高度为1,权重为0.9,因此不确定为什么列表比图像小4倍。

另一个问题,我已经在持有图像的JLabel中添加了一个侦听器(在调整大小时),无论如何,它没有被调用。我应该将侦听器添加到主面板吗?因为图像只由布局管理器调整大小。

谢谢^^

编辑:SSCCE:

package co.relieved.jelly.application.display.swing;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.ListSelectionModel;

@SuppressWarnings("serial")
public class Test extends JPanel {

    static JLabel image;

    public static void main(String[] args) {
        display();
        try {
            BufferedImage buffer = ImageIO
                .read(new File("/home/juanco/Pictures/Screenshot from 2016-02-08 22-43-22.png"));
            image.setIcon(new ImageIcon(
                buffer.getScaledInstance(image.getWidth(), image.getHeight(), BufferedImage.SCALE_SMOOTH)));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public Test() {
        super(new GridLayout(1, 1));
        JTabbedPane tabs = new JTabbedPane();

        /*** >>> Console Pane <<< ***/
        JPanel console = new JPanel();
        console.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        c.ipadx = 0;
        c.ipady = 0;
        c.gridwidth = 1;
        c.anchor = GridBagConstraints.CENTER;
        c.fill = GridBagConstraints.BOTH;

        // Console Screen
        JTextPane screen = new JTextPane();
        screen.setEditable(false);

        c.gridx = 1;
        c.gridy = 0;
        c.gridheight = 2;
        c.weightx = 0.8;
        c.weighty = 1;
        console.add(screen, c);

        // Console Input
        JTextField input = new JTextField();

        c.insets = new Insets(2, 0, 2, 0);
        c.ipady = 3;
        c.gridy = 2;
        c.gridheight = 1;
        c.weighty = 0;
        c.fill = GridBagConstraints.HORIZONTAL;
        console.add(input, c);

        // Command List
        DefaultListModel<String> listInput = new DefaultListModel<String>();
        listInput.setSize(1);
        JList<String> list = new JList<String>(listInput);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JScrollPane scrollPane = new JScrollPane(list);

        c.insets = new Insets(2, 2, 2, 2);
        c.ipady = 0;
        c.ipadx = 100;
        c.gridx = 0;
        c.gridy = 1;
        c.gridheight = 2;
        c.weightx = 0.1;
        c.weighty = 0.6;
        c.fill = GridBagConstraints.BOTH;
        console.add(scrollPane, c);

        // Image Displayer
        image = new JLabel(new ImageIcon());

        c.insets = new Insets(0, 0, 0, 0);
        c.ipadx = 0;
        c.gridy = 0;
        c.gridheight = 1;
        c.weighty = 0.3;
        console.add(image, c);

        // General
        tabs.addTab("Console", console);

        /*** >>> Logs Pane <<< ***/
        JPanel logs = new JPanel();

        tabs.addTab("Logs", logs);

        // Setup
        tabs.setSelectedIndex(0);
        add(tabs);
    }

    static void display() {
        JFrame frame = new JFrame("Relieved Console");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setPreferredSize(new Dimension(800, 500));
        frame.add(new Test(), BorderLayout.CENTER);

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

共3个答案

匿名用户

下面是一些代码。

这无济于事。网格只能用整个代码完成。也就是说,我们需要知道所有组件的网格宽度和网格高度,以便确定网格中每个组件的空间分配。

文本字段的网格与列表绑定在一起,尽管列表在y 1上,文本字段在y 2上。

你不能随便给一个网格分配一个组件。仅当组件上方的组件的网格高度为2时,组件才会转到网格2。所以基本上你的每一列都需要有总网格高度为3的组件。

我不知道如何把名单扩大

将首选大小设置为 (20, 20) 无济于事。无论如何,你不应该使用 setPreferredSize() 方法。

相反,您应该使用:

list.setVisibleRowCount(...);

以指定可见行。然后JList可以确定自己喜欢的大小。

另一个布局选项是使用嵌套面板,这可以简化布局。

所以你可以从一个使用边界布局的“西”面板开始。然后将标签添加到“PAGE_START”,将列表添加到“CENTER”。

然后创建一个“中心”面板。将主组件添加到“中心”,将文本字段添加到“PAGE_START”。

然后将两个面板添加到框架中:

frame.add(westPanel, BorderLayout.LINE_START);
frame.add(centerPanel, BorderLayout.CENTER);

编辑:

对不起,我收回了我关于让每列的网格高度为3的评论。不能只指定总轴网高度为3,因为每列中只有2个构件,所以每个构件的高度只能为1。

看看我在这篇文章中的回答:为什么这个GridBagLayout没有按计划出现?一个黑客,允许你通过使用行/列中的不可见组件来操纵网格高度/重量。

但是,我不建议使用这种方法。使用我建议的嵌套面板使用BorderLayout(或嵌套面板上的其他布局管理器)会容易得多。

匿名用户

在我看来,您还需要为文本字段指定< code>gridwidth和/或< code>gridheight。

GridBagLayout就像一个荣耀的GridLayout。它将尝试将所有组件与周围最近的网格空间对齐。Oracle的教程也描述了这种行为。

很多时候,使用GridBagLayout布局组件的问题来自于添加到布局中的其他组件,而不是明显的问题子组件。

匿名用户

我修复了它,将“控制台”JPanel 一分为二,左侧是边框布局面板,右侧是网格袋布局面板。正如@camickr所建议的