Archived

This topic is now archived and is closed to further replies.

Tac-Tics

[java] Applets aren't working.

Recommended Posts

Hi. I''ve been having this problem for a while now and I can''t figure it out.My applet runs fine on appletviewer.exe and the first time on webpages, but when I reload the applet, it screws up really bad. Does anyone know why this happens? If you need any more information about my program, I''ll add it.

Share this post


Link to post
Share on other sites
My hunch tells me that you are spawning a thread from within your applet and when the applet stops this thread is not getting killed eating your JVM resources.

Maybe I am totally wrong!!

Would you elaborate more on the problem.

Regards,
IDispatch

Share this post


Link to post
Share on other sites
Try changing your init() to start() (I''m not sure if its start() or Start()). Init() is run when the applet is started for the first time, and start() is run when the applet is started for the first time AND every time you go back to your applet in a browser.

Share this post


Link to post
Share on other sites
OK, I finally got around to testing my program a little more. Sry for the delay. I tried to create a much simpler applet based off of an example in a book I have and it still is acting funny-like. Here''s the two main source files:


  
import javax.swing.*;
import lifegen.*;

public
class LifeGenApplet
extends JApplet
{
private Thread gameThread;
private LifeGen game;

public void init ()
{
game = null;
gameThread = null;
}

public void start ()
{
if (gameThread == null)
{
game = new LifeGen(30, this);
gameThread = new Thread(game);
gameThread.start();
}
}

public void stop ()
{
gameThread = null;
game = null;
}

}



  
package lifegen;

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public
class LifeGen
extends JPanel
implements Runnable
{
private JApplet applet;
private GameHandler game;

private Image buffer;
private Graphics bufferGraphics;
private boolean readyToPaint;

private Grid currentGrid;

static
private int cellSize;

static
private int gameSize;

public LifeGen (int size, JApplet applet)
{
this.applet = applet;
readyToPaint = false;

gameSize = size;

Dimension d = applet.getSize();
cellSize = (int) ( (double) (d.width - 10) / (double) (gameSize) );
applet.getContentPane().add(this);
}

public void run ()
{

currentGrid = Grid.getRandGrid(40);
// loadVirusMap();


game = new GameHandler(this);
readyToPaint = true;
}

public void loadVirusMap ()
{
currentGrid = new Grid(getGameSize(), getGameSize() );

int emptyLine = 0;
for (int row = 0; row < getGameSize(); row++)
{
if (emptyLine != 0)
{
for (int col = 1; col < getGameSize(); col += 3)
{
currentGrid.addCell(new Cell(row, col, currentGrid, Color.BLUE) );
try
{
currentGrid.addCell(new Cell(row, col + 1, currentGrid, Color.BLUE) );
}
catch (ArrayIndexOutOfBoundsException arrrg)
{
}
}
}

emptyLine++;

if (emptyLine > 2)
emptyLine = 0;

}
currentGrid.addCell(new Cell(3, 1, currentGrid, Color.RED) );
}

static
public int getCellSize ()
{
return (cellSize);
}

static
public int getGameSize ()
{
return (gameSize);
}

public void stop ()
{
if (game != null)
game.stop();
}

public void paintComponent (Graphics g)
{
if (readyToPaint)
{
Dimension d = applet.getSize();
buffer = applet.createImage(d.height, d.width);
bufferGraphics = buffer.getGraphics();
currentGrid.render(bufferGraphics);

drawGeneration(bufferGraphics);

g.drawImage(buffer, 0, 0, null);
}
}

public void drawGeneration (Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Rectangle2D box = new Rectangle2D.Double(0, gameSize * cellSize, 120, 20);
g2.setPaint(Color.BLACK);
g2.fill(box);
g2.draw(box);
g2.setPaint(Color.WHITE);
g2.drawString("Generation: " + GameHandler.getGeneration(), 15, gameSize * cellSize + 15);
}

public GameHandler getGameHandler ()
{
return (game);
}

public Grid getCurrentGrid ()
{
return (currentGrid);
}

public void setGrid (Grid g)
{
currentGrid = g;
}
}


