0

I was wondering why I couldn't use the same effect by using the for loop, versus using inner class with an actionlistener object to refresh plots of points on an image. Here are the codes:

import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import java.util.Random;

public class MyCanvas
{
    JLabel view;
    BufferedImage surface;
    Random random = new Random();
    public void initMyCanvas()
    {
        surface = new BufferedImage(1000,1000,BufferedImage.TYPE_INT_RGB);
        view = new JLabel(new ImageIcon(surface));
        Graphics g = surface.getGraphics();
        g.setColor(Color.ORANGE);
        g.fillRect(0,0,1000,1000);
        ActionListener listener=new ActionListener(){
            public void actionPerformed(ActionEvent ae){
                int[] xLoc = new int[10]; 
                int[] yLoc = new int[10];
                System.out.println("drawing..");
                Graphics g = surface.getGraphics();
                g.setColor(Color.ORANGE);
                g.fillRect(0,0,1000,1000);

                Random rn=new Random();

                for (int ji=0;ji<10;ji++){
                    xLoc[ji]=rn.nextInt(500);
                    yLoc[ji]=rn.nextInt(500);
                }

                drawNodes(xLoc,yLoc,g);
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        };
        Timer timer = new Timer(1000, listener);
        timer.start();
    }
    public static void main(String[] args)
    {
        MyCanvas canvas = new MyCanvas();
        canvas.initMyCanvas();
        JFrame frame = new JFrame();
        int vertexes = 0;
        vertexes = 10;
        int canvasSize = vertexes * vertexes;
        frame.setSize(canvasSize, canvasSize);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(canvas.view);        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public void drawNodes(int[] x, int[] y, Graphics g)
    {
            // Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5
            g.setColor(Color.white);
            System.out.println(" In drawNodes");
            for (int i=0;i<x.length;i++){
                g.fillOval(x[i], y[i], 8, 8);
            }
            g.dispose();
            view.repaint();
    }
}

Versus the one implemented with the for loop to iterate over the same 'section' of the codes multiple times to create the plots.

import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import java.util.Random;

public class MyCanvas
{
    JLabel view;
    BufferedImage surface;
    Random random = new Random();
    public void initMyCanvas()
    {
        surface = new BufferedImage(1000,1000,BufferedImage.TYPE_INT_RGB);
        view = new JLabel(new ImageIcon(surface));
        Graphics g = surface.getGraphics();
        g.setColor(Color.ORANGE);
        g.fillRect(0,0,1000,1000);
        for (int i=0; i<5;i++){
            int[] xLoc = new int[10]; 
            int[] yLoc = new int[10];
            System.out.println("drawing..");

            g.setColor(Color.ORANGE);
            g.fillRect(0,0,1000,1000);

            Random rn=new Random();

            for (int ji=0;ji<10;ji++){
                xLoc[ji]=rn.nextInt(500);
                yLoc[ji]=rn.nextInt(500);
            }

            drawNodes(xLoc,yLoc,g);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args)
    {
        MyCanvas canvas = new MyCanvas();
        canvas.initMyCanvas();
        JFrame frame = new JFrame();
        int vertexes = 0;
        vertexes = 10;
        int canvasSize = vertexes * vertexes;
        frame.setSize(canvasSize, canvasSize);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(canvas.view);        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public void drawNodes(int[] x, int[] y, Graphics g)
    {
            // Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5
            g.setColor(Color.white);
            System.out.println(" In drawNodes");
            for (int i=0;i<x.length;i++){
                g.fillOval(x[i], y[i], 8, 8);
            }
            g.dispose();
            view.repaint();
    }
}

The reason I ask is because I'm writing the equivalent implementation in Xtend, as a part of a Domain-specific language building effort; and I'm having problems being able to write inner classes and/or implement the ActionListener interface. And again, this would be a nice thing to de-mystify for myself as well !!

alex2410
  • 10,904
  • 3
  • 25
  • 41
apil.tamang
  • 2,545
  • 7
  • 29
  • 40

1 Answers1

0

Problem of method 2 is you call your loop in EDT, because of, it blocks and can't paint your components. Read Swing Concurency.

1)Swing Timer is suitable for drawing with intervals. With timer you needn't to use Thread.sleep(1);.

2)You can try to use SwingWorker for repainting. You can find a lot of examples for that.

3)Also use custom paintings in paintComponent() method watch next example and read oracle

Community
  • 1
  • 1
alex2410
  • 10,904
  • 3
  • 25
  • 41