开发者

automatic dynamic expansion / contraction of JTextArea in Java

开发者 https://www.devze.com 2023-03-04 07:28 出处:网络
I start off by creating a JTextArea of a specific size. The user can add text within it but it will get cut off if it becomes too long (vertically or开发者_如何转开发 horizontally). I want the JTextAr

I start off by creating a JTextArea of a specific size. The user can add text within it but it will get cut off if it becomes too long (vertically or开发者_如何转开发 horizontally). I want the JTextArea to automatically expand or contract (for deletion of text).

I may allow users to change font and font size in the future, so it would be good if I could avoid making things increase/decrease by a certain size.

I am currently using bounds to size my JTextArea. Perhaps I should size by rows and columns and use a listener and act appropriately?

thanks in advance!


I can't imagine why you'd want to do this, why not put a JTextArea in a JScrollPane, but ok, i'll play along... Maybe something like this:

import java.awt.Container;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;


public class Expander extends JFrame {

    private final JTextArea area;
    private int hSize = 1;
    private int vSize = 1;

    public Expander() {
        Container cp = getContentPane();
        cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS));

        cp.add(Box.createHorizontalGlue());
        area = new JTextArea(vSize, hSize);
        cp.add(area);
        cp.add(Box.createHorizontalGlue());

        area.getDocument().addDocumentListener(new DocumentListener() {

            @Override
            public void insertUpdate(DocumentEvent e) {
                adjust();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                adjust();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                adjust();
            }
        });

        pack();
    }

    private void adjust() {
        int maxColumns = getMaxColumns();
        if ((area.getLineCount() != vSize) || (maxColumns != hSize)) {
            hSize = maxColumns;
            vSize = area.getLineCount();
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    area.setColumns(hSize);
                    area.setRows(vSize);
                    Expander.this.doLayout();
                    Expander.this.pack();
                }
            });
        }
    }

    private int getMaxColumns() {
        int startOffset = 0;
        int maxColumns = 0;
        for (int i = 0; i < area.getLineCount(); i++) {
            try {
                int endOffset = area.getLineEndOffset(i);
                int lineSize = endOffset - startOffset;
                if (lineSize > maxColumns) {
                    maxColumns = lineSize;
                }
                startOffset = endOffset;
            } catch (BadLocationException ble) {
            }
        }

        return maxColumns;
    }

    public static void main(String[] args) {

        Expander e = new Expander();
        e.setLocationRelativeTo(null);
        e.setVisible(true);
    }
}


I second the advice to simply put the JTextArea in a JScrollPane and let this take care of extra text. Also and perhaps most importantly, don't set the bounds of the JTextArea because if you do this, you constrain it to be a certain size and that's not what you want to have happen. Instead initialize your JTextArea with two int constants to represent the number of rows and columns that should be visualized and then place it in a JScrollPane. Also be sure to read up on using the layout managers so you can avoid setting the size of your JScrollPane too!

Edit: on testing, it seems that setPreferredSize is more dangerous to a JTextArea than setSize.

import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.*;

public class ConstrainedTextArea extends JPanel {
   private JTextArea textArea1, textArea2, textArea3;

   public ConstrainedTextArea() {
      textArea1 = new JTextArea(20, 30);
      textArea2 = new JTextArea();
      textArea3 = new JTextArea();

      textArea2.setPreferredSize(new Dimension(300, 300));
      textArea3.setSize(textArea3.getPreferredSize());

      setLayout(new GridLayout(1, 0));
      add(new JScrollPane(textArea1));
      add(new JScrollPane(textArea2));
      add(new JScrollPane(textArea3));
   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("ConstrainedTextArea");
      frame.getContentPane().add(new ConstrainedTextArea());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}


also, see GrowingTextAreaExample

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号