1

I have an JApplet which during "init" starts JFrame. There are some operations in that JFrame and user closes the JFrame finally.

Now I'd like to notify the browser via javascript that something is to be done.

How to accomplish that? If it was the applet alone, the simple function below would be good enough

public void notifyBrowser() {
 JSObject browserWindow = JSObject.getWindow(this);
 browserWindow.eval("try{RefreshFilesInLongue();}catch(e){alert('error');}");
}

but "this" in the code is referring to the applet object, and I don't know how to reach that object while I am in the JFrame.

JFrame is called like below in order to receive focus:

public void init() {
 paramPostUrl = this.getParameter("postUrl");

/* Create and display the applet */
try {
    java.awt.EventQueue.invokeAndWait(new Runnable() {
    public void run() {
        initComponents();

        ScanFrame scanFrame = new ScanFrame();
        scanFrame.setPostUrl(paramPostUrl);
        scanFrame.setVisible(true);
        try {
        Thread.sleep(300L);
        scanFrame.toFront();
        } catch (InterruptedException ex) {
        Logger.getLogger(Applet.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    });
} catch (Exception ex) {
    ex.printStackTrace();
}
}

So my questions are:
1. how can I call notifyBrowser(), while being in scanFrame object
2. or how to detect that scanFrame was closed and being in applet object successfully call notifyBrowser?

Thanks for your help.


So modified code is like that:

public class Applet extends javax.swing.JApplet {
...
public void init() {
paramPostUrl = this.getParameter("postUrl");
myApplet = this;

/* Create and display the applet */
try {
    java.awt.EventQueue.invokeAndWait(new Runnable() {
    @Override
    public void run() {
        initComponents();
        ScanFrame scanFrame = new ScanFrame(myApplet);
...

and ScanFrame

public class ScanFrame extends javax.swing.JFrame implements ScannerListener {
 ...
 private JApplet appletObj;

 public ScanFrame(JApplet myApplet) {
appletObj = myApplet;
 ....

private void sendScannedDocumentToCallingApp() {
 ....
  JSObject browserWindow;
  browserWindow = JSObject.getWindow((JApplet)appletObj);
  browserWindow.eval("try{RefreshFilesInLongue();}catch(e){alert('error');}");
 }

and the error I get:

Exception in thread "AWT-EventQueue-2" java.util.NoSuchElementException
    at java.util.LinkedList.getFirst(Unknown Source)
    at java.awt.SequencedEvent.getFirst(Unknown Source)
    at java.awt.SequencedEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(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 Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    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)
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
norbi771
  • 814
  • 2
  • 12
  • 29

1 Answers1

3
  • If you need to open a separate window, don't use a JFrame. Use a modal JDialog, and then control returns automatically to the calling code.
  • If you need to pass the JApplet's reference into another class, simply pass it in as a parameter of the constructor.

i.e.,

ScanFrame scanFrame = new ScanFrame(this); 

where this represents the JApplet.

Note that calling Thread.sleep(300L); on the Swing event thread is a very bad idea. If you need a delay like this, use a Swing Timer so you don't shut down the event thread during the sleep.


Edit
You state,

I just copied some stuff I found in the Internet,

Be careful here. Copy ideas but not code lest you run into unseen walls.

...but I suspected it was not the way to go, although I didn't notify any problems with that until now and it solved the issue of the JFrame going behind the browser window. But the question is, when I pass the applet object via this, how can I call it and my function notifyBrowser. My Netbeans told me to change ScanFrame constructor to something like this: public ScanFrame(Runnable aThis)

Your JApplet class apparently implements Runnable but it also should extend JApplet. Note that the NetBeans suggestion is done out of ignorance of your plans. An IDE is smart, but only so smart. You know better that the constructor parameter should be a JApplet so that you can call JApplet methods on the parameter.

public class ScanFrame {
   private JApplet myApplet;

   public ScanFrame(JApplet myApplet) {
     this.myApplet = myApplet;
     // .... etc...
   }
}

and now you can call applet methods on the myApplet field.


Edit 2
Ah, my bad, I forgot that you were calling the constructor from an anonymous inner class. Let me change some recommendations:

  • First rename your class. "Applet" is already a name for a core Java class of some importance, and you don't want to use it as you may confuse others or yourself by doing this. Let's say you rename it to ScanFrameApplet.
  • Then to get the this of the instance of this applet inside of an anonymous inner class, you must preface the this with the class name, so in my instance it would be ScanFrameApplet.this.

i.e.,

public class ScanFrameApplet extends JApplet {
  try {
    java.awt.EventQueue.invokeAndWait(new Runnable() {
    @Override
    public void run() {
        initComponents();
        ScanFrame scanFrame = new ScanFrame(ScanFrameApplet.this);
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Thanks for your comments. I just copied some stuff I found in the Internet, but I suspected it was not the way to go, although I didn't notify any problems with that until now and it solved the issue of the JFrame going behind the browser window. But the question is, when I pass the applet object via this, how can I call it and my function notifyBrowser. My Netbeans told me to change ScanFrame constructor to something like this: public ScanFrame(Runnable aThis) – norbi771 May 14 '13 at 22:24
  • Thank you for your answer. Of course you are right. I am pretty new to Java and I am pretty often lost looking for solution, because my knowledge in that matter (Java) is ... lets call it scattered ;-). I tried what you've proposed but for my mistake I tried to use Applet not JApplet (I know, it was wrong). Now when it comes to runnable, Netbeans marked calling *this* as an error, but I found a way to get round by creating private local variable myApplet = this, before java.awt.EventQueue.invokeAndWait ... and now it is working almost fine ... unfortunately there is an exception. – norbi771 May 14 '13 at 22:56
  • @norbi771: please see **Edit 2** – Hovercraft Full Of Eels May 15 '13 at 01:09
  • @Hovercraft: Thank you for your comments. Do you have any ideas on how to avoid exception? I will probably rewrite this component in the way that JFrame will not be used at, but now I am in a hurry to have working proof of concept. Is there a way to have Netbeans convert JFrame to JApplet? There is some generated code, which I like because I can easily visually design the form. My idea is to change the .form file externally but haven't tried it yet. Anyway I deeply appreciate your comments, thank you! – norbi771 May 15 '13 at 09:54
  • @norbi771: you could extract the JFrame's contentPane and put it into a JApplet as its contentPane, but better to avoid having classes extend JFrame and the like. Better to write classes to *produce* JPanels, components that can be added to JFrames or JApplets when needed. – Hovercraft Full Of Eels May 15 '13 at 13:46
  • 1
    @Hovercraft: Good point, I have JPanels on my JFrame, thanks, this is good idea, I like it very much. – norbi771 May 15 '13 at 15:52