Solved

Assigning appletContext to an applet

Posted on 1998-11-25
7
311 Views
Last Modified: 2013-11-23
I have been working on making an applet that runs other applets.  Everything works with most applets, but an applet which uses the getGraphics() method returns a null pointer exception.  I believe, as someone suggested, I just need to assign the parent appletContext to the instance of the applet, but for some reason I have not been able to get that to work.  This is essentially the part of the code I use to instantiate and run an applet:
  the_frame = new Frame();
  the_app.init();
  the_frame.add(the_app);
  the_frame.setSize(width,height);
  the_frame.show();
  the_app.start();
Exactly how can I can assign appletContext to this, and do I need to do any extra implements, import, or extends commands for my class?  Will this allow me to use getGraphics() with the applets it runs?

Thanks a lot.
0
Comment
Question by:cms6204
  • 3
  • 3
7 Comments
 
LVL 5

Accepted Solution

by:
msmolyak earned 70 total points
Comment Utility
To get an applet context you call applet.getAppletContext(). Thus if you override this method of your applet class you will allow interested parties to get a hold of applet's context.Solving th eproblem with getGraphics depends upon whether it uses the applet context and if yes, then how. To figure that out create a class MyAppletContext which implements AppletContext. Each method of that class will print its name (besides doing something useful). Override the getAppletContext() method of your subclass of Applet class to return an instance of MyAppletContext class. When you call getGraphics() you will know if any of the method of your applet context are used by the presence or abcense of printed information.
0
 
LVL 16

Expert Comment

