Управление предпочтительным размером JEditorPane с длинным текстом - PullRequest
5 голосов
/ 08 февраля 2010

У меня есть JEditorPane, который отображается внутри всплывающего окна, запускаемого с помощью кнопки. Панель содержит длинный текст, поэтому она вложена в JScrollPane, а максимальный размер всплывающего окна ограничен 300 x 100:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            String text = "Potentially looooooong text. " + 
                "Lorem ipsum dolor sit amet, consectetuer" +
                "adipiscing elit, sed diam nonummy nibh euismod " +
                "tincidunt ut laoreet dolore magna aliquam" + 
                "adipiscing elit, sed diam nonummy nibh euismod" + 
                "erat volutpat. Ut wisi enim ad minim veniam, " + 
                "quis nostrud exerci tation.";

            final JEditorPane editorPane = new JEditorPane("text/html", text);
            editorPane.setEditable(false);

            final JButton button = new JButton("Trigger Popup");
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JPopupMenu popup = new JPopupMenu();
                    popup.setLayout(new BorderLayout());
                    popup.add(new JScrollPane(editorPane));
                    Dimension d = popup.getPreferredSize();
                    int w = Math.min(300, d.width);
                    int h = Math.min(100, d.height);
                    popup.setPopupSize(w, h);
                    Dimension s = button.getSize();
                    popup.show(button, s.width / 2, s.height / 2);
                }
            });

            JFrame f = new JFrame("Layout Demo");
            f.setSize(200, 200);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setLocationRelativeTo(null);
            f.getContentPane().add(button);
            f.setVisible(true);
        }
    });
}

Когда экземпляр JEditorPane отображается впервые (то есть, когда кнопка нажата один раз), он каким-то образом сообщает о предпочтительной высоте, которая слишком мала

first invocation

После последующих нажатий кнопок макет соответствует ожидаемому (2) :

subsequent invocations

Как заставить / наложить правильный предпочтительный размер, чтобы всегда инициализировался как (2)?

1 Ответ

11 голосов
/ 08 февраля 2010

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

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

На втором проходе ширина уже была установлена ​​(ограничена размером первого JPopupMenu), и теперь, когда она знает максимальную ширину, она может вычислить, какой высоты она должна быть.

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

String text = "Potentially looooooong text. " + 
    "Lorem ipsum dolor sit amet, consectetuer" +
    "adipiscing elit, sed diam nonummy nibh euismod " +
    "tincidunt ut laoreet dolore magna aliquam" + 
    "adipiscing elit, sed diam nonummy nibh euismod" + 
    "erat volutpat. Ut wisi enim ad minim veniam, " + 
    "quis nostrud exerci tation.";

final JEditorPane editorPane = new JEditorPane("text/html", text);
editorPane.setSize(300, Integer.MAX_VALUE);
editorPane.setEditable(false);

Не беспокойтесь о том, чтобы сделать его слишком большим, он все равно будет уменьшаться, чтобы соответствовать содержанию (как вы увидите, если вы измените текст на "Hello, World!".

...