Почему size и preferredSize не увеличивают размер этой метки?

#java #swing

#java #swing

Вопрос:

Я создаю панель, которая будет использоваться в более крупной программе; следующая программа по-прежнему иллюстрирует мой вопрос, но она выглядит немного сложнее, чем нужно, потому что есть места, которые я добавлю позже.

 package sandbox;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SpacingPlay extends JFrame
{
  private static final long serialVersionUID = 1L;

  public static void main(String[] args)
  {
    SpacingPlay sp = new SpacingPlay();
    sp.setVisible(true);
  }
  
  public SpacingPlay()
  {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel panel = new DragNDropPanel();
    add(panel);
    pack();
  }

  class DragNDropPanel extends JPanel
  {
    private static final long serialVersionUID = 1L;
    
    public DragNDropPanel()
    {
      
      JPanel currentImagePanel    = getCurrentImagePanel();
      JPanel  leftPanel = new JPanel();
      leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
      leftPanel.add(currentImagePanel);
      
      // other things will go here; I cut them out to make this simpler.
      
      setLayout(new BorderLayout());
      // put things in a containing panel so that they aren't stretched being in the WEST part of a borderlayout.
      JPanel leftContainingPanel = new JPanel();
      leftContainingPanel.add(leftPanel);
      add(leftContainingPanel, BorderLayout.WEST);
    }
    
    private Component createStandardSpace()
    {
      return Box.createRigidArea(new Dimension(0, 15));
    }
    
    private JPanel getCurrentImagePanel()
    {
      JPanel currentImagePanel = new JPanel();
      currentImagePanel.setLayout(new BoxLayout(currentImagePanel, BoxLayout.PAGE_AXIS));
      
      JLabel currentImageLabel = new JLabel("none");
      currentImageLabel.setBorder(BorderFactory.createDashedBorder(Color.BLUE));
      currentImageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
      Dimension defaultLabelSize = new Dimension(150,150);      // was expecting this to enlarge the label.
      currentImageLabel.setPreferredSize(defaultLabelSize);
      currentImageLabel.setSize(defaultLabelSize);
      
      JButton clearButton = new JButton("Clear");
      clearButton.setAlignmentX(Component.CENTER_ALIGNMENT);
      clearButton.setBorder(BorderFactory.createLineBorder(Color.GREEN));
      
      currentImagePanel.add(currentImageLabel);
      currentImagePanel.add(createStandardSpace()); 
      currentImagePanel.add(clearButton);
      
      currentImagePanel.setBorder(BorderFactory.createLineBorder(Color.ORANGE));
      return currentImagePanel;
    }
  }

}
  

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

Однако defaultLabelSize это не имеет того эффекта, который я ожидал. Метка переходит в панель BoxLayout; она добавляется, затем жесткий пробел, затем кнопка. Я ожидал, что метка будет иметь размер по умолчанию, а не уменьшена до минимально допустимого. Я вставил цветные границы, чтобы попытаться лучше понять, что происходит; похоже, что предпочтительный размер учитывается для общей панели BoxLayout, но не для размещения кнопки под меткой. РЕДАКТИРОВАТЬ: другими словами, я хочу, чтобы кнопка под меткой размещалась под меткой, когда метка должна быть больше. Но размер, который я указываю на ярлыке, похоже, не работает.

Что мне нужно сделать, чтобы исправить размер currentImageLabel ?

Ответ №1:

Не на 100%, почему размер метки соответствует только тексту, а не (жестко заданному) предпочтительному размеру. Я не смог воспроизвести это поведение, используя другие комбинации панелей и менеджеров компоновки.

Вы используете pack, поэтому все компоненты должны иметь желаемые размеры.

   Dimension defaultLabelSize = new Dimension(150,150);      // was expecting this to enlarge the label.
  currentImageLabel.setPreferredSize(defaultLabelSize);
  currentImageLabel.setSize(defaultLabelSize);
  

Несколько комментариев:

  1. Установка размера никогда не будет работать. Менеджер компоновки всегда переопределяет размер / местоположение на основе правил менеджера компоновки.

  2. Менеджер компоновки может использовать (или игнорировать) предпочтительные, минимальные и максимальные размеры компонента. В случае BoxLayout is пытается использовать предпочтительный размер, но будет учитывать минимальный и максимальный размеры (в зависимости от доступного пространства на родительской панели).

Что мне нужно сделать, чтобы исправить размер currentImageLabel ?

Итак, для достижения желаемой цели фиксированного предпочтительного размера для JLabel вы можете использовать:

 Dimension defaultLabelSize = new Dimension(150,150);      // was expecting this to enlarge the label.
currentImageLabel.setPreferredSize(defaultLabelSize);
currentImageLabel.setMinimumSize(defaultLabelSize);
currentImageLabel.setMaximumSize(defaultLabelSize);
//currentImageLabel.setSize(defaultLabelSize);
  

Редактировать:

искал, почему это, похоже, не работает

Для получения дополнительных разъяснений измените исходный код на:

   currentImageLabel.setPreferredSize(defaultLabelSize);
  System.out.println(currentImageLabel.getPreferredSize());
  System.out.println(currentImageLabel.getMinimumSize());
  System.out.println(currentImageLabel.getMaximumSize());
  

Вы увидите, что минимальные и максимальные размеры метки не затрагиваются.

Из пункта 2 выше вы увидите, что BoxLayout соответствует максимальному размеру.

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

Однако, когда вы вычисляете предпочтительный размер «currentImagePanel», (жестко заданный) предпочтительный размер метки используется при вычислении предпочтительного размера панели, так что панель отображается в предпочтительном размере.

Еще одна записка. «leftContainingPanel» не требуется. Вы можете просто добавить «Левую панель» в BorderLayout.ЗАПАД, так как BorderLayout будет учитывать ширину добавляемого вами компонента.

Комментарии:

1. Что ж, я чувствую себя немного лучше оттого, что ты тоже этого не знаешь. Я боялся, что это было что-то очевидное. Я только что обнаружил, что добавление параметра максимального размера дало эффект; кажется немного странным, но это так. Спасибо.

2. Ну, я искал, почему это, похоже, не работает, но я думаю, что вы действительно ответили на фактический вопрос. Добавлено принятие.