Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JTextArea/JTextComponent setText causes crash

I am new to Java in general and in particular with the Swing library. When I experimented with the Notepad demo (standard demo from JDK), I got a crash when trying to change text in the editor window. My sample code:

void Filter(Component f){
  if (f instanceof JTextComponent){
    JTextComponent textComponent = (JTextComponent) f;
    textComponent.setVisible(false); //Works
    textComponent.setVisible(true); //Works
    textComponent.getText(); //Works
    textComponent.updateUI(); //Works
    textComponent.setText("Hello world!"); //Crashes
  }else{
    RecursiveGet(f);
  }
}
void RecursiveGet(Component c){
  for (Component f : ((JComponent) c).getComponents()) {
    if (f instanceof JComponent) {
      Filter(f);
    }
  }
}

I searched for instance JTextComponent, until I found it and then tested some methods. I think I am missing something, some details. My environment JDK 1.7, JRE 7.0, Win7 x64. I will be glad to have any help. Thank you.

Update I add Exception handler

void Filter(Component f){
        if (f instanceof JTextComponent){
            JTextComponent textComponent = (JTextComponent) f;
            textComponent.setVisible(false);  //Work
            textComponent.setVisible(true);  //Work
            textComponent.getText();  //Work
            textComponent.updateUI(); //Work
            try {
            textComponent.setText("Hello world!"); //Crash
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            RecursiveGet(f);
        }
    }

and get this..

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at javax.swing.plaf.synth.SynthContext.getPainter(Unknown Source)
        at javax.swing.plaf.synth.SynthTextAreaUI.update(Unknown Source)
        at javax.swing.JComponent.paintComponent(Unknown Source)
        at javax.swing.JComponent.paint(Unknown Source)
        at javax.swing.JComponent.paintChildren(Unknown Source)
        at javax.swing.JComponent.paint(Unknown Source)
        at javax.swing.JViewport.paint(Unknown Source)
        at javax.swing.JComponent.paintChildren(Unknown Source)
        at javax.swing.JComponent.paint(Unknown Source)
        at javax.swing.JComponent.paintChildren(Unknown Source)
        at javax.swing.JComponent.paint(Unknown Source)
        at javax.swing.JComponent.paintToOffscreen(Unknown Source)
        at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown S
ource)
        at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
        at javax.swing.RepaintManager.paint(Unknown Source)
        at javax.swing.JComponent._paintImmediately(Unknown Source)
        at javax.swing.JComponent.paintImmediately(Unknown Source)
        at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.access$700(Unknown Source)
        at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
        at java.awt.event.InvocationEvent.dispatch(Unknown Source)
        at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
        at java.awt.EventQueue.access$000(Unknown Source)
        at java.awt.EventQueue$3.run(Unknown Source)
        at java.awt.EventQueue$3.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Sour
ce)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)

Update 2 setText method work after add Exception handler block. But what i miss?

like image 477
Darius Avatar asked Jul 13 '12 16:07

Darius


2 Answers

This is not an answer, but a code post showing that your method, or a variant of it, one that allows the coder to change what text to post, works:

import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.text.*;

@SuppressWarnings("serial")
public class TestFilter extends JPanel {
   public TestFilter() {
      JPanel textFieldPanel = new JPanel(new GridLayout(0, 3));
      for (int i = 0; i < 15; i++) {
         textFieldPanel.add(new JTextField(10));
      }

      JPanel buttonPanel = new JPanel();
      buttonPanel.add(new JButton(new FilterAction("Show Text", "Hello World")));
      buttonPanel.add(new JButton(new FilterAction("Clear Text", "")));

      setLayout(new BorderLayout());
      add(textFieldPanel, BorderLayout.NORTH);
      add(new JScrollPane(new JTextArea(10, 15)));
      add(buttonPanel, BorderLayout.SOUTH);
   }

   private class FilterAction extends AbstractAction {
      private String text;

      public FilterAction(String name, String text) {
         super(name);
         this.text = text;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         filter(TestFilter.this, text);
      }
   }

   void filter(Component f, String text) {
      if (f instanceof JTextComponent) {
         JTextComponent textComponent = (JTextComponent) f;
         textComponent.setVisible(false); // Works
         textComponent.setVisible(true); // Works
         textComponent.getText(); // Works
         textComponent.updateUI(); // Works
         textComponent.setText(text); // Crashes
      } else {
         RecursiveGet(f, text);
      }
   }

   void RecursiveGet(Component c, String text) {
      for (Component f : ((JComponent) c).getComponents()) {
         if (f instanceof JComponent) {
            filter(f, text);
         }
      }
   }

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

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Thus the problem is likely how you're calling your method, something you haven't shown us yet.

like image 200
Hovercraft Full Of Eels Avatar answered Sep 28 '22 09:09

Hovercraft Full Of Eels


According to the comments on your original question,

"[...] it work[s] in another thread, but [the original] thread start[s] after all objects created.. "

All code that modifies a Swing component must run in the event dispatch thread. It is NOT enough if you wait until everything is created.

java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
        // modify swing components
    }
});

You might want to read this: Java Event-Dispatching Thread explanation

...and this: Java: Swing Libraries & Thread Safety

like image 28
lbalazscs Avatar answered Sep 28 '22 09:09

lbalazscs