Проблем с Swing BoxLayout с JComboBox без използване на setXXXSize

ето SSCCE:

import java.awt.Color;
import java.awt.Dimension;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class BoxLayoutTest extends JFrame {

    public BoxLayoutTest(){
        JPanel main = new JPanel();
        main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS));
        main.setBackground(Color.red);
        this.add(main);
        JPanel northPanel = new JPanel();

        JPanel middle = new JPanel();
        middle.setLayout(new BoxLayout(middle, BoxLayout.X_AXIS));
        middle.add(new JButton("FOO"));
        middle.add(Box.createHorizontalGlue());

        JPanel aPanel = new JPanel();
        aPanel.setBackground(Color.black);

            JComboBox b = new JComboBox();
    //b.setPreferredSize(new Dimension(100,16)); //uncomment this to see the layout I would like to achieve
    //b.setMaximumSize(new Dimension(100,16));
        //middle.add(b); //uncomment this line 

        middle.setBackground(Color.green);
        northPanel.setBackground(Color.blue);

        main.add(northPanel);
        main.add(middle);
        main.add(Box.createVerticalGlue());

        this.setSize(800,600);
        this.setResizable(true);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        new BoxLayoutTest();
    }

}

Опитвам се да преработя някои класове, които написах преди време, когато не знаех, че използването на методи setXXXSize върху компоненти е грешно. Използвайки рамка с възможност за промяна на размера, резултатът, който искам да постигна, е следният:

  1. Северният панел трябва да остане отгоре и да промени размера си в съответствие с модификациите на размера на рамката (изглежда, че работи добре)
  2. Зеленият панел, където поставям JButton, трябва да запази максималния размер на JButton и да остане точно под синия панел по-горе (това работи добре, ако поставям само JButton вътре в този панел).

Проблемът възниква, ако поставя JComboBox в зеления панел (опитайте се да разкоментирате реда в SSCCE). Предполагам, че JComboBox няма посочен максимален размер, така че се разтяга с рамката. В предишната грешна версия на моя код използвах методи setxxxSize на JComboBox, за да огранича размерите му (опитайте се да премахнете коментарите от реда на методите setXXXSize, за да го видите).

Въпросът ми е:

  1. Възможно ли е да се постигне същия резултат с помощта на BoxLayout без извикване на методи setXXXSize()?
  2. Ако да, как?
  3. Има ли друг LayoutManager, който мога да използвам, за да постигна този ефект?

Моля, насочете ме в правилната посока


person Heisenbug    schedule 28.09.2011    source източник


Отговори (2)


JComboBox се държи неправилно (същото като JTextField) при отчитане на неограничена максимална височина: никога не трябва да показва повече от един ред. Решението е същото: подклас и връщане на разумна височина

        JComboBox b = new JComboBox() {

            /** 
             * @inherited <p>
             */
            @Override
            public Dimension getMaximumSize() {
                Dimension max = super.getMaximumSize();
                max.height = getPreferredSize().height;
                return max;
            }

        };

просто за забавление, ето един фрагмент, използващ MigLayout (който е моят личен фаворит в момента :-)

    // two panels as placeholders
    JPanel northPanel = new JPanel();
    northPanel.setBackground(Color.YELLOW);
    JPanel southPanel = new JPanel();
    southPanel.setBackground(Color.YELLOW);
    // layout with two content columns
    LC layoutContraints = new LC().wrapAfter(2)
            .debug(1000);
    AC columnContraints = new AC()
    // first column pref, followed by greedy gap
            .size("pref").gap("push")
            // second
            .size("pref");
    // three rows, top/bottom growing, middle pref
    AC rowContraints = new AC()
       .grow().gap().size("pref").gap().grow();
    MigLayout layout = new MigLayout(layoutContraints, columnContraints,
            rowContraints);
    JPanel main = new JPanel(layout);
    main.setBackground(Color.WHITE);
    // add top spanning columns and growing
    main.add(northPanel, "spanx, grow");
    main.add(new JButton("FOO"));

    // well-behaved combo: max height == pref height
    JComboBox combo = new JComboBox() {

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

    };
    // set a prototype to keep it from constantly adjusting
    combo.setPrototypeDisplayValue("somethingaslongasIwant");

    main.add(combo);
    // add top spanning columns and growing
    main.add(southPanel, "spanx, grow");
person kleopatra    schedule 28.09.2011
comment
Благодаря за отговора. Изглежда, че това е грешка на Swing, ще бъде ли поправена? - person Heisenbug; 28.09.2011
comment
@Heisenbug - не знам, попитайте екипа на Swing :-) - person kleopatra; 28.09.2011

Винаги съм виждал, че използването на мениджърите за оформление в jdk не е лесно. Те са или твърде прости и негъвкави, или gridbaglayout е твърде много проблем. Вместо това започнах да използвам оформлението на формуляра jgoodies и никога не погледнах назад оттогава.. Разгледайте го. Той е много прост и лесен за използване. Ето линк:

http://www.jgoodies.com/freeware/forms/

Уверете се, че сте прегледали бялата хартия.

А сега имаме и google, който ни предоставя WYSISWG редактор за formlayout като плъгин за eclipse. Това просто прави живота много по-лесен.

http://code.google.com/javadevtools/wbpro/palettes/swing_palette.html

person sethu    schedule 28.09.2011