Class JTextArea
A JTextArea is a multi-line area that displays plain text. It is intended to be a lightweight component that provides source compatibility with the java.awt.TextArea class where it can reasonably do so. You can find information and examples of using all the text components in Using Text Components, a section in The Java Tutorial.
This component has capabilities not found in the java.awt.TextArea class. The superclass should be consulted for additional capabilities. Alternative multi-line text classes with more capabilities are JTextPane and JEditorPane .
The java.awt.TextArea internally handles scrolling. JTextArea is different in that it doesn’t manage scrolling, but implements the swing Scrollable interface. This allows it to be placed inside a JScrollPane if scrolling behavior is desired, and used directly if scrolling is not desired.
The java.awt.TextArea has the ability to do line wrapping. This was controlled by the horizontal scrolling policy. Since scrolling is not done by JTextArea directly, backward compatibility must be provided another way. JTextArea has a bound property for line wrapping that controls whether or not it will wrap lines. By default, the line wrapping property is set to false (not wrapped).
java.awt.TextArea has two properties rows and columns that are used to determine the preferred size. JTextArea uses these properties to indicate the preferred size of the viewport when placed inside a JScrollPane to match the functionality provided by java.awt.TextArea . JTextArea has a preferred size of what is needed to display all of the text, so that it functions properly inside of a JScrollPane . If the value for rows or columns is equal to zero, the preferred size along that axis is used for the viewport preferred size along the same axis.
The java.awt.TextArea could be monitored for changes by adding a TextListener for TextEvent s. In the JTextComponent based components, changes are broadcasted from the model via a DocumentEvent to DocumentListeners . The DocumentEvent gives the location of the change and the kind of change if desired. The code fragment might look something like:
DocumentListener myListener = ??; JTextArea myArea = ??; myArea.getDocument().addDocumentListener(myListener);
Warning: Swing is not thread safe. For more information see Swing’s Threading Policy.
Warning: Serialized objects of this class will not be compatible with future Swing releases. The current serialization support is appropriate for short term storage or RMI between applications running the same version of Swing. As of 1.4, support for long term storage of all JavaBeans has been added to the java.beans package. Please see XMLEncoder .
Class JTextArea
A JTextArea is a multi-line area that displays plain text. It is intended to be a lightweight component that provides source compatibility with the java.awt.TextArea class where it can reasonably do so. You can find information and examples of using all the text components in Using Text Components, a section in The Java Tutorial.
This component has capabilities not found in the java.awt.TextArea class. The superclass should be consulted for additional capabilities. Alternative multi-line text classes with more capabilities are JTextPane and JEditorPane .
The java.awt.TextArea internally handles scrolling. JTextArea is different in that it doesn’t manage scrolling, but implements the swing Scrollable interface. This allows it to be placed inside a JScrollPane if scrolling behavior is desired, and used directly if scrolling is not desired.
The java.awt.TextArea has the ability to do line wrapping. This was controlled by the horizontal scrolling policy. Since scrolling is not done by JTextArea directly, backward compatibility must be provided another way. JTextArea has a bound property for line wrapping that controls whether or not it will wrap lines. By default, the line wrapping property is set to false (not wrapped).
java.awt.TextArea has two properties rows and columns that are used to determine the preferred size. JTextArea uses these properties to indicate the preferred size of the viewport when placed inside a JScrollPane to match the functionality provided by java.awt.TextArea . JTextArea has a preferred size of what is needed to display all of the text, so that it functions properly inside of a JScrollPane . If the value for rows or columns is equal to zero, the preferred size along that axis is used for the viewport preferred size along the same axis.
The java.awt.TextArea could be monitored for changes by adding a TextListener for TextEvent s. In the JTextComponent based components, changes are broadcasted from the model via a DocumentEvent to DocumentListeners . The DocumentEvent gives the location of the change and the kind of change if desired. The code fragment might look something like:
DocumentListener myListener = ??; JTextArea myArea = ??; myArea.getDocument().addDocumentListener(myListener);
Warning: Swing is not thread safe. For more information see Swing’s Threading Policy.
Warning: Serialized objects of this class will not be compatible with future Swing releases. The current serialization support is appropriate for short term storage or RMI between applications running the same version of Swing. As of 1.4, support for long term storage of all JavaBeans has been added to the java.beans package. Please see XMLEncoder .
How do I flush to Java’s JTextArea?
I am writing a GUI with a button. When the user clicks the button, I would like a «Beginning work. » message to appear in a JTextArea immediately, and a «Finished.» message to appear when the work is done. The GUI contains some code of the form
private void buttonActionPerformed(java.awt.event.ActionEvent evt) < myJTextArea.append("Beginning work. \n"); myJTextArea.append("Finished.\n"); >
Unfortunately, neither message appears until the end. Is there a way to flush messages to JTextArea? On another forum, I saw people mention running a separate thread for the JTextArea output. Would some solution based on that be possible? Thanks
2 Answers 2
Unfortunately, neither message appears until the end. Is there a way to flush messages to JTextArea? On another forum, I saw mention running a separate thread for the JTextArea output. Would some solution based on that be possible?
This has nothing to do with «flushing» the JTextArea, and all to do with making sure that your code follows Swing threading rules. The long running code that is outputting to the JTextArea should be called in a background thread such as with a SwingWorker. Then it would intermittently output its results to the JTextArea, but making sure to do so carefully on the Swing event thread. If you use a SwingWorker, this could be done using the publish/process method pair.
import java.util.List; import javax.swing.*; public class SwingThreadingEg extends JPanel implements MyAppendable < private JTextArea area = new JTextArea(30, 50); public SwingThreadingEg() < JScrollPane scrollPane = new JScrollPane(area); scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); add(scrollPane); >@Override public void append(String text) < area.append(text); >private static void createAndShowGui() < SwingThreadingEg mainPanel = new SwingThreadingEg(); MyWorker myWorker = new MyWorker(mainPanel); // add a Prop Change listener here to listen for // DONE state then call get() on myWorker myWorker.execute(); JFrame frame = new JFrame("SwingThreadingEg"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); >public static void main(String[] args) < SwingUtilities.invokeLater(new Runnable() < public void run() < createAndShowGui(); >>); > > class MyWorker extends SwingWorker < private static final long SLEEP_TIME = 500; private MyAppendable myAppendable; public MyWorker(MyAppendable myAppendable) < this.myAppendable = myAppendable; >@Override protected Void doInBackground() throws Exception < publish("Beginning Work"); // simulate some long-running task: for (int i = 0; i < 20; i++) < publish("From SwingWorker: " + i); Thread.sleep(SLEEP_TIME); >publish("Finished!"); return null; > @Override protected void process(List chunks) < for (String text : chunks) < myAppendable.append(text + "\n"); >> > interface MyAppendable
Code adapted from my code from an answer to a previous similar question.
Note, if you’re going to use a standard Runnable and a background Thread without a SwingWorker, as Lars recommends, you’ll first of all want to implement a Runnable and not extend Thread, and you must take care that most all Swing calls are queued onto the event thread, thus something like:
@Override public void actionPerformed(ActionEvent e) < textarea.append("Start. "); new Thread(new Runnable()< @Override public void run() < try < Thread.sleep(5000); >catch (InterruptedException e) < e.printStackTrace(); >SwingUtilities.invokeLater(new Runnable() < @Override public void run() < textarea.append("End"); >>); > >).start(); >
This looks a bit complicated what with all the nested anonymous inner classes, and in fact this is one of the main reasons why a SwingWorker may work better in this situation, since the code used is simpler, reducing the chances of creating unseen bugs.
Clear Appended Text from JTextArea
I am using a JTextArea to display an ArrayList by appending the entries to the area one at a time. However, when I use the method .setText(«») to clear all of the appended entries, they are not removed. Is there anyway to clear the text area?
If you are doing things properly, then setText(«») should work. Are you sure your aren’t doing everything in the main thread and so the GUI never gets a chance to update?
Your question is not clear. What do you want to remain within the JTextArea and what specifically do you want to remove? How do you decide that which should stay and that which should be removed?
And if you’re wishing to handle each ArrayList item as its own logical entry within the JTextArea, then perhaps a JTextArea is not what you really should be using, but rather a JList.
1 Answer 1
If you’re using a JTextArea, and you want to clear all entries after certain text has been entered, then simply store that originl pre-appended text in a String, say called myOriginalText . Rather than call .setText(«»); call .setText(myOriginalText) . Another option is to work directly with the JTextArea’s Document, getting the index value of the end of the original text, and then removing all text after that index within the Document.
import java.awt.BorderLayout; import java.awt.event.ActionEvent; import javax.swing.*; @SuppressWarnings("serial") public class TextAreaFun extends JPanel < private JTextArea textArea = new JTextArea(20, 40); private JTextField textEntry = new JTextField(25); private AppendAction appendAction = new AppendAction("Append Text"); private ProtectAction protectAction = new ProtectAction("Protect Text"); private ClearAction clearAction = new ClearAction("Clear Text"); private String protectedText = ""; public TextAreaFun() < textArea.setFocusable(false); textArea.setEditable(false); JScrollPane taScrollPane = new JScrollPane(textArea); taScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); textEntry.setAction(appendAction); JPanel bottomPanel = new JPanel(); bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS)); bottomPanel.add(textEntry); bottomPanel.add(new JButton(appendAction)); bottomPanel.add(new JButton(protectAction)); bottomPanel.add(new JButton(clearAction)); setLayout(new BorderLayout()); add(taScrollPane, BorderLayout.CENTER); add(bottomPanel, BorderLayout.PAGE_END); >private class AppendAction extends AbstractAction < public AppendAction(String name) < super(name); int mnemonic = (int) name.charAt(0); putValue(MNEMONIC_KEY, mnemonic); putValue(SHORT_DESCRIPTION, "Append text to text area"); >@Override public void actionPerformed(ActionEvent e) < textArea.append(textEntry.getText() + "\n"); textEntry.selectAll(); textEntry.requestFocusInWindow(); >> private class ProtectAction extends AbstractAction < public ProtectAction(String name) < super(name); int mnemonic = (int) name.charAt(0); putValue(MNEMONIC_KEY, mnemonic); putValue(SHORT_DESCRIPTION, "Protext text in text area from being cleared"); >@Override public void actionPerformed(ActionEvent e) < protectedText = textArea.getText(); textEntry.selectAll(); textEntry.requestFocusInWindow(); >> private class ClearAction extends AbstractAction < public ClearAction(String name) < super(name); int mnemonic = (int) name.charAt(0); putValue(MNEMONIC_KEY, mnemonic); putValue(SHORT_DESCRIPTION, "Clear unprotected text from text area"); >@Override public void actionPerformed(ActionEvent e) < textArea.setText(protectedText); textEntry.selectAll(); textEntry.requestFocusInWindow(); >> private static void createAndShowGui() < TextAreaFun mainPanel = new TextAreaFun(); JFrame frame = new JFrame("Text Area Fun"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); >public static void main(String[] args) < SwingUtilities.invokeLater(() ->createAndShowGui()); > >
If each item within the ArrayList is to be added or removed depending on the state of the program, then perhaps you’re likely better off not displaying the text within a JTextArea but rather a JList where you can handle each item within the JList independently.