Swing: вертикально сложенные компоненты без MigLayout - PullRequest
2 голосов
/ 14 июня 2011

Я наконец-то получил желаемое поведение для вертикально расположенных компонентов, которые имеют предпочтительную высоту, которая меняется со временем. Но мне нужно было использовать MigLayout.

Есть ли способ сделать это без MigLayout? (Это для библиотеки, и я не хочу форсировать зависимость, если мне не нужно)

Вот поведение, которое я ищу (которого достигает моя тестовая программа):

enter image description here

В вертикальном порядке есть кнопка изменения размера, «пустое пространство» (ну, JLabel, помеченный как таковой), красный прямоугольник и зеленый квадрат. Кнопка изменения размера имеет фиксированную высоту. Красный квадрат имеет случайный размер, который может меняться в любое время. Зеленый квадрат устанавливает его предпочтительную высоту, чтобы соответствовать его ширине, и я хочу увеличить его ширину, чтобы заполнить контейнер. Пустое пространство расширяется по горизонтали и вертикали, чтобы заполнить оставшееся пространство в контейнере.

Что будет работать вместо MigLayout?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;

public class AutoResizeDemo extends JPanel
{   
    static private class ResizingPanel extends JPanel
    {
        final private Color color;

        private Dimension dpref = new Dimension(100,100);

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int w = getWidth();
            int h = getHeight();
            g.setColor(this.color);
            g.fillRect(0, 0, w, h);
            g.setColor(Color.BLACK);
            g.drawRect(0, 0, w-1, h-1); 
            String s = this.dpref.width+"x"+this.dpref.height;
            FontMetrics fm = g.getFontMetrics();
            g.drawString(s, 0, fm.getHeight());
        }

        public ResizingPanel(Color color, boolean isSquare)
        {
            this.color = color;
            if (isSquare)
            {
                addComponentListener(new ComponentAdapter() {
                    @Override public void componentResized(ComponentEvent e) {
                        doResize(getWidth(), getWidth());
                    }               
                });
            }
        }

        @Override public Dimension getPreferredSize() {
            return this.dpref;
        } 

        public void doResize(int w, int h)
        {
            this.dpref = new Dimension(w, h);
            revalidate();
        }
    }

    public AutoResizeDemo()
    {
        super(new MigLayout("","[grow]",""));
        setPreferredSize(new Dimension(200, 800));

        final ResizingPanel resizingPanelRandom = new ResizingPanel(Color.RED, false);
        ResizingPanel resizingPanelSquare = new ResizingPanel(Color.GREEN, true);
        JPanel buttonPanel = new JPanel(new FlowLayout());

        final Random rand = new Random();
        addButton(buttonPanel, "resize",new Runnable() {
            @Override public void run() {
                resizingPanelRandom.doResize(
                        rand.nextInt(100)+100,
                        rand.nextInt(100)+100
                        );
            }           
        });
        add(buttonPanel, "wrap");
        JLabel spaceLabel = new JLabel("empty space");
        spaceLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        add(spaceLabel, "push, grow, wrap");
        add(resizingPanelRandom, "wrap");
        add(resizingPanelSquare,"pushx, growx, wrap");
    }

    private void addButton(JPanel panel, String title, final Runnable r) {
        JButton button = new JButton(title);
        button.addActionListener(new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
                r.run();
            }           
        });
        panel.add(button);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame(AutoResizeDemo.class.getSimpleName());
        frame.setContentPane(new AutoResizeDemo());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

    }

}

Ответы [ 3 ]

6 голосов
/ 14 июня 2011

Используйте BoxLayout.

Вы бы использовали Box.createVerticalGlue () для пустого пространства.

BoxLayout учитывает максимальный размер компонента, поэтому вам, вероятно, потребуется переопределить метод getMaximumSize (), чтобы вернуть предпочтительный размер для красных и зеленых полей.

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

4 голосов
/ 14 июня 2011

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

Панель кнопок
слева и сверху панели кнопок слева и сверху панели контейнера

Зеленая панель
слева, справа и снизу слева, справа и снизу панели контейнера

Красная панель
слева от панели контейнера и снизу вверх зеленой панели

Пробел
сверху к югу от панели кнопок, слева и справа, слева и справа от панели контейнера, снизу вверх красной панели

Редактировать: Я люблю SpringLayout , есть ничего это не может сделать.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SpringLayout;

public class AutoResizeDemo2 extends JPanel {
  static private class ResizingPanel extends JPanel {
    final private Color color;

    private Dimension dpref = new Dimension(100, 100);

    @Override
    protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      int w = getWidth();
      int h = getHeight();
      g.setColor(this.color);
      g.fillRect(0, 0, w, h);
      g.setColor(Color.BLACK);
      g.drawRect(0, 0, w - 1, h - 1);
      String s = this.dpref.width + "x" + this.dpref.height;
      FontMetrics fm = g.getFontMetrics();
      g.drawString(s, 0, fm.getHeight());
    }

    public ResizingPanel(Color color, boolean isSquare) {
      this.color = color;
      if (isSquare) {
        addComponentListener(new ComponentAdapter() {
          @Override
          public void componentResized(ComponentEvent e) {
            doResize(getWidth(), getWidth());
          }
        });
      }
    }

    @Override
    public Dimension getPreferredSize() {
      return this.dpref;
    }

