【问题标题】:Return control to an applet将控制权返回给小程序
【发布时间】:2013-05-14 21:57:16
【问题描述】:

我有一个 JApplet,它在“init”期间启动 JFrame。 该JFrame中有一些操作,最终用户关闭了该JFrame。

现在我想通过 javascript 通知浏览器有一些事情要做。

如何做到这一点? 如果只是小程序的话,下面这个简单的功能就足够了

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

但代码中的“this”指的是小程序对象,当我在 JFrame 中时,我不知道如何访问该对象。

JFrame 被调用如下以获得焦点:

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();
}
}

所以我的问题是:
1. 如何在 scanFrame 对象中调用 notifyBrowser()
2. 或者如何检测scanFrame已关闭并在applet对象中成功调用notifyBrowser?

感谢您的帮助。


所以修改后的代码是这样的:

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);
...

和扫描帧

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');}");
 }

我得到的错误:

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)

【问题讨论】:

  • 如需尽快获得更好的帮助,请发帖SSCCE

标签: java swing jframe japplet jsobject


【解决方案1】:
  • 如果您需要打开一个单独的窗口,请不要使用 JFrame。使用模态 JDialog,然后控制自动返回到调用代码。
  • 如果您需要将 JApplet 的引用传递给另一个类,只需将其作为构造函数的参数传递。

即,

ScanFrame scanFrame = new ScanFrame(this); 

this 代表 JApplet。

请注意,在 Swing 事件线程上调用 Thread.sleep(300L); 是一个非常糟糕的主意。如果您需要这样的延迟,请使用 Swing Timer,这样您就不会在睡眠期间关闭事件线程。


编辑
你说,

我只是复制了一些我在网上找到的东西,

这里要小心。复制想法而不是代码,以免遇到看不见的墙。

...但是我怀疑这不是要走的路,尽管直到现在我还没有通知任何问题,它解决了 JFrame 落后于浏览器窗口的问题。但问题是,当我通过这个传递applet 对象时,我如何调用它和我的函数notifyBrowser。我的 Netbeans 告诉我将 ScanFrame 构造函数更改为: public Sc​​anFrame(Runnable aThis)

您的 JApplet 类显然实现了 Runnable,但它也应该扩展 JApplet。请注意,NetBeans 的建议是出于对您计划的无知。 IDE 很聪明,但只有 如此 聪明。您更清楚构造函数参数应该是 JApplet,以便您可以在参数上调用 JApplet 方法。

public class ScanFrame {
   private JApplet myApplet;

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

现在您可以在 myApplet 字段上调用小程序方法。


编辑 2
啊,我的错,我忘了你是从匿名内部类调用构造函数。让我改变一些建议:

  • 首先重命名您的班级。 “Applet”已经是某个重要的核心 Java 类的名称,您不想使用它,因为这样做可能会混淆他人或您自己。假设您将其重命名为 ScanFrameApplet。
  • 然后要在匿名内部类中获取此小程序实例的this,您必须在this 前面加上类名,因此在我的实例中为ScanFrameApplet.this

即,

public class ScanFrameApplet extends JApplet {
  try {
    java.awt.EventQueue.invokeAndWait(new Runnable() {
    @Override
    public void run() {
        initComponents();
        ScanFrame scanFrame = new ScanFrame(ScanFrameApplet.this);

【讨论】:

  • 感谢您的 cmets。我只是复制了一些我在互联网上找到的东西,但我怀疑这不是要走的路,虽然直到现在我还没有通知任何问题,它解决了 JFrame 在浏览器窗口后面的问题。但问题是,当我通过这个传递applet 对象时,我如何调用它和我的函数notifyBrowser。我的 Netbeans 告诉我将 ScanFrame 构造函数更改为:public Sc​​anFrame(Runnable aThis)
  • 感谢您的回答。你当然是对的。我对 Java 很陌生,而且我经常迷失在寻找解决方案的过程中,因为我在这方面的知识(Java)是......让我们称之为分散的 ;-)。我尝试了您提出的建议,但由于我的错误,我尝试使用 Applet 而不是 JApplet(我知道,这是错误的)。现在,当谈到可运行时,Netbeans 将调用 this 标记为错误,但我找到了一种通过在 java.awt.EventQueue.invokeAndWait 之前创建私有局部变量 myApplet = this 来解决问题的方法...现在它几乎可以正常工作了......不幸的是有一个例外。
  • @norbi771:请参阅编辑 2
  • @Hovercraft:谢谢你们的 cmets。您对如何避免异常有任何想法吗?我可能会以不使用 JFrame 的方式重写这个组件,但现在我急于进行概念验证。有没有办法让 Netbeans 将 JFrame 转换为 JApplet?有一些生成的代码,我喜欢这些代码,因为我可以轻松地直观地设计表单。我的想法是从外部更改 .form 文件,但还没有尝试过。无论如何,我非常感谢您的 cmets,谢谢!
  • @Hovercraft:很好,我的 JFrame 上有 JPanel,谢谢,这是个好主意,我非常喜欢。
猜你喜欢
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 2015-05-17
相关资源
最近更新 更多