1

I am trying to load an and Image draw on it and then display that on the frame. I can also load the image on the frame and draw on the frame but this will create more blinking on my screen.

In the below code the screen blinks when users presses any key because image is loaded again and on that the new position of ball is drawn.

if up_key y--
if down_key y++
if left_key x--
if right_key x++

based on the key pressed the image is re-displayed and ball position is updated.

How to reduce the blinking effect in-order to make it smooth?

The path which I have given in the file constructor must be replaced.

import java.awt.*;
import java.io.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.awt.event.*;

class MyFrame extends Frame implements KeyListener 
{
    BufferedImage img;
    int x=100,y=100;
    public MyFrame()
    {
        super("Box");
        this.setSize(1382,784);
        this.setVisible(true);
        this.addKeyListener(this);
        this.requestFocus();
        this.setResizable(false);
    }
    public void make()
    {
        try{
        img=ImageIO.read(new File("c:/users/udesh_2/desktop/Boundary.jpg"));
        Graphics gfx=img.getGraphics();
        gfx.setColor(Color.black);
        gfx.fillOval(x,y,40,40);
        }
        catch(IOException io){}
    }
    @Override
    public void paint(Graphics g)
    {
        make();
        g.drawImage(img,0,0,getWidth(),getHeight(),null);
    }
    public static void main(String $[])
    {
        MyFrame f=new MyFrame();
        f.make();
        f.repaint();
    }

    public void keyPressed(KeyEvent key)
    {
        boolean found=false;

        if(key.getKeyCode()==KeyEvent.VK_UP)
        {
            found=true;
            y--;
        }
        if(key.getKeyCode()==KeyEvent.VK_DOWN)
        {
            found=true;
            y++;
        }
        if(key.getKeyCode()==KeyEvent.VK_LEFT)
        {
            found=true;
            x--;
        }
        if(key.getKeyCode()==KeyEvent.VK_RIGHT)
        {
            found=true;
            x++;
        }
                    if(found)
        repaint();
    }
    public void keyTyped(KeyEvent key){}
    public void keyReleased(KeyEvent key){}
}
George Z.
  • 6,643
  • 4
  • 27
  • 47
