5

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?

Darius
  • 180
  • 1
  • 13
  • Are there any errors reported? – Brainbot Jul 13 '12 at 16:21
  • 2
    What do you mean by `crash`? Does it throw an exception? If yes, what is it? – Eng.Fouad Jul 13 '12 at 16:21
  • I mean Notepad app got frozen and wont respond to my manipulation. – Darius Jul 13 '12 at 16:23
  • If you are running your program from the command line, look at the output. If you're running in an IDE, look at your output tab. If not, enable the Java console in your system settings. – RustyTheBoyRobot Jul 13 '12 at 16:25
  • frozen ... take a Thread dump and see why it gets frozen. Also, is it just busy (100%CPU usage which could indicate an infinite loop) or simply dead-locked ? – Robin Jul 13 '12 at 16:28
  • 2
    is your code running on the event dispatch thread? – lbalazscs Jul 13 '12 at 16:32
  • @HovercraftFullOfEels the instanceof does not let a null value pass. @ Darius it does not work with the catch block, your program simply does not crash anymore since you are handling the Exception. But there shouldn't be an exception in the first place – Robin Jul 13 '12 at 16:36
  • I deleted my comment. He's calling this in the wrong place, perhaps before components have been rendered? Before calling `setVisible(true)` perhaps? – Hovercraft Full Of Eels Jul 13 '12 at 16:36
  • Or the Document might be null. It's somewhere down in the internals of the class, so it points to some bad setup. – RustyTheBoyRobot Jul 13 '12 at 16:37
  • Nope i call this after all initialisation it done. And it work in another thread, but thread start after all objects created.. – Darius Jul 13 '12 at 16:48
  • I think security manager make me nervous. – Darius Jul 13 '12 at 16:50

2 Answers2

4

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.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Ok i try to show all code but don't blame me) As i say its experiment. – Darius Jul 13 '12 at 17:01
  • +1 for the effort of posting runnable code, and showing that `setText` actually works :-) @Darius no, do not show all code. Post an [SSCCE](http://sscce.org) which demonstrates your problem. – Robin Jul 13 '12 at 17:05
2

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

Community
  • 1
  • 1
lbalazscs
  • 17,474
  • 7
  • 42
  • 50
  • According to the stack trace, this exception *is* coming from the event dispatch thread. – Nick Rippe Jul 13 '12 at 17:48
  • 1
    In the comments of the original question, he wrote: "And it work in another thread, but thread start after all objects created.. " – lbalazscs Jul 13 '12 at 18:05