JSpinner в макете gridbag

У меня есть простой макет сетки, и когда я использую только текстовые поля, он работает правильно. Когда я вставляю JSpinner, весь макет полностью портится. Под этим я подразумеваю, что два из трех моих столбцов полностью исчезают, второй столбец, единственный столбец, который появляется, занимает всю ширину окна независимо от размера окна. Полный код ниже.

Проблема, похоже, как-то связана со счетчиками, если я использую другие виды JComponents, такие как JLabel, проблема не проявляется. Что я сделал не так, из-за чего JSpinner полностью уничтожил макет?

package product_data.ui;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;

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

public class StrippedProductEditor extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 5429511033322948114L;
    private JLabel lblManufacturer;
    private JLabel lblSku;
    private JTextField mfrText;
    private JTextField skuText;
    private JTextArea extraText;
    private JLabel lblListPrice;
    private JSpinner spinner;


    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    new StrippedProductEditor();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public StrippedProductEditor() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWidths = new int[] { 0, 0, 0 };
        gridBagLayout.rowHeights = new int[] { 0, 0, 0, };
        gridBagLayout.columnWeights = new double[] { 0.0, 1.0, 1.0 };
        gridBagLayout.rowWeights = new double[] { 0.0, 0.0, 0.0};
        getContentPane().setLayout(gridBagLayout);

        lblManufacturer = new JLabel("Manufacturer");
        GridBagConstraints gbc_lblManufacturer = new GridBagConstraints();
        gbc_lblManufacturer.insets = new Insets(0, 0, 5, 5);
        gbc_lblManufacturer.gridx = 0;
        gbc_lblManufacturer.gridy = 0;
        getContentPane().add(lblManufacturer, gbc_lblManufacturer);

        mfrText = new JTextField();
        GridBagConstraints gbc_lblMfrText = new GridBagConstraints();
        gbc_lblMfrText.insets = new Insets(0, 0, 5, 5);
        gbc_lblMfrText.fill = GridBagConstraints.HORIZONTAL;
        gbc_lblMfrText.gridx = 1;
        gbc_lblMfrText.gridy = 0;
        getContentPane().add(mfrText, gbc_lblMfrText);

        lblSku = new JLabel("SKU");
        GridBagConstraints gbc_lblSku = new GridBagConstraints();
        gbc_lblSku.insets = new Insets(0, 0, 5, 5);
        gbc_lblSku.gridx = 0;
        gbc_lblSku.gridy = 1;
        getContentPane().add(lblSku, gbc_lblSku);

        skuText = new JTextField();
        GridBagConstraints gbc_textField_1 = new GridBagConstraints();
        gbc_textField_1.insets = new Insets(0, 0, 5, 5);
        gbc_textField_1.fill = GridBagConstraints.HORIZONTAL;
        gbc_textField_1.gridx = 1;
        gbc_textField_1.gridy = 1;
        getContentPane().add(skuText, gbc_textField_1);
        skuText.setColumns(10);

        extraText = new JTextArea();
        JScrollPane dictScrollPane = new JScrollPane(extraText);
        GridBagConstraints gbc_dict = new GridBagConstraints();
        gbc_dict.insets = new Insets(0, 0, 5, 5);
        gbc_dict.gridx = 2;
        gbc_dict.gridy = 0;
        gbc_dict.gridheight = 2;
        gbc_dict.fill = GridBagConstraints.BOTH;

        getContentPane().add(dictScrollPane, gbc_dict);
        lblListPrice = new JLabel("List Price");
        GridBagConstraints gbc_lblListPrice = new GridBagConstraints();
        gbc_lblListPrice.insets = new Insets(0, 0, 5, 5);
        gbc_lblListPrice.gridx = 0;
        gbc_lblListPrice.gridy = 2;
        getContentPane().add(lblListPrice, gbc_lblListPrice);

        double lp = 99.9;
        SpinnerNumberModel m = new SpinnerNumberModel(lp, 0.0d,
                Double.MAX_VALUE, 0.01d);
        spinner = new JSpinner(m);
        GridBagConstraints gbc_spinner = new GridBagConstraints();
        gbc_spinner.fill = GridBagConstraints.HORIZONTAL;
        gbc_spinner.insets = new Insets(0, 0, 5, 5);
        gbc_spinner.gridx = 1;
        gbc_spinner.gridy = 2;
        //commenting out this line will make the layout look 
        //correct, but then the spinner is missing.
        getContentPane().add(spinner, gbc_spinner);

        this.pack();
        this.setVisible(true);
    }

}

person zelinka    schedule 06.10.2014    source источник
comment
Даже с закомментированным счетчиком раскладка не совсем подходит для меня. При первом отображении фрейма столбец 2 имеет нулевую ширину. Он восстанавливается, если я изменяю размер кадра.   -  person John Bollinger    schedule 07.10.2014
comment
Похоже, у вас шаткие весы. У вас есть только веса по умолчанию, нет весов для каждого компонента, но веса строк и столбцов, указанные в самом макете, в основном равны нулю.   -  person John Bollinger    schedule 07.10.2014


Ответы (3)


Итак, немного покопавшись в коде, я обнаружил, что JSpinner.NumberEditor, который является редактором, который использовался для поддержки SpinnerNumberModel, вычисляет свойство fields columns с помощью...

try {
    String maxString = formatter.valueToString(model.getMinimum());
    String minString = formatter.valueToString(model.getMaximum());
    ftf.setColumns(Math.max(maxString.length(),
                            minString.length()));
}
catch (ParseException e) {
    // TBD should throw a chained error here
}

Теперь, как выясняется, maxString равно 0 (да, я знаю), а minString равно...

179,769,313,486,231,570,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000

Что равняется 411 символам... упс...

Теперь вы можете уменьшить максимальное значение ваших моделей до чего-то более реалистичного (например, миллион) или вы можете настроить размер спиннеров вручную, используя что-то вроде...

((JSpinner.NumberEditor) spinner.getEditor()).getTextField().setColumns(10);

Лично я предпочитаю первый вариант ;)

person MadProgrammer    schedule 06.10.2014

Проблема возникает из-за того, что ваши компоненты и макет недостаточно ограничены, но ключевая проблема, по-видимому, заключается в том, что предпочтительный размер Spinner не сочетается с другими компонентами. Все стало намного лучше после того, как я добавил

spinner.setPreferredSize(new Dimension(128, 16));

хотя столбец 2 по-прежнему имеет ширину 0. Вы также должны установить предпочтительный размер для JTextArea, чтобы разобраться с этим. Кроме того, вы можете установить предпочтительный размер для всего JFrame.

person John Bollinger    schedule 06.10.2014
comment
См. Должен ли я избегать использования набора (предпочтительно |Максимум|Минимум) Методы размера в Java Swing? почему этот ответ, скорее всего, будет отклонен - person MadProgrammer; 07.10.2014

Если вы используете eclipse, попробуйте установить подключаемый модуль http://www.eclipse.org/windowbuilder/. делает все для вас. Лично мне очень помогло.

person Muselc    schedule 06.10.2014