2010-11-03 6 views
12

Во всех примерах, которые я могу найти, что использовать JTextArea, ширина высота & известна перед тем построения JTextArea, и если JTextArea потребуется больше высоты, то он помещается внутри JScrollPane. Очевидно, что высота JTextArea зависит от ширины и содержимого текста.Как создать JTextArea с указанной шириной и наименьшей возможной высотой, необходимой для отображения всего текста?

Теперь моя ситуация требует, чтобы я не использовал JScrollPane, но вместо этого, чтобы JTextArea был достаточно высок, чтобы отобразить весь текст. Когда я создаю JTextArea, я знаю содержание текста и сколько ширины ему придется работать; Я не знаю высоты - я хочу, чтобы это было как можно меньше, не отрезая ни одного текста. Это кажется очень трудным для достижения.

В качестве примечания стороны добавляется JTextArea к JPanel, у которого нет менеджера компоновки - он использует абсолютное позиционирование на основе предпочтительного размера добавленного компонента. Это требует, чтобы мой JTextArea вернул правильные размеры на getPreferredSize(). Правильные размеры должны быть той шириной, которую я предоставил, когда я ее построил, и минимальной высотой, необходимой для отображения всего текста с предоставленной шириной.

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

Надеюсь, мой вопрос ясен. Спасибо за вашу помощь!

+0

Будет ли JLabel вместо JTextArea? –

+0

@Andrew Thompson Конечно, я мог бы использовать 'JLabel', но тогда мне все равно придется вручную вставлять новые строки в строку, что потребует от меня вычислить, где они должны быть основаны на настройках ширины и шрифта, а затем я нужно добавить некоторую специальную обработку, чтобы она обернулась целыми словами, а не символами. Это вещи, предоставленные «JTextArea», поэтому я бы предпочел использовать это, если смогу. –

+0

См. Пример ниже. Мне нравится использовать небольшой «трюк HTML» для достижения таких вещей. ;) –

ответ

5

он использует абсолютное позиционирование на основе предпочтительного размера добавленного компонента.

Звучит как работа менеджера макета.

Это требует, чтобы мой JTextArea вернул правильные размеры на getPreferredSize().

JTextArea textArea = new JTextArea(); 
textArea.setLineWrap(true); 
textArea.setWrapStyleWord(true); 
textArea.setText("one two three four five six seven eight nine ten"); 
System.out.println("000: " + textArea.getPreferredSize()); 
textArea.setSize(100, 1); 
System.out.println("100: " + textArea.getPreferredSize()); 
textArea.setSize(textArea.getPreferredSize()); 
+0

Я не могу использовать диспетчер компоновки - я попробовал их всех и пришел к выводу, что использовать абсолютное позиционирование проще. Все, что я подразумевал под «... он использует абсолютное позиционирование, основанное на предпочтительном размере добавленного компонента», заключалось в том, что на этот метод полагаются, поэтому он должен быть правильным. –

+0

Ничего себе! Это работает! Спасибо огромное! Я никогда бы не подумал попробовать это. –

+0

Вы не должны использовать один маневр макета. Вы можете использовать вложенные панели с разными менеджерами макетов, чтобы выполнить работу. Опять же «определение позиции на основе предпочтительного размера компонента» - это, в точности, задача менеджера компоновки. Если вам не нравятся существующие менеджеры макетов, напишите их самостоятельно. Это то, что вы делаете в любом случае, за исключением случаев, когда вы реализуете интерфейс LayoutManager, у вас есть хорошо знакомый интерфейс для кода. – camickr

-1

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

Скажите, что ваш текст имеет 1000 символов, включая пробелы, а ширина символа эквивалентна 4 пикселям, тогда вы можете решить, будет ли ширина 400 символов в каждой строке, а затем вам понадобится 10 строк. Теперь скажите, что высота составляет 10 для размера шрифта, теперь вы знаете, что вам нужно 10 x 10 == 100 пикселей, поэтому ваш TextArea должен быть 400x100

+0

Этот подход не работает для шрифтов с фиксированной шириной. Дальнейшие проблемы возникают, когда слова завернуты, теряя часть конца строки. –

+0

Спасибо за ваш ответ, но, как указано, этот подход не совсем работает, если я хочу поддерживать шрифт с переменным размером (который мне нужен). Кроме того, это все вещи, предоставленные «JTextArea», поэтому я бы предпочел не изобретать колесо. –

5
import java.awt.*; 
import javax.swing.*; 

class FixedWidthLabel { 

    public static void main(String[] args) { 

     Runnable r = new Runnable() { 
      public void run() { 
       String pt1 = "<html><body width='"; 
       String pt2 = 
        "px'><h1>Label Height</h1>" + 
        "<p>Many Swing components support HTML 3.2 &amp;" + 
        " (simple) CSS. By setting a body width we can cause the " + 
        " component to find the natural height needed to display" + 
        " the component.<br><br>" + 
        "<p>The body width in this text is set to " + 
        ""; 
       String pt3 = 
        " pixels." + 
        ""; 

       JPanel p = new JPanel(new BorderLayout()); 

       JLabel l1 = new JLabel(pt1 + "125" + pt2 + "125" + pt3); 
       p.add(l1, BorderLayout.WEST); 

       JLabel l2 = new JLabel(pt1 + "200" + pt2 + "200" + pt3); 
       p.add(l2, BorderLayout.CENTER); 

       JOptionPane.showMessageDialog(null, p); 
      } 
     }; 
     SwingUtilities.invokeLater(r); 
    } 
} 
+0

AhhHh очень умный! Хорошая работа, и все, что требуется, это использовать тег body. –

0

Решение, описанное в FixedWidthLabel, используя <html><body width="..." потребует от программиста, чтобы обеспечить сообщение как часть HTML-строки.

Если сообщение что-то вроде invalid integer: i<0 not allowed, то < не должны быть экранированы (закодированы?), В противном случае это не знает, как JLabel будет интерпретировать HTML.

Это добавляет сложности этому решению.

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

+0

Или ... если вы кодируете их как HTML. –