    public void doResize(int w, int h) {
      this.dpref = new Dimension(w, h);
      revalidate();
    }
  }

  public AutoResizeDemo2() {

    SpringLayout layout = new SpringLayout();
    setLayout(layout);

    setPreferredSize(new Dimension(200, 800));

    final ResizingPanel resizingPanelRandom = new ResizingPanel(Color.RED, false);
    ResizingPanel resizingPanelSquare = new ResizingPanel(Color.GREEN, true);
    JPanel buttonPanel = new JPanel(new FlowLayout());

    final Random rand = new Random();
    addButton(buttonPanel, "resize", new Runnable() {
      @Override
      public void run() {
        resizingPanelRandom.doResize(rand.nextInt(100) + 100, rand.nextInt(100) + 100);
      }
    });
    add(buttonPanel);
    layout.putConstraint(SpringLayout.NORTH, buttonPanel, 5, SpringLayout.NORTH, this);
    layout.putConstraint(SpringLayout.WEST, buttonPanel, 5, SpringLayout.WEST, this);

    JLabel spaceLabel = new JLabel("empty space");
    spaceLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));

    add(resizingPanelSquare);
    layout.putConstraint(SpringLayout.SOUTH, resizingPanelSquare, -5, SpringLayout.SOUTH, this);
    layout.putConstraint(SpringLayout.WEST, resizingPanelSquare, 5, SpringLayout.WEST, this);
    layout.putConstraint(SpringLayout.EAST, resizingPanelSquare, -5, SpringLayout.EAST, this);

    add(resizingPanelRandom);
    layout.putConstraint(SpringLayout.SOUTH, resizingPanelRandom, -5, SpringLayout.NORTH, resizingPanelSquare);
    layout.putConstraint(SpringLayout.WEST, resizingPanelRandom, 5, SpringLayout.WEST, this);

    add(spaceLabel);
    layout.putConstraint(SpringLayout.NORTH, spaceLabel, 5, SpringLayout.SOUTH, buttonPanel);
    layout.putConstraint(SpringLayout.WEST, spaceLabel, 5, SpringLayout.WEST, this);
    layout.putConstraint(SpringLayout.EAST, spaceLabel, -5, SpringLayout.EAST, this);
    layout.putConstraint(SpringLayout.SOUTH, spaceLabel, -5, SpringLayout.NORTH, resizingPanelRandom);
  }

  private void addButton(JPanel panel, String title, final Runnable r) {
    JButton button = new JButton(title);
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        r.run();
      }
    });
    panel.add(button);
  }

  public static void main(String[] args) {
    JFrame frame = new JFrame(AutoResizeDemo2.class.getSimpleName());
    frame.setContentPane(new AutoResizeDemo2());
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

  }

}
0 голосов
/ 02 июня 2012

SpringLayout трудно определить, как он выложен без большого анализа.Попробуйте TableLayout .Единственная сложная часть вашего макета - высота зеленого квадрата, равная его ширине.Это немного необычно для менеджера компоновки, чтобы поддержать, поэтому я бы просто особый случай.Пример выполнения:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import com.esotericsoftware.tablelayout.swing.Table;

public class Test extends JFrame {
    JButton button;
    JPanel red, green;

    public Test () {
        button = new JButton("Resize");
        button.addActionListener(new ActionListener() {
            public void actionPerformed (ActionEvent e) {
                red.setPreferredSize(new Dimension(138, new Random().nextInt(190) + 10));
                red.revalidate();
            }
        });

        red = new JPanel();
        red.setPreferredSize(new Dimension(138, 145));
        red.setBackground(Color.red);

        green = new JPanel();
        green.setPreferredSize(new Dimension(100, 100));
        green.setBackground(Color.green);

        // The DSL can be much easier to describe complex hierarchies.
        boolean dsl = false;
        if (dsl)
            dsl();
        else
            javaApi();

        setSize(160, 400);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private void javaApi () {
        final Table table = new Table() {
            public void layout () {
                green.setPreferredSize(new Dimension(getWidth(), getWidth()));
                super.layout();
            }
        };
        table.pad(10).defaults().left().space(5);
        table.addCell(button);
        table.row();
        table.addCell().expandY();
        table.row();
        table.addCell(red);
        table.row();
        table.addCell(green).expandX().fillX();
        getContentPane().add(table);
    }

    private void dsl () {
        final Table table = new Table() {
            public void layout () {
                green.setPreferredSize(new Dimension(getWidth(), getWidth()));
                super.layout();
            }
        };
        table.register("button", button);
        table.register("red", red);
        table.register("green", green);
        table.parse("pad:10 * left space:5 " //
            + "[button] ---" //
            + "[] expandy ---" //
            + "[red] ---" //
            + "[green] expandx fillx" //
        );
        getContentPane().add(table);
    }

    public static void main (String[] args) throws Exception {
        new Test();
    }
}

Будучи основанным на таблицах, легко получить представление о макете с первого взгляда.Я включил код для использования Java API, а также DSL.Java API хорош, так как вы получили завершение.Вот только код компоновки:

table.pad(10).defaults().left().space(5);
table.addCell(button);
table.row();
table.addCell().expandY();
table.row();
table.addCell(red);
table.row();
table.addCell(green).expandX().fillX();

DSL удобен для описания иерархий, вероятно, не требуется для этого примера.К сожалению, Java не имеет дословной строки, хотя большой интерфейс может быть описан в файле.DSL для этого примера без строковых кавычек Java будет:

pad:10 * left space:5
[button]
---
[] expandy
---
[red]
---
[green] expandx fillx
...