Принуждение компонентов к укладке сверху, а не по центру по вертикали

В настоящее время я разрабатываю графический интерфейс для приложения, использующего Swing. Если вы посмотрите на картинку, вы увидите желтую панель JPanel, которая размещена внутри BorderLayout. Эта панель использует GridBagLayout для размещения внутри нее компонентов. Как видите, один ряд компонентов состоит из метки, текстового поля и кнопки. На данный момент есть два ряда компонентов, центрированных по вертикали. Однако я хотел бы, чтобы они располагались сверху панели. Я попытался установить свойство frame.setAlignmentY(TOP_ALIGNMENT), а также свойство gridBagConstraints.anchor, но безрезультатно. Я считаю, что мой подход к этой проблеме неправильный, и вместо того, чтобы часами биться, я обращаюсь к добрым людям из stackoverflow.

Так вот вопрос, как заставить сетку компонентов быть вертикально не по центру, а сверху? Спасибо за любой совет, указывающий мне в правильном направлении.

Frame

РЕДАКТИРОВАТЬ (код):

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 * 
 * @author mt
 */
public class MainView extends JFrame {

    public MainView() {
        setPreferredSize(new Dimension(500, 500));
        getContentPane().setLayout(new BorderLayout());

        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBackground(Color.YELLOW);
        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(4, 4, 4, 4);

        c.gridx = 0;
        c.gridy = 0;
        panel.add(new JLabel("PokerStars"), c);

        c.gridx = 1;
        c.gridy = 0;
        panel.add(new JTextField(20), c);

        c.gridx = 2;
        c.gridy = 0;
        panel.add(new JButton("btn"), c);

        c.gridx = 0;
        c.gridy = 1;
        panel.add(new JLabel("Full Tilt Poker"), c);

        c.gridx = 1;
        c.gridy = 1;
        panel.add(new JTextField(20), c);

        c.gridx = 2;
        c.gridy = 1;
        panel.add(new JButton("btn"), c);

        add(panel, BorderLayout.LINE_START);

        pack();
        setVisible(true);
    }

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

person m.t    schedule 04.01.2013    source источник
comment
Не могли бы вы добавить код?   -  person Stefan Neubert    schedule 04.01.2013
comment
Опубликуйте SSCCE. Ваше описание действительно трудно понять. К вашему сведению: если вы хотите, чтобы anchor или fill работали, вам также необходимо указать weightx и/или weighty что-то большее, чем 0 (помните, что эти значения не являются процентами, они представляют собой только «вес» того, как распределяется дополнительное доступное пространство. Сумма веса не обязательно должна составлять 1).   -  person Guillaume Polet    schedule 04.01.2013
comment
@GuillaumePolet Извините за неясность. Я понял, что допустил пару ошибок в описании. Тем не менее, вот, надеюсь, достаточная ссылка SSCCE.   -  person m.t    schedule 04.01.2013


Ответы (1)


Хорошо, один из способов решить вашу проблему — добавить дополнительный «невидимый» компонент в конец вашего panel и заставить его занимать все дополнительное доступное вертикальное пространство. Вот как вы можете это сделать:

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

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 * 
 * @author mt
 */
public class MainView extends JFrame {

    public MainView() {
        setPreferredSize(new Dimension(500, 500));
        getContentPane().setLayout(new BorderLayout());
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBackground(Color.YELLOW);
        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(4, 4, 4, 4);
        panel.add(new JLabel("PokerStars"), c);

        panel.add(new JTextField(20), c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        panel.add(new JButton("btn"), c);
        c.gridwidth = 1;

        panel.add(new JLabel("Full Tilt Poker"), c);

        panel.add(new JTextField(20), c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        panel.add(new JButton("btn"), c);
        c.weighty = 1.0;
        panel.add(Box.createGlue(), c);

        add(panel, BorderLayout.LINE_START);

        pack();
        setVisible(true);
    }

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

Хотя это не мой любимый вариант, он решит ваши проблемы приемлемым образом. Существует, вероятно, более интересный способ решить эту проблему, но для этого нужно знать, на какой пользовательский интерфейс вы ориентируетесь и как вы ожидаете, что различные компоненты будут вести себя при изменении размера окна.

В большинстве случаев вы должны стараться не устанавливать gridx/gridy и использовать их значение по умолчанию (RELATIVE), это делает ваш код короче и его намного проще поддерживать, если вам нужно вставить один или несколько компонентов.

person Guillaume Polet    schedule 04.01.2013