It runs fine until you press F5 and reload the browser... Then the new date and old date get stacked up on top of each other and if you reload it over and over, the date becomes unintelligible. Can anyone help me here?

Just as a side note. Earlier, I wasn''t messing with Threads in the program and I just had a stop method that *supposedly* stopped the program by simply rendering all important objects to null, but it didn''t work. Please excuse me for my sloppy, poorly documented and designed code =-)

Share this post


Link to post
Share on other sites
I couldn''t see in your code how you manage to stop the running thread!!!!

stop() is not being called from anywhere. And btw what is this GameHandler thing... is it another threaded class?

Share this post


Link to post
Share on other sites
Now that you mention it, the GameHandler class might be very useful to know wouldn''t it =-)


  
package lifegen;

public
class GameHandler
{
private LifeGen master;
private Grid currentGrid;

static
private int generation;


public GameHandler (LifeGen master)
{
GameHandler.generation = 0;
this.master = master;
currentGrid = master.getCurrentGrid();
run();
}

public void destroy ()
{
master = null;
currentGrid.destroy();
}

public void run ()
{
for (int i = 0; i < 10000; i++)
{
nextGen();
master.repaint();
}

}

public void nextGen ()
{
GameHandler.generation++;
Grid nextGen = new Grid(currentGrid.getSize() );
currentGrid.update(nextGen);
master.setGrid(nextGen);
currentGrid = nextGen;
}

static
public int getGeneration ()
{
return (generation);
}

public void stop ()
{
master = null;
}
}


However, the stop() method is deprecated. Instead, I have made it so the run() method has a limited lifetime, which is the correct way to stop a Thread according to my book.

Share this post


Link to post
Share on other sites
Part of your problem is that you are creating a new thread and destroying the old thread everytime you go to another browser page. stop() is depracated in Thread, but not in JApplet, so you are correct in the way that you destroy the thread. The problem is when you destroy the thread. The suggested method is to keep a thread alive, even if it is not being used, if it needs to be used later. What you need to do is:

      
import javax.swing.*;
import lifegen.*;
publicclass LifeGenAppletextends JApplet {
private Thread gameThread;
private LifeGen game;
public void init () {
game = null;
gameThread = null;
if (gameThread == null) {
game = new LifeGen(30, this);
gameThread = new Thread(game);
gameThread.start();
}
}

public void start () {
game.go();
}
public void stop () {
game.pause();
}
public void destroy() {
gameThread = null;
game = null;
}
}


Then in your thread(this is trimmed down):


  
package lifegen;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
public class LifeGenextends JPanel implements Runnable {
boolean go;

public void go() {
go=true;
}
public void pause() {
go=false;
}
public void run() {
while(true) { //[EDIT] forgot this

if(go) {
do thread stuff
}
}
}
}


I left out synchronization for simplicity, but you might want to sync go()/pause() for thread safety.

This is the the recommended way to handle a thread. You keep the run() going in a continuous loop and pause from the control program with boolean values. This keeps threads from being wasted and gets away from re-initialising a thread every time.

This is where the JApplet.destroy() method comes in handy, because even if the applet is stopped, destroy is called when the browser is closed, so you are guaranteed that your thread will be cleaned up.

---
Make it work.
Make it fast.

"Commmmpuuuuterrrr.." --Scotty Star Trek IV:The Voyage Home

[edited by - CaptainJester on March 27, 2002 1:06:39 PM]

[edited by - CaptainJester on March 27, 2002 1:08:20 PM]

Share this post


Link to post
Share on other sites
Well it *seems* to be working now. Thanks for the help. I just have another question. I was fiddling around with a test program and for some reason I can''t get JApplets to respond to keyboard input from a browser (but it works in appletviewer.exe). Why does this happen?


  
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;


