Заставьте высоту многострочного текста с фиксированной шириной заставлять диалоговое окно изменить размер правильно

Я хочу создать диалоговое окно, которое содержит некоторый текстовый элемент (JLabel/JTextArea и т.д.), который является много выровненный, и перенесите слова. Я хочу, чтобы диалоговое окно было фиксированной ширины, но адаптировать высоту в зависимости от того, насколько большой текст. У меня есть этот код:

import static javax.swing.GroupLayout.DEFAULT_SIZE;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class TextSizeProblem extends JFrame {
  public TextSizeProblem() {

    String dummyString = "";
    for (int i = 0; i < 100; i++) {
      dummyString += " word" + i;  //Create a long text
    }
    JLabel text = new JLabel();
    text.setText("" + dummyString + "");

    JButton packMeButton = new JButton("pack");
    packMeButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        pack();
      }
    });

    GroupLayout layout = new GroupLayout(this.getContentPane());
    getContentPane().setLayout(layout);
    layout.setVerticalGroup(layout.createParallelGroup()
        .addComponent(packMeButton)
        .addComponent(text)
    );
    layout.setHorizontalGroup(layout.createSequentialGroup()
        .addComponent(packMeButton)
        .addComponent(text, DEFAULT_SIZE, 400, 400) //Lock the width to 400
    );

    pack();
  }

  public static void main(String args[]) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JFrame frame = new TextSizeProblem();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
      }
    });
  }
}

При запущении программы это похоже на это: alt text
(источник: lesc.se)

Но я хотел бы, чтобы диалоговое окно было похоже на это (как тогда, когда Вы нажимаете кнопку пакета): alt text
(источник: lesc.se)

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

8
задан Glorfindel 20 July 2019 в 10:01
поделиться

2 ответа

Я нашел решение своей проблемы. Заменив JLabel на JTextArea:

 JTextArea text = new JTextArea ();
text.setText (dummyString);
text.setLineWrap (правда);
text.setWrapStyleWord (истина);

И вызов pack () с последующим вызовом диспетчера компоновки для повторной компоновки компонентов, за которым следует другой pack:

 pack ();
layout.invalidateLayout (this.getContentPane ());
pack ();

Это заставит диспетчер компоновки адаптироваться к ширине.

Полный код:

import static javax.swing.GroupLayout.DEFAULT_SIZE;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class TextSizeProblem3 extends JFrame {
  public TextSizeProblem3() {

    String dummyString = "";
    for (int i = 0; i < 100; i++) {
      dummyString += " word" + i;  //Create a long text
    }
    JTextArea text = new JTextArea();
    text.setText(dummyString);
    text.setLineWrap(true);
    text.setWrapStyleWord(true);

    JButton packMeButton = new JButton("pack");
    packMeButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        pack();
      }
    });

    GroupLayout layout = new GroupLayout(this.getContentPane());
    getContentPane().setLayout(layout);
    layout.setVerticalGroup(layout.createParallelGroup()
        .addComponent(packMeButton)
        .addComponent(text)
    );
    layout.setHorizontalGroup(layout.createSequentialGroup()
        .addComponent(packMeButton)
        .addComponent(text, DEFAULT_SIZE, 400, 400) //Lock the width to 400
    );

    pack();
    layout.invalidateLayout(this.getContentPane());
    pack();
  }

  public static void main(String args[]) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JFrame frame = new TextSizeProblem3();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
      }
    });
  }
}

(вы можете добавить некоторые настройки (границы, цвет и т. Д.), Чтобы он выглядел так же, как JLabel, но я пропустил это)

4
ответ дан 5 December 2019 в 08:54
поделиться

Вот адаптация вашего кода, делающая то, что вы хотите. Но для вычисления размера метки и установки ее предпочтительного размера требуется небольшая хитрость.

Я нашел решение здесь

import static javax.swing.GroupLayout.DEFAULT_SIZE;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.text.View;

public class TextSizeProblem extends JFrame {
    public TextSizeProblem() {

        String dummyString = "";
        for (int i = 0; i < 100; i++) {
            dummyString += " word" + i; // Create a long text
        }
        JLabel text = new JLabel();
        text.setText("<html>" + dummyString + "</html>");

        Dimension prefSize = getPreferredSize(text.getText(), true, 400);

        JButton packMeButton = new JButton("pack");
        packMeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                pack();
            }
        });



        GroupLayout layout = new GroupLayout(this.getContentPane());
        getContentPane().setLayout(layout);
        layout.setVerticalGroup(layout.createParallelGroup().addComponent(packMeButton)
                .addComponent(text,DEFAULT_SIZE, prefSize.height, prefSize.height));
        layout.setHorizontalGroup(layout.createSequentialGroup().addComponent(packMeButton)
                .addComponent(text, DEFAULT_SIZE, prefSize.width, prefSize.width) // Lock the width to 400
                );

        pack();
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new TextSizeProblem();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }

    private static final JLabel resizer = new JLabel();

    /**
     * Returns the preferred size to set a component at in order to render an html string. You can
     * specify the size of one dimension.
     */
    public static java.awt.Dimension getPreferredSize(String html, boolean width, int prefSize) {

        resizer.setText(html);

        View view = (View) resizer.getClientProperty(javax.swing.plaf.basic.BasicHTML.propertyKey);

        view.setSize(width ? prefSize : 0, width ? 0 : prefSize);

        float w = view.getPreferredSpan(View.X_AXIS);
        float h = view.getPreferredSpan(View.Y_AXIS);

        return new java.awt.Dimension((int) Math.ceil(w), (int) Math.ceil(h));
    }
}
10
ответ дан 5 December 2019 в 08:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: