JLabel: setPreferredSize вручную, но getPreferredSize после setText

я хочу установить размер JLabel на определенный (минимальный) размер через setPreferredSize(). Если текст внутри JLabel больше не помещается, JLabel должен увеличиться.

Проблема сейчас в следующем:

  • после label.setPreferredSize(new Dimension(50,20));
  • я делаю setText("new long text"); но размер не изменится
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class LabelTest
{
    public static void createWindow()
    {
        JFrame frame = new JFrame();

        JLabel label = new JLabel("Text");
        System.out.println(label.getPreferredSize().width); // 25
        label.setText("New long text");
        System.out.println(label.getPreferredSize().width); // 77 - JLabel grows as expected

        label.setText("Text");
        System.out.println(label.getPreferredSize().width); // 25
        label.setPreferredSize(new Dimension(50, 20));
        System.out.println(label.getPreferredSize().width); // 50 - JLabel grows to given size as expected
        label.setText("New long text");
        System.out.println(label.getPreferredSize().width); // 50 - it should be 77 again

        frame.add(label);
        frame.setPreferredSize(new Dimension(200, 100));
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }


    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                createWindow();
            }
        });
    }
}

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

Если вам нужна дополнительная информация, просто спросите.

Заранее спасибо!


person Nikolai    schedule 11.11.2013    source источник
comment
Так что на самом деле вам бы хотелось что-то вроде возможности переопределить getMinimumSize()... Хммм.   -  person JB Nizet    schedule 11.11.2013
comment
несвязанный: никогда не используйте setXXSize   -  person kleopatra    schedule 11.11.2013
comment
Как только вы вызовете setPreferredSize(), размер метки больше никогда не будет динамически изменяться. Вам нужно использовать setPreferredSize(null). Лучший вариант — использовать менеджер компоновки, который будет учитывать минимальные/предпочтительные размеры, например BoxLayout или GrigBagLayout.   -  person camickr    schedule 11.11.2013
comment
Спасибо за этот ответ @camickr! setPrefferedSize(null) - это именно то, что мне нужно в моем случае, хотя я знаю, что LayoutManager был бы лучше!   -  person Nikolai    schedule 14.12.2013


Ответы (2)


Вы можете достичь желаемого с помощью LayoutManager
Ниже приведен пример с GridBag Layout.

public class GridBagExample extends JFrame {

    private JPanel      contentPane;
    private JLabel      lblMyLabel;
    private JTextField  textField;
    private JButton     btnChangeMyLabel;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    GridBagExample frame = new GridBagExample();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public GridBagExample() {
        initComponents();
    }

    private void initComponents() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 94);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        GridBagLayout gbl_contentPane = new GridBagLayout();
        gbl_contentPane.columnWidths = new int[] { 0, 344, 0 };
        gbl_contentPane.rowHeights = new int[] { 0, 0, 0 };
        gbl_contentPane.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
        gbl_contentPane.rowWeights = new double[] { 1.0, 1.0, Double.MIN_VALUE };
        contentPane.setLayout(gbl_contentPane);

        lblMyLabel = new JLabel(" My Label");
        GridBagConstraints gbc_lblMyLabel = new GridBagConstraints();
        gbc_lblMyLabel.insets = new Insets(0, 0, 5, 5);
        gbc_lblMyLabel.anchor = GridBagConstraints.EAST;
        gbc_lblMyLabel.gridx = 0;
        gbc_lblMyLabel.gridy = 0;
        contentPane.add(lblMyLabel, gbc_lblMyLabel);

        textField = new JTextField();
        GridBagConstraints gbc_textField = new GridBagConstraints();
        gbc_textField.insets = new Insets(0, 0, 5, 0);
        gbc_textField.fill = GridBagConstraints.HORIZONTAL;
        gbc_textField.gridx = 1;
        gbc_textField.gridy = 0;
        contentPane.add(textField, gbc_textField);
        textField.setColumns(10);

        btnChangeMyLabel = new JButton("Change My Label");
        btnChangeMyLabel.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                lblMyLabel.setText("This is the new text of my JLabel");
            }
        });
        GridBagConstraints gbc_btnChangeMyLabel = new GridBagConstraints();
        gbc_btnChangeMyLabel.gridwidth = 2;
        gbc_btnChangeMyLabel.gridx = 0;
        gbc_btnChangeMyLabel.gridy = 1;
        contentPane.add(btnChangeMyLabel, gbc_btnChangeMyLabel);
    }

Надеюсь, поможет.

person Gabriel Câmara    schedule 11.11.2013

Чтобы установить минимальный размер, используйте setMinimumSize(Dimension). В большинстве случаев лучше поместить JLabel в контейнер с подходящим менеджером компоновки и задать для него размер.


Возвращаемое значение getPreferredSize() вычисляется автоматически, пока вы явно не зададите предпочтительный размер. После этого getPreferredSize() будет возвращен с этим конкретным размером. Если вы сбросите предпочтительный размер (установив его на null), автоматический размер снова будет доступен. В твоем случае:

label.setText("Text");
System.out.println(label.getPreferredSize().width); // 25
label.setPreferredSize(new Dimension(50, 20));
System.out.println(label.getPreferredSize().width); // 50
label.setText("New long text");
System.out.println(label.getPreferredSize().width); // 50
label.setPreferredSize(null);
System.out.println(label.getPreferredSize().width); // 77
person Dávid Horváth    schedule 19.08.2016