2010-02-08 1 views
5

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

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 показан в первый раз (то есть, когда кнопка щелкнул один раз) это как-то, кажется, сообщить предпочтительную высоту, которая слишком мало (1):

first invocation

После последующих нажатий кнопок, макет просто, как можно было бы ожидать, что она (2):

subsequent invocations

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

ответ

11

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!"

+0

@finnw:. Отличное объяснение и обходные - Спасибо большое! – netzwerg

+1

Отличное решение, +1! Хотя это было немного времени, у меня есть еще один хороший вопрос для вас. Я пробовал такой же подход с JTextPane, это не что иное, как подкласс JEditorPane, Я пытаюсь углубиться (BasicTextUI), чтобы понять, где разница. Но, может быть, вы уже это знаете? :-) – AgostinoX