[java] Mouse action in a while loop

Started by
8 comments, last by The Hitman 17 years, 5 months ago
public void paint( Graphics g )
{

super.paint(g);
g.drawImage( logo1.getImage(), x, y, null );
JLabel fk = new JLabel("hi");

//begin rnd
while (count > 1) {
    
    while ( i < 10000) { //change to control speed
    	i++;
    	System.out.println(i);
	Math.sqrt((double)i); // this should really chew up some time
    
    
    	if (i > 9999) {
    	i = i - 9999;
    		int xn = (int)(Math.random()*600);
     int yn = (int)(Math.random()*300);
     y = yn;
     x = xn;
   
 update(g);
  
}
Basicly can somebody show me how to make it so while in the while loop ( i <10000)i can add a action listener so when i click the image icon "logo1" it does a action. Thanks XD
Advertisement
This looks totally wrong. What are you trying to do?
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][LWJGL Tutorials for NeHe][LWJGL Wiki][jMonkey Engine]
Quote:
JLabel fk = new JLabel("hi");


Is there some reason you are creating a JLabel each time paint(...) is called.


It sounds like you need to restructure your idea. However, you could create a queue of messages, and then check for messages each (or every N) itteration(s) through the while loop. Basicaly have your mouseListener.mouseClick event put the messages into an appropriate data structure (Vector/Linked List/Array etc...). Then check this data structure for messages.

Here is a psudo example
Vector messagesmouseClick(Event e)    messages.add(e)paint()  while(n < 10000)     calculate()     if(messages.size() > 0)        processMessages()



It is possible to create a annonymous event handler inside this loop. But this is a VERRY BAD THING.


I am not sure exactly what you are trying to do, but it looks like you are updating the position of logo1 in the paint() method. Try doing this in it's own function, then call paint directly to draw the new position.

From your code it looks like you are calling the update(Graphics) function for your window within the paint method. I would recommend you do not do this. I can not tell how many recusions deep you get because I don't see the control logic for the count variable. If this never changed then as soon as paint is called, your program will continue to recurse into the paint method indifinitly... or until it dies with a stack overflow.

I suggest you abstract all your variable/graphics calculation routines away from your drawing routines.
∫Mc
Your right i am trying to keep moving the ImageIcon acrooss the screen,I did what you said and made it sperate.
new code:
public void refresh() {
//begin rnd


while (count > 5) {
try {
Thread.sleep(SPEED);
} catch (InterruptedException e) {}


i++;
System.out.println(i);
Math.sqrt((double)i); // this should really chew up some time
//addMouseMotionListener(logo1);

int xn = (int)(Math.random()*600);
int yn = (int)(Math.random()*300);
y = yn;
x = xn;



//update(g); old
update(getGraphics());

}
}
Also I stoped using a while loop as a timer(sucked CPU XD)Thanks for the tip.
But know my application looks like it has chikenpox - because the ImageIcon is a red ball shape and it doesnt delete when it moves to a new pos but that should be a easy fix-.But im still not shure about makeing it so when you click the imageicon something happens
It would be helpfull if you posted the entre class(s) to this thread. When you do please use source tags: souce and /source enclosed in []. I don't want to assume to much about your code, and lead you down the wrong path.

Personaly I would create a separate thread as the main 'render' loop. Alternatly you could run the animation on the main(...) thread. The event messaging will still be on another thread, so you will get your events.

I have to run to class right now. I'll post more details later.
∫Mc
Thank i didnt want to post the whole class because i didnt want to waste anyones timer lol but i see why its important so here is the full source
/* * Main.java * * Created on November 7, 2006, 8:55 PM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */package imagetest;import javax.swing.*;import java.applet.*;import java.awt.*;import java.awt.event.*;import  sun.audio.*; import java.io.*;//remember for snake game if snake = food x + y random pos of food +1scorepublic class Main extends JFrame {int SPEED = 1000;private ImageIcon logo1;//Defines logo1 as image iconint delay = 5000; //5second delayint period = 1000; //repeat every secpublic int x = 300;//defines x pos of logo1 later on		public int y = 300;//define y posint count = 500;int score = 0;int i = 0;public Main() {  JButton faris = new JButton("faris");	logo1 = new ImageIcon("ball.png");	getContentPane().setPreferredSize( new Dimension( 600, 300 ) );// sets screen to 600*300		pack();	setVisible( true );	setResizable(false); //stops user from resizing        setDefaultCloseOperation(EXIT_ON_CLOSE);  		//audio code comin soon  		//try {  		  	//	InputStream in = new FileInputStream("sound.mp3"); not work yet//	AudioStream as = new AudioStream(in);//	AudioPlayer.player.start(as);     	   	//} // catch(IOException e){  	//System.out.println(e);  //}  //end audio code}public void paint( Graphics g ){g.drawImage( logo1.getImage(), x, y, null );refresh();               }                       public void refresh() {//begin rnd    while (count > 5) {       try {              Thread.sleep(SPEED);          } catch (InterruptedException e) {}         	i++;    	System.out.println(i);	Math.sqrt((double)i); // this should really chew up some time    //addMouseMotionListener(logo1);        		int xn = (int)(Math.random()*600);     int yn = (int)(Math.random()*300);     y = yn;     x = xn;     //update(g); old     update(getGraphics());	 }    }public static void main(String args[]){	Main test = new Main();		}}

Thanks:D
Thank i didnt want to post the whole class because i didnt want to waste anyones timer lol but i see why its important so here is the full source
/* * Main.java * * Created on November 7, 2006, 8:55 PM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */package imagetest;import javax.swing.*;import java.applet.*;import java.awt.*;import java.awt.event.*;import  sun.audio.*; import java.io.*;//remember for snake game if snake = food x + y random pos of food +1scorepublic class Main extends JFrame {int SPEED = 1000;private ImageIcon logo1;//Defines logo1 as image iconint delay = 5000; //5second delayint period = 1000; //repeat every secpublic int x = 300;//defines x pos of logo1 later on		public int y = 300;//define y posint count = 500;int score = 0;int i = 0;public Main() {  JButton faris = new JButton("faris");	logo1 = new ImageIcon("ball.png");	getContentPane().setPreferredSize( new Dimension( 600, 300 ) );// sets screen to 600*300		pack();	setVisible( true );	setResizable(false); //stops user from resizing        setDefaultCloseOperation(EXIT_ON_CLOSE);  		//audio code comin soon  		//try {  		  	//	InputStream in = new FileInputStream("sound.mp3"); not work yet//	AudioStream as = new AudioStream(in);//	AudioPlayer.player.start(as);     	   	//} // catch(IOException e){  	//System.out.println(e);  //}  //end audio code}public void paint( Graphics g ){g.drawImage( logo1.getImage(), x, y, null );refresh();               }                       public void refresh() {//begin rnd    while (count > 5) {       try {              Thread.sleep(SPEED);          } catch (InterruptedException e) {}         	i++;    	System.out.println(i);	Math.sqrt((double)i); // this should really chew up some time    //addMouseMotionListener(logo1);        		int xn = (int)(Math.random()*600);     int yn = (int)(Math.random()*300);     y = yn;     x = xn;     //update(g); old     update(getGraphics());	 }    }public static void main(String args[]){	Main test = new Main();		}}

Thanks:D
Thanks... I will take a look at it and post back. I have another class in an hour and need to get some dinner. I did write up a example to illistrate some of the things I was mentioning.

This class will rotate a box clockwize in the shape of a rounded edged box (uncomment the first fillRect in paint). It will stop the animation on a down click and resume it on a up click. This is a very quick hack, but it should suffice as an example.



import java.awt.* ;import java.awt.event.* ;public class GDNETJavaAnim extends Frame implements MouseListener, Runnable{     private Thread      cls_Thread          = null ;    private Rectangle   cls_Rect	    = new Rectangle(10,10,50,50) ;        private boolean	bool_Running	    = false ;    private boolean	bool_StopThread	    = false ;        private boolean	bool_StopAnim	    = false ;            public GDNETJavaAnim() {	super("GDNETJavaAnim") ;		//Setup window close event.	WindowAdapter wa = new WindowAdapter() {	   public void windowClosing(WindowEvent e)  {	       System.exit(0) ;	   }	} ;		addWindowListener(wa) ;	addMouseListener(this) ;		setSize(320,240) ;	setVisible(true) ;		    }        public void repaint() {	paint(getGraphics()) ;    }        public void update(Graphics g) {	paint(g) ;    }        public void paint(Graphics g) {	g.setColor(Color.white) ;	g.fillRect(0,0,getWidth(),getHeight()) ;	g.setColor(Color.black) ;	g.fillRect(cls_Rect.x,cls_Rect.y,cls_Rect.width,cls_Rect.height) ;    }        /**     *	Start the animation     */    public void start() {    	try {	    bool_StopThread = false ;	    cls_Thread = new Thread(this) ;	    cls_Thread.start() ;	}	catch(Exception e) {}    }        public void stop() {	bool_StopThread = true ;		while(bool_Running) {	    try {Thread.sleep(100) ; }	    catch(Exception e) {}	}    }        /*****************************************************************     *			Interface Implementations     *****************************************************************/    /**     *	    Runnable Implementation     */    public void run() {        bool_Running = true ;	double dx = 0, dy = 0 ;	double theta = 0 ;		try {	    while(!bool_StopThread) {		if(!bool_StopAnim) {		    theta = theta + .01d ;		    dx = 50 * Math.cos(theta) ;		    dy = 50 * Math.sin(theta) ;		    cls_Rect.x = 100 + (int) dx ;		    cls_Rect.y = 100 + (int) dy ;		    			    paint(getGraphics()) ;		}				Thread.sleep(10) ;	    }	}	catch(Exception e) {}	bool_Running = false ;	return ;    }        /**     *	    Mouse event handlers     */        public void mouseClicked(MouseEvent e) {}    public void mouseEntered(MouseEvent e) { }    public void mouseExited(MouseEvent e) { }              public void mousePressed(MouseEvent e) { bool_StopAnim = true ;}              public void mouseReleased(MouseEvent e) { bool_StopAnim = false ;}                    public static void main(String args[]) {        new GDNETJavaAnim().start() ;    }    }
∫Mc
The initial execution path through your program is as follows:

Main.main(...)- entry point
Main.Main - constructor
Main.paint() - Paint the image
Main.refresh() - Do some calculations and repaint

Here is the problem. You are using the paint() method to involk the refresh() function wich in turn involkes the paint() method ( via update(getGraphics()) ) and so on. These calls dont appear to unwind at any point. To make matters worse, the paint() method gets called by the Swing library. So now you have many calls into paint, which in turn call into refresh etc. Always control your execution flow using some predictiable behaviour. Using JFrame.paint() to start the execution of your applicaiton is not a good behaviour.

I also do not see where you are deincrementing the count variable, so the while loop in your refresh method runs forever. Maybe you are doing this just for testing.

In any case I recommend you do the following for now.

1. Remove the refresh function from your paint method. Only do rendering operations in here. Do not call any other functions that may call back into paint.

2. Remove the loops from your refresh function.

3. Create a loop in your constructor and call refresh from within this loop.

Essentialy this is what the example I wrote up for you does. You could easily move the looping in the run method to the bottom of the constructor and the program would work the same. The only difference is now you are running on the startup thread.

Basicaly you want the initialization and execution of your program to follow a path somewhat like this:

1. Initialize variables and resources
2. start main rendering loop
3. Calculate data
4. paint
5. goto 3


I hope some of this helps.
∫Mc
Thanks for taking your spare time to help me i relly apprecaae it.
Ive learnt from your code and im going to rewrite my code make it more efficent,ill post back with my new code just incase you want to see it.The reson i wanted the while loop constant is so it kept randimazing a new position,so when you have to click the image as it moves around which adds up to your own score.Then ill make a multpayer version played from diffent computers.

This topic is closed to new replies.

Advertisement