public
class Box
extends JApplet
implements Runnable
{
private Thread appThread;
Shape[] shape;
private boolean running;
private DPanel panel;

public void init ()
{
appThread = new Thread(this);
shape = new Shape[5];
shape[0] = new Rectangle2D.Float(2, 2, 10, 15);
running = false;
panel = new DPanel(this);
appThread.start();
}

public void start ()
{
running = true;
getContentPane().add(panel);
}

public void stop ()
{
running = false;
getContentPane().remove(panel);
}

public void destroy ()
{
appThread = null;
shape = null;
}

public void run ()
{
while (true)
{
if (running)
{
panel.getShapes(shape);
repaint();
}
}
}

public Shape[] getShape ()
{
return (shape);
}

public boolean isRunning ()
{
return (running);
}
}

class DPanel
extends JPanel
implements KeyListener
{
private Box applet;
private int count;
private boolean[] keysPressed;

public DPanel (Box applet)
{
this.applet = applet;
count = 0;
addKeyListener(this);
keysPressed = new boolean[150];
}

public void paintComponent (Graphics g)
{
if (applet.isRunning() )
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;

Dimension d = applet.getSize();
Image buff = this.createImage(d.width, d.height);
Graphics2D buffGraphics = (Graphics2D) buff.getGraphics();


Shape[] shape = applet.getShape();
for (int i = 0; i < shape.length; i++)
{
if (shape[i] != null)
buffGraphics.draw(shape[i] );
}

g2.drawImage(buff, 0, 0, null);
}
}

public boolean isFocusable ()
{
return (true);
}

public void keyPressed (KeyEvent e)
{
int k = e.getKeyCode();

if (! keysPressed[k] )
{
count++;
keysPressed[k] = true;
System.out.println(count);
}
}

public void keyTyped (KeyEvent e)
{
}

public void keyReleased (KeyEvent e)
{
int k = e.getKeyCode();

if (keysPressed[k] )
{
count--;
keysPressed[k] = false;
System.out.println(count);
}
}

public void getShapes (Shape[] shape)
{

if (count == 1)
shape[1] = new Ellipse2D.Double(10, 10, Math.random() * 30, Math.random() * 20);

else
if (count == 2)
{
shape[1] = new Ellipse2D.Double(10, 10, Math.random() * 30, Math.random() * 20);
shape[2] = new Ellipse2D.Double(10, 20, Math.random() * 30, Math.random() * 20);
}
}
}

Share this post


Link to post
Share on other sites
Just a really quick thought (I didn''t look at the code at all), but have you clicked on the applet to make sure that it has the focus in the browser?

-pirate_dau

Share this post


Link to post
Share on other sites
The problem is that the applet keeps steals the focus. Your JPanel will never have it. Try the addKeyListener into the applet, but still have the JPanel do the listening. Like this:

    
public class Box extends JApplet implements Runnable,KeyListener {
private Thread appThread;
Shape[] shape;
private boolean running;
private DPanel panel;
public void init () {
appThread = new Thread(this);
shape = new Shape[5];
shape[0] = new Rectangle2D.Float(2, 2, 10, 15);
running = false;
panel = new DPanel(this);
addKeyListener(panel); //<== change here

appThread.start();
}

This way the events from the applet will be listened to, but the processing will take place in the panel, where you want it.
---
Make it work.
Make it fast.

"Commmmpuuuuterrrr.." --Scotty Star Trek IV:The Voyage Home

[edited by - CaptainJester on March 29, 2002 3:45:59 PM]

Share this post


Link to post
Share on other sites
I think I tried that before but it still didn''t work.

No worries though, I found a way (but I dunno how efficient it really is... but as long as it works). In my game loop, I call "request focus" on the game panel once every cycle. If you know of any more efficient ways, I''d like to hear them tho.

Share this post


Link to post
Share on other sites
When I took your code and compiled it, I had the problem in Appletviewer. No keyboard events were being captured. As soon as I changed the sender of the events to the JApplet, it worked. What browser and version do you use?

---
Make it work.
Make it fast.

"Commmmpuuuuterrrr.." --Scotty Star Trek IV:The Voyage Home

Share this post


Link to post
Share on other sites