Topic: 为什么我的applet闪烁不定呢(附代码)

  Print this page

1.为什么我的applet闪烁不定呢(附代码) Copy to clipboard
Posted by: april518
Posted on: 2004-10-06 11:12

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

public class MyFifth extends Applet{
public void init(){
  Color s1=new Color(225,230,60);
   setBackground(s1);   
     }   
public void paint(Graphics g){
   Font f=new Font("Courier",Font.BOLD+Font.ITALIC,72);
   setFontRose;
   Color s2=new Color(230,50,50);
   g.setColor(s2);
   g.drawString("Rush,men",5,60) ;
   }  
  
   }

2.Re:为什么我的applet闪烁不定呢(附代码) [Re: april518] Copy to clipboard
Posted by: dorrenchen
Posted on: 2004-10-06 12:37

quick fix, put all newly instantiated variables somewhere else.


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

public class MyFifth2 extends Applet {
  int c;
  Font f = new Font("Courier", Font.BOLD + Font.ITALIC, 72);
  
  public void init() {
    setFont(f);
    Color s1 = new Color(225, 230, 60);
    setBackground(s1);
  }

  public void paint(Graphics g) {    
    Color s2 = new Color(230, 50, 50);
    g.setColor(s2);
    
    g.drawString("Rush,men", 5, 60);
    System.out.println(c++);
  }

}


but ideally, you want to use double buffering technique. Create a base BufferedApplet and extends it with your own applet, like this

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;

public class BufferedApplet extends java.applet.Applet implements Runnable {
  /*
   * THIS CLASS HANDLES DOUBLE BUFFERING FOR YOU, SO THAT THE IMAGE DOESN'T
   * FLICKER WHILE YOU'RE RENDERING IT. YOU DON'T REALLY NEED TO WORRY ABOUT
   * THIS TOO MUCH, AND YOU'LL PROBABLY NEVER NEED TO CHANGE IT. IT'S REALLY
   * JUST USEFUL LOW LEVEL PLUMBING.
   */

  public void render(Graphics g) {} // *you* define how to render

  public boolean damage = true; // you can force a render

  private Image image = null;

  private Graphics buffer = null;

  private Thread t;

  private Rectangle r = new Rectangle(0, 0, 0, 0);
  private int counter;

  // A BACKGROUND THREAD CHECKS FOR CHANGES ABOUT 30 TIMES PER SECOND

  public void start() {
    if (t == null) {
      t = new Thread(this);
      t.start();
    }
  }

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

  public void run() {
    try {
      while (true) {
        repaint();
        Thread.sleep(30);
      }
    } catch (InterruptedException e) {
    }
    ;
  }

  /*
   * UPDATE GETS CALLED BY THE SYSTEM. IT CALLS YOUR RENDER METHOD, WHICH
   * DRAWS INTO AN OFF-SCREEN IMAGE. THEN UPDATE COPIES THE IMAGE YOU'VE
   * RENDERED ONTO THE APPLET WINDOW.
   */
  public void update(Graphics g) {
    if (r.width != bounds().width || r.height != bounds().height) {
      image = createImage(bounds().width, bounds().height);
      buffer = image.getGraphics();
      r = bounds();
      damage = true;
    }
    render(buffer);
    if (damage){
      g.drawImage(image, 0, 0, this);
      //damage = false; // comment this out so it redraw all the time
    }
  }
}


and your improved applet

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

public class MyFifth2 extends BufferedApplet {
  int w, h;
  int x, counter;
  Font f = new Font("Courier", Font.BOLD + Font.ITALIC, 72);
  Color s1 = new Color(225, 230, 60);
  Color s2 = new Color(230, 50, 50);
  
  public void init() {
    w = this.getWidth();
    h = this.getHeight();
    setFont(f);
    setBackground(s1);
  }

  public void render(Graphics g) {  
    g.setColor(s1);
    g.fillRect(0, 0, w, h);
        
    g.setColor(s2);
    x = (counter++ / w)%2==0 ? x+1 : x-1;
    g.drawString("Rush,men", x, 60);
    System.out.println(x + " " + counter + " " + w);
  }

}

3.Re:为什么我的applet闪烁不定呢(附代码) [Re: april518] Copy to clipboard
Posted by: april518
Posted on: 2004-10-06 18:08

THANK YOU!
MR.DORRENCHEN.
I AM ONLY A BEGINNER WITH JAVA,SO ....
I REALLY COULD'T UNDERSTAND WHAT YOU SAID IN YOUR REPLY.THAT'S MAYBE DISAAPIONTING,BUT IT'S THE FACT .BUT I AM STRONG WILLING,I WILL TRY MY BEST TO CATCH IT.JUST BELIEVE ME! HE HE!
IN YOUR REPLY ,IT IS FANTASTIC,YOU JUST ADD A INTEGER VARIABLS C, THE PROBLEMS COMES TO AN END .COULD YOU EXPLAIN WHY MY APPLET
FLICHERS AND WHY AFTER ADDING A "C",IT WOKS NORMALLY.IS THERE
ANYTHING DIFFRENT?AND THE LINE "PRINTLN("C++")",DOES'NT IT HAVE A
LIMIT?
WHEN IT STOPS?
WHY COULD'T I SEE THE OUTPUT OF C++?
MY ENGLISH IS SO POOR ,BUT I HOPE YOU COULD UNDERSTAND WHAT I
MEAN.
THANK YOU FOR YOU HELP!

4.Re:为什么我的applet闪烁不定呢(附代码) [Re: april518] Copy to clipboard
Posted by: floater
Posted on: 2004-10-06 22:13

A little tip for english. Using capital letters means you are yelling at someone. While apparently not, please use small letters with appropriate caps. If you want to emphasize on something, use *-quotes, like *handsome*.

Dorren, you could use 禁止在这个帖子中使用笑脸标记 check to get rid of the 笑脸s in your code. How's everything going?

5.Re:为什么我的applet闪烁不定呢(附代码) [Re: april518] Copy to clipboard
Posted by: dorrenchen
Posted on: 2004-10-06 22:41

SetFont() is making it flickering.

when c reaches Integer.MaxValue, it will be negative, but it takes a long time for that to happen.

If you look more closely, you can see my changes are not just adding variable C. I moved some variable instantiation out of paint(), like Font f. But I moved it for efficiency, since paint() will be called many times, but font doesn't change, so it's better to make it a class member. For the same reason, both Color variable s1, s2 should be class member as well.

int C is being printed to console, not into applet. So if paint() is being called many times, you can see the print out at the console.

and ideally, you only put applet related code in init(), like getting width, height stuff. Do not put drawing related code in init(), think about it, what if your animation changes background color?

Double buffering.
-----------------------------
When you paint directly onto applet, especially when you doing any kind of animation, the applet will flash. More stuff you try to put into applet, more it flashes. The solution is to use a common technique called "double buffering". What it means is that you first paint the image in a secondary place---buffer, after the image is complete, you paint this whole finished image onto applet. So you paint twice in this process, that's why it's called "double buffering".

because you do the step by step drawing on the buffer, and you only copy the final image onto applet once at the end, so the visual applet is updated less frequently, and that stops the flashing.

how do you exactly to do it? you do it in update(g) method.

// in update(Graphics g) method.
bufferImage = createImage(width, height);
bufferG = bufferImage.getGraphics();
render(bufferG);

1. you create the buffer image instance the same size as applet.
2. then you get the graphic from that buffer image, consider Graphics g is your paint brush for the buffer image.
3. to make implementation cleaner, do all your drawing in a separate method "render".

Ideally, you should create a bufferedApplet, then everytime you create a new animation applet, then just extends from that bufferedApplet. But here you doing all double buffering and drawing in the same applet, just for the sake of simplicity. When you ready to use extend the bufferedApplet, then you can just take out render(g) method and related class variables, put into your new applet, and rename the old one to bufferedApplet and extends it.
 

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

