Изменение размера делает вещи неправильными

Я хочу создать JInternalFrame с некоторыми компонентами.

Моя цель - разработать консоль bash на Java.

Моя рама состоит из 4 компонентов:

  • JTextArea включен в JScrollPane
  • JLabel с текстом «Cmd:»
  • JTextField
  • JButton с текстом "Отправить"

И у меня есть следующий код:

Box box = Box.createHorizontalBox();
box.add(Box.createVerticalStrut(5));
box.add(this.cmd_label);
box.add(Box.createVerticalStrut(5));
box.add(this.cmd_input);
box.add(Box.createVerticalStrut(5));
box.add(this.submit);
box.add(Box.createVerticalStrut(5));

Box mainBox = Box.createVerticalBox();
mainBox.add(Box.createHorizontalStrut(5));
mainBox.add(this.result_scroll);
mainBox.add(Box.createHorizontalStrut(5));
mainBox.add(box);
mainBox.add(Box.createHorizontalStrut(5));
add(mainBox);

Итак, когда кадр не развернут, у меня правильный вид:

Неразвернутый кадр

Но когда я его максимизирую, все компоненты расположены неправильно:

Развернутый кадр

Итак, вот мой вопрос: как я могу установить вес компонентов, чтобы каждый раз фиксировать их местоположение, или как я могу это исправить?

Спасибо.


person Manitoba    schedule 20.04.2012    source источник


Ответы (3)


Я думаю, что это было бы лучше сделать с помощью BorderLayout. В BorderLayout компонент, указанный как центральный, будет расширяться, чтобы заполнить как можно больше места, а другие компоненты останутся в своих предпочтительных размерах.

int hgap = 5;
int vgap = 5;
internalFrame.getContentPane().setLayout(new BorderLayout(hgap, vgap));
internalFrame.getContentPane().add(this.result_scroll, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel();
bottomPanel.add(this.cmd_label);
bottomPanel.add(this.cmd_input);
bottomPanel.add(this.submit);
internalFrame.getContentPane().add(bottomPanel, BorderLayout.SOUTH);
person Dan O    schedule 20.04.2012
comment
Спасибо, это работает, но JTextField больше не занимает всю ширину. Как я могу это сделать? - person Manitoba; 20.04.2012
comment
используйте другой BorderLayout для нижней панели :) - person Dan O; 20.04.2012
comment
+1, мне нравится такой подход, это то, о чем я подумал при первом взгляде на вопрос. - person nIcE cOw; 20.04.2012

Вот попробуйте этот код, возможно ли это поведение:

import java.awt.*;
import javax.swing.*;

public class LayoutExample
{
    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("LAYOUT EXAMPLE");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel centerPanel = new JPanel();
        centerPanel.setLayout(new BorderLayout(5, 5));
        centerPanel.setBorder(
                    BorderFactory.createEmptyBorder(2, 2, 2, 2));
        JTextArea tarea = new JTextArea(10, 10);
        tarea.setBackground(Color.DARK_GRAY.darker());  
        tarea.setForeground(Color.WHITE);
        tarea.setCaretColor(Color.WHITE);
        tarea.setLineWrap(true);

        JScrollPane scrollPane = new JScrollPane(tarea);
        centerPanel.add(scrollPane, BorderLayout.CENTER);

        JPanel footerPanel = new JPanel();
        footerPanel.setLayout(new BorderLayout(5, 5));
        footerPanel.setBorder(
                    BorderFactory.createEmptyBorder(2, 2, 2, 2));       
        JLabel cmdLabel = new JLabel("Cmd : ");         
        JTextField tfield = new JTextField(10);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setBorder(
                    BorderFactory.createEmptyBorder(2, 2, 2, 2));
        JButton sendButton = new JButton("SEND");

        footerPanel.add(cmdLabel, BorderLayout.LINE_START);
        footerPanel.add(tfield, BorderLayout.CENTER);
        buttonPanel.add(sendButton);
        footerPanel.add(buttonPanel, BorderLayout.LINE_END);

        frame.getContentPane().add(centerPanel, BorderLayout.CENTER);
        frame.getContentPane().add(footerPanel, BorderLayout.PAGE_END);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {   
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new LayoutExample().createAndDisplayGUI();
            }
        });
    }
}

ВЫХОД :

НА НАЧАЛЕ

КОГДА МАКСИМИЗИРОВАНО

person nIcE cOw    schedule 20.04.2012

Основная проблема здесь заключается в том, что я считаю ошибкой в ​​​​подсказке максимального макета JTextField: он не ограничен как по горизонтали , так и по вертикали. Последнее — полная ерунда для компонента, предназначенного для отображения одной строки текста. Чтобы исправить, создайте подкласс и позвольте ему вернуть свой pref для высоты, например:

JTextField cmdInput = new JTextField() {

    @Override
    public Dimension getMaximumSize() {
        Dimension max = super.getMaximumSize();
        max.height = getPreferredSize().height;
        return max;
    }

};

Поскольку BoxLayout учитывает maxSize, избыточная высота теперь будет отдана только верхнему блоку.

В долгосрочной перспективе рассмотрите возможность перехода к стороннему менеджеру, который позволяет точно настроить подход «все в одной панели». А вот и мой нынешний фаворит: MigLayout. Сравните следующие строки со всеми приведенными выше трюками с вложением и границами и получайте удовольствие :-)

MigLayout layout = new MigLayout("wrap 3, debug", 
        "[][grow, fill][]", // 3 columns, middle column filled and allows growing
        "[grow, fill][]"); // two rows, first filled and allows growing

JComponent content = new JPanel(layout);
// the scrollPane in the first row spanning all columns
// and growing in both directions 
content.add(new JScrollPane(new JTextArea(20, 20)), "span, grow");
// auto-wrapped to first column in second row
content.add(new JLabel("Cmd:"));
content.add(new JTextField());
content.add(new JButton("Submit"));
person kleopatra    schedule 30.06.2012
comment
+1 за исправление компонентов Core-Javas снова ;-) И для LayoutManager: я не могу выбрать между MigLayout и DesignGridLayout... - person bobndrew; 04.07.2012