Udesh
  • 2,415
  • 2
  • 22
  • 32
  • 2
    To avoid blinking preload you img, move make() call to constructor and get rid of calling make() inside of paint method. Inside paint you should only have drawing stuffs, not loading resources and other heavy work. – mmmatey Aug 18 '19 at 10:29
  • @mmmatey Then how shall I efficiently load load the image draw on it and display the image on the frame. – Udesh Aug 18 '19 at 10:32
  • 1
    I prepare you example how to avoid it, can't run right now but it should be something like this: https://pastebin.com/XpzDx33e check here for code. – mmmatey Aug 18 '19 at 10:39
  • *`class MyFrame extends Frame`* Why use AWT? See [this answer](http://stackoverflow.com/questions/6255106/java-gui-listeners-without-awt/6255978#6255978) for many good reasons to abandon AWT components in favor of Swing. Note the Swing based `JComponent` and classes that extend it like `JPanel` are **double buffered.** So my first recommendation would be to switch to Swing (`JFrame`) but not extend it. Instead extend a `JPanel` and override `paintComponent(Graphics)` for custom painting. Or even simpler, display the image in a `JLabel` added to the frame. – Andrew Thompson Aug 18 '19 at 10:47
  • @mmmatey I would like to draw on the Image not on the frame because actually I am not drawing a single figure.What I am trying to do is buffering where I will draw every thing on the image and then I will display this image on the frame ya the only problem is that Image is taking long time to load. This way I can make my game smooth if I draw on the frame after drawing the image it wont be smooth. – Udesh Aug 18 '19 at 10:55
  • @ Andrew can u send me the code. – Udesh Aug 18 '19 at 10:57
  • 2
    *"I would like to draw on the Image not on the frame"* Interestingly (or not I guess), I actually prefer doing all painting on an image, but then it'd simply be displayed using a label (the 2nd method described above). Here is [an example of doing that](https://stackoverflow.com/questions/12683533/drawing-a-rectangle-that-wont-disappear-in-next-paint/12683632#12683632), though it is more complicated than you seem to need now. **One thing I noticed with your code. A large part of the time is taken up in resizing the image! If the GUI is not going to change size, I'd scale it once only.** – Andrew Thompson Aug 18 '19 at 11:03
  • 4
    (slaps forehead) ***And the `make()` method is called for every paint, which causes the image to be loaded again!*** – Andrew Thompson Aug 18 '19 at 11:04
  • @ Andrew no need I will code it. – Udesh Aug 18 '19 at 11:07

2 Answers2

3

You are setting value of variable img each and every time you are calling repaint() which causes the flickering. Rather initialize it once in your constructor. Then no need of extra make method also in this case. This should work:

import java.awt.*;
import java.io.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.awt.event.*;

class MyFrame extends Frame implements KeyListener {

    BufferedImage img;
    int x = 100, y = 100;

    public MyFrame() {
        super("Box");
        this.setSize(480, 480);
        this.setVisible(true);
        this.addKeyListener(this);
        this.requestFocus();
        this.setResizable(false);
        try {
            img = ImageIO.read(new File("c:/users/udesh_2/desktop/Boundary.jpg"));   
        } catch (IOException io) {
            io.printStackTrace();
        }
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
        g.setColor(Color.black);
        g.fillOval(x, y, 40, 40);
    }

    public static void main(String $[]) {
        MyFrame f = new MyFrame();
        f.repaint();
    }

    public void keyPressed(KeyEvent key) {
        boolean found = false;

        if (key.getKeyCode() == KeyEvent.VK_UP) {
            found = true;
            y--;
        }
        if (key.getKeyCode() == KeyEvent.VK_DOWN) {
            found = true;
            y++;
        }
        if (key.getKeyCode() == KeyEvent.VK_LEFT) {
            found = true;
            x--;
        }
        if (key.getKeyCode() == KeyEvent.VK_RIGHT) {
            found = true;
            x++;
        }
        if (found) {
            repaint();
        }
    }

    public void keyTyped(KeyEvent key) {
    }

    public void keyReleased(KeyEvent key) {
    }
}
UkFLSUI
  • 5,509
  • 6
  • 32
  • 47
  • 2
    `g.drawImage(img, 0, 0, getWidth(), getHeight(), null);` 1) Call `super.paint(g);` first. 2) A `Frame` is an `ImageObserver` so `null` should better be `this`. – Andrew Thompson Aug 18 '19 at 11:06
  • 1
    @AndrewThompson Nice observation and good suggestions, I've edited my answer. – UkFLSUI Aug 18 '19 at 11:13
1
import java.awt.*;
import java.io.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.awt.event.*;

class MyFrame extends Frame implements KeyListener {

    BufferedImage img;
    Image _img;
    Graphics gfx;
    int x = 100, y = 100;

    public MyFrame() {
    super("Box");
    this.setSize(1000,780);
    this.setVisible(true);
    this.addKeyListener(this);
    this.requestFocus();
    this.setResizable(false);
    try {
        img = ImageIO.read(new File("c:/users/udesh_2/desktop/Boundary.jpg"));   
    } catch (IOException io) {
        io.printStackTrace();
    }
    _img=createImage(getWidth(),getHeight());
    gfx=_img.getGraphics();

    }

    @Override
    public void paint(Graphics g) {
        if(img!=null){
        gfx.drawImage((Image)img,0,0,getWidth(),getHeight(),this);
        gfx.fillOval(x,y,30,30);

        g.drawImage(_img, 0, 0, getWidth(), getHeight(), this);

        try
        {
            Thread.sleep(70);

        }catch(Exception e){System.out.println(e);}
        }
    }

    public static void main(String $[]) {
        MyFrame f = new MyFrame();
        f.repaint();
    }

    public void keyPressed(KeyEvent key) {
    boolean found = false;

        if (key.getKeyCode() == KeyEvent.VK_UP) {
            found = true;
            y-=2;
        }
        if (key.getKeyCode() == KeyEvent.VK_DOWN) {
            found = true;
            y+=2;
        }
        if (key.getKeyCode() == KeyEvent.VK_LEFT) {
            found = true;
            x-=2;
        }
        if (key.getKeyCode() == KeyEvent.VK_RIGHT) {
            found = true;
            x+=2;
        }
        if (found) {
            repaint();
        }
    }

    public void keyTyped(KeyEvent key) {
    }

    public void keyReleased(KeyEvent key) {
    }
}
Udesh
  • 2,415
  • 2
  • 22
  • 32