public class MyFifth1 extends Applet implements Runnable {
  private Image bufferImage = null;

  private Graphics bufferG = null;

  private Rectangle r = new Rectangle(0, 0, 0, 0);
  private Thread t;

  int x, counter;
  Font f = new Font("Courier", Font.BOLD + Font.ITALIC, 72);
  Color s1 = new Color(225, 230, 60);
  Color s2 = new Color(230, 50, 50);
  int R,G,B;
  
  // start the animation thread.
  public void start() {
    if (t == null) {
      t = new Thread(this);
      t.start();
    }
  }
  
  // do your own painting, draw words, circles, etc.
  public void render(Graphics g) {
    g.setFont(f);
    R = (R+1) % 255;
    G = (G+1) % 255;
    B = (B+1) % 255;
    g.setColor(new Color(R, G, B)); // alter bkgd from black to white
    g.fillRect(0, 0, r.width, r.height); // clean previous drawing

    g.setColor(s2);
    // make the "rush,men" going back and forth
    x = (counter++ / r.width) % 2 == 0 ? x + 1 : x - 1;
    g.drawString("Rush,men", x, 60);
    
    // debugging
    System.out.println(x + " " + counter + " " + r.width + ", RGB" +
        R + ","+G+","+B);
  }

  // using double bufffering. leave this method alone, and do all your painting
  // in render(g) method
  public void update(Graphics g) {
    // if the applet's size has been changed.
    if (r.width != bounds().width || r.height != bounds().height) {
      // create buffer image
      bufferImage = createImage(bounds().width, bounds().height);
      // breate buffer graphic instance, to be used to draw onto buffer
      bufferG = bufferImage.getGraphics();
      r = bounds();
    }
    
    render(bufferG); // draw onto buffer
    g.drawImage(bufferImage, 0, 0, this); // copy final image to applet
  }

  // doing the animation by calling repaint() every 30 millisecond
  public void run() {
    try {
      while (true) {
        repaint();
        Thread.sleep(30);
      }
    } catch (InterruptedException e) {
    }
  }
}

6.Re:为什么我的applet闪烁不定呢(附代码) [Re: april518] Copy to clipboard
Posted by: april518
Posted on: 2004-10-09 16:11

import java.awt.*;
import java.applet.*;
public class MyFifth extends Applet{

Image workspace ;
Graphics offscreen;

Font f=("Cnew Fontourier",Font.BOLD+Font.ITAICL,72);

public void init(){

workspace=createImage(size().width,size().height);
offscreen=workspace.getGraphics();

setFontRose;

Color s1=new Color(225,230,60);
setBackground(s1);


}

public void paint(Graphics g){


offscreen.drawString("RUSH,MAN",50,60);


Color s2=new Color(230,50,50);
g.setColor(s2);
g.drawImage(workspace,0,0,this);

}

}
I have improved my code as above, "using "the double buffering technique.It seems right . but when compiling the file ,the build output is "MyFifth.java uses or overrides a deprecated API".
What's the matter?
And how can I handdle the problem?

I think I am only painting serveral words on the applet,it's no use to "implements Runnable" ,so in my code I don't implement Thread.But I am still a little doubt of myself.hehe .
Am I right ?
Thank you! Dorren!

7.Re:为什么我的applet闪烁不定呢(附代码) [Re: april518] Copy to clipboard
Posted by: april518
Posted on: 2004-10-09 16:16

line 8 should be
Font f =new Font ("Courier",Font.BOLD+Font.ITAICL,72);
sorry !

8.Re:为什么我的applet闪烁不定呢(附代码) [Re: april518] Copy to clipboard
Posted by: kulatasana
Posted on: 2004-10-20 22:27

我E文不好,就中文说了.
本人对双缓冲技术认识的并不多,不过我在遇到这种情况的时候一般先建立一个BufferedImage bimg图象,bg = bimg.createGraphics();
然后所有操作在bg中进行就好,最后在paint()方法中把bimg画上.
我是新手,只能用这么笨的方法了,不过蛮好用的.


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923