by:heyhey_
Comment Utility
"getGraphics returns null" is probably because applet peer is not created / initialized at the moment (so your applet don't have associated Graphics object). you probably must create Applet, add it to Frame, show it (peers are created) and then call its init method ... (just a quick suggestion)
0
 
LVL 16

Expert Comment

by:heyhey_
Comment Utility
and when exactly getGraphics() returns null. Give us the stacktrace (+ the source code of the "bad applet")

0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:cms6204
Comment Utility
Here is the method which runs the applets.  In the real version, the applets are in a linked list so that we can intercept each one's windowClosing message and destroy them when the user clicks on the close box (multiple applets can be run at once), but I have made it simpler here.  As it is coded below, it correctly runs any applet (that we have tested) that does not call getGraphics(), but when an applet does call getGraphics(), it gives the following errors (Bouncing_Ball2 code is at end of this comment):
  java.lang.NullPointerException
     at Ball.draw_ball(Bouncing_Ball2.java:101)
     at Ball.bounce(Bouncing_Ball2.java:109)
     at Bouncing_Ball2.star(Bouncing_Ball2.java:21)              atAppletViewDynamicBeta2.runApp                                         (AppletViewDynamicBeta2.java:332)
     at AppletViewDynamicBeta2.actionPerformed(Compiled Code)
as well as errors in java.awt

  public void runApp(){
      boolean appletFound=true;
      Applet app = new Applet();
      try {
        Class c = Class.forName(app_to_run);
        app = (Applet) Class.forName(app_to_run).newInstance();
      } // end of try
      // if no applet class can be instantiated, assign an error
      // message and return to user-input paint method
      catch (Exception e) {
        error = "No applet with this name found.";
        appletFound=false;
        repaint();
      } // end of catch
      if (appletFound) {
        Frame fr=new Frame();
        app.init();
        fr.add(app);
        fr.setSize(width,height);
        fr.show();
        app.start();
      } // end of if
      // be processed
  } // end of runApp()

If I move the app.init() line to between fr.show() and app.start(), it gives no errors with either program, but components, such as buttons and textfields, will either not appear or not work.  Thanks a lot for your help.  If you can help, I may accept msmolyak's answer, but I can post a "dummie" question for you so you can get some points for your efforts.  Here is Bouncing_Ball2 (it is threaded):

import java.applet.Applet;
import java.awt.*;

public class Bouncing_Ball2 extends Applet {
  private final int SIZE = 300;
  private Ball ball = new Ball(150, 10, 250, 200);
  private Graphics page;
  private Control_Panel controls;
  public void init() {
    setVisible(true);
    setSize(SIZE,SIZE);
    page = getGraphics();
    page.setXORMode(getBackground());
  }
  public void start() {
    controls = new Control_Panel(Thread.currentThread());
    controls.start();
    ball.pause();
    while(ball.moving()) {
      ball.bounce(page);
    }
  }
}

class Control_Panel extends Thread {
  private Button suspend = new Button("suspend");
  private Button resume = new Button("resume");
  private Frame frame = new Frame("Bouncing Ball Control Panel");
  private Thread applet_thread;
  Control_Panel(Thread applet_thread) {
    this.applet_thread = applet_thread;
  }
  public void run() {
    Resume_Action resume_action = new Resume_Action(applet_thread);
    Suspend_Action suspend_action = new Suspend_Action(applet_thread);
    suspend.addActionListener(suspend_action);
    resume.addActionListener(resume_action);
    frame.setLayout(new FlowLayout());
    frame.add(suspend);
    frame.add(resume);
    frame.pack();
    frame.setLocation(250, 200);
    frame.setVisible(true);
  }
}

class Suspend_Action implements ActionListener {
  Thread applet_thread;
  Suspend_Action(Thread applet_thread) {
    this.applet_thread = applet_thread;
  }
  public void actionPerformed(ActionEvent action) {
    applet_thread.suspend();
  }
}

class Resume_Action implements ActionListener {
  Thread applet_thread;
  Resume_Action(Thread applet_thread) {
    this.applet_thread = applet_thread;
  }
  public void actionPerformed(ActionEvent action) {
    applet_thread.resume();
  }
}

class Ball {
  private final int MOVE = 2;
  private final float DISTANCE = 0.97f;
  private final int SIZE = 20;
  private final int PAUSE = 5;
  private int x;
  private int start_y;
  private int end_y;
  private int length;
  private boolean moving_up = true;
  Ball(int new_x, int new_start_y, int new_end_y, int new_length) {
    x = new_x;
    start_y = new_start_y;
    end_y = new_end_y;
    length = new_length;
  }
  public void pause() {
    try {
      Thread.currentThread().sleep(PAUSE);
    }
    catch (InterruptedException exception) {
      System.out.println("have an exception");
    }
  }
  void move() {
    if (moving_up) {
      end_y = end_y - MOVE;
    }
    else {
      end_y = end_y + MOVE;
    }
  }
  void draw_ball (Graphics page) {
    page.drawOval (x-(SIZE/2), end_y, SIZE, SIZE);
    page.drawLine (x, start_y, x, end_y);
  }
  public boolean moving() {
    return length != 0;
  }
  public void bounce(Graphics page) {
    for (int count = 1; count < length; count+=MOVE) {
      draw_ball(page);
      pause();
      draw_ball(page);
      move();
    }
    moving_up = !moving_up;
    length = (int) (DISTANCE * length);
  }
}




0
 
LVL 16

Expert Comment

by:heyhey_
Comment Utility

 /*
the real answer is - you don't have problems with the "visualizator" applet,
but with applets that use getGraphics, because THEY DON'T BEHAVE properly !!!
so this is not an AppletContext problem, but a Graphics one.
*/

/*
getGraphics is a pretty tricky method and applets (and all other java components) are not supposed to use it at all
(you can search through java.* sources and see that NOBODY, NOWHERE uses this method directly !!!)

applets are supposed to draw themselves only in their update / paint methods (and there they receive the appropriate Graphics object as method invocation parameter)

i think that
- (for your own applets) you should always NOT use getGraphics. you should make the appropriate change, call repaint and
JVM will call your paint method with the appropriate Graphics object.
- (for your own applets) you should always use SAFE coding - for example

public void paint(Graphics g)
{
      if (g == null) return; // paranoia :)
      if (img == null) return; // safe !!
      g.drawImage(img);
}

- using getGraphics() will probably bring many refresh problems. for example suspend your ball, and bring some other Frame in front of the applet window. when you move this window, Ball will not repaint itself !!!

- from the docs
 public void paint(Graphics g)
    Paints this component. This method is called when the contents of the component should be
    painted in response to the component first being shown or damage needing repair. The clip
    rectangle in the Graphics parameter will be set to the area which needs to be painted.

 public Graphics getGraphics()
    Creates a graphics context for this component. This method will return null if this component
    is currently not on the screen.

so you will receive graphics object only after you've already showed your component
(that is - when the native peer is already created)

look at the source of getGraphics method

     public Graphics getGraphics() {
      if (peer instanceof java.awt.peer.LightweightPeer) {
          // This is for a lightweight component, need to
          // translate coordinate spaces and clip relative
          // to the parent.
          Graphics g = parent.getGraphics();
          g.translate(x,y);
          g.setClip(0, 0, width, height);
            g.setFont(getFont());
          return g;
      } else {
          ComponentPeer peer = this.peer;
          return (peer != null) ? peer.getGraphics() : null;
      }
    }

Summary:
1.) never use .getGraphics method and never KEEP the returned Graphics object !!! (this is a really bad practice)
2.) if you really need this to work with this "VERY BAD behaved applet", you certainty need to call the fr.show()
method before app.init() method (so that all the peer objects are created and you have the peer Graphics)
3.) i'm posting modified version of the applet code that paints itself only in its paint method. it works in appletviewer and it should work in your frame too

hope this helps
  heyhey
 */

import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;

 public class Bouncing_Ball2 extends Applet {
   private final int SIZE = 300;
   private Ball ball = new Ball(150, 10, 250, 200);
//   private Graphics page;
   private Control_Panel controls;
   public void init() {
     setVisible(true);
     setSize(SIZE,SIZE);
//     page = getGraphics();
//     page.setXORMode(getBackground());
   }

   public void paint(Graphics g) {

     //controls = new Control_Panel(Thread.currentThread());
       ball.draw_ball(g);


       }


   public void start() {
     controls = new Control_Panel(Thread.currentThread());
     controls.start();
     ball.pause();
     while(ball.moving()) {
       ball.bounce();
     }
   }

 class Control_Panel extends Thread {
   private Button suspend = new Button("suspend");
   private Button resume = new Button("resume");
   private Frame frame = new Frame("Bouncing Ball Control Panel");
   private Thread applet_thread;
   Control_Panel(Thread applet_thread) {
     this.applet_thread = applet_thread;
   }
   public void run() {
     Resume_Action resume_action = new Resume_Action(applet_thread);
     Suspend_Action suspend_action = new Suspend_Action(applet_thread);
     suspend.addActionListener(suspend_action);
     resume.addActionListener(resume_action);
     frame.setLayout(new FlowLayout());
     frame.add(suspend);
     frame.add(resume);
     frame.pack();
     frame.setLocation(250, 200);
     frame.setVisible(true);
   }
 }

 class Suspend_Action implements ActionListener {
   Thread applet_thread;
   Suspend_Action(Thread applet_thread) {
     this.applet_thread = applet_thread;
   }
   public void actionPerformed(ActionEvent action) {
     applet_thread.suspend();
   }
 }

 class Resume_Action implements ActionListener {
   Thread applet_thread;
   Resume_Action(Thread applet_thread) {
     this.applet_thread = applet_thread;
   }
   public void actionPerformed(ActionEvent action) {
     applet_thread.resume();
   }
 }

 class Ball {
   private final int MOVE = 2;
   private final float DISTANCE = 0.97f;
   private final int SIZE = 20;
   private final int PAUSE = 5;
   private int x;
   private int start_y;
   private int end_y;
   private int length;
   private boolean moving_up = true;
   Ball(int new_x, int new_start_y, int new_end_y, int new_length) {
     x = new_x;
     start_y = new_start_y;
     end_y = new_end_y;
     length = new_length;
   }
   public void pause() {
     try {
       Thread.currentThread().sleep(PAUSE);
     }
     catch (InterruptedException exception) {
       System.out.println("have an exception");
     }
   }
   void move() {
     if (moving_up) {
       end_y = end_y - MOVE;
     }
     else {
       end_y = end_y + MOVE;
     }
   }
   void draw_ball (Graphics page) {
     page.drawOval (x-(SIZE/2), end_y, SIZE, SIZE);
     page.drawLine (x, start_y, x, end_y);
   }
   public boolean moving() {
     return length != 0;
   }
   public void bounce() {
     for (int count = 1; count < length; count+=MOVE) {
       //draw_ball(page);
         repaint();
       pause();
       //draw_ball(page);
         repaint();
       move();
     }
     moving_up = !moving_up;
     length = (int) (DISTANCE * length);
   }
 }
 }

0
 

Author Comment

by:cms6204
Comment Utility
Thanks for your help heyhey_;  I think I have everything working the way it needs to now.  I'm posting another "dummie" question for you to answer so I can give you some of the points you deserve for helping me with your comments on this one.  It's titled "AppletViewer (for heyhey_)".  
0
 

Author Comment

by:cms6204
Comment Utility
msmolyak, sorry it took me so long to respond;  I wanted to keep my question active for a while because I also got a lot of valuable help from someone else's comments.  I think I have everything working as it needs to now.  Thanks.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
countHi challenge 25 84
eclipse compiler vs Installed JREs option 3 35
Java Jpanels and Jframe 8 19
github account with ecipse 1 15
Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now