Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Unresponsive Input 1

Status
Not open for further replies.

ACRRHODES

Programmer
May 16, 2000
33
CA
I have a program that I am working on which is relatively simple. It runs using a thread (start, run, stop), and responds to keyboard/mouse input. The problem is that, though the graphical/technical elements of the program run smoothly, the more advanced my program has become, the less responsive the mouse/keyboard have become while running my program. Now, they respond almost never, and if they do, it's about a minute after I've hit them. When I commented out the paint() method, everything started working again. My program DOES use some relatively advanced graphical techniques (at least for this level of programming) which I would hate to sacrifice, so I'd like to know if anyone understands what in my paint() method might be interfeering with my program.

Best Regards,
ACRRHODES ***
Dammit Jim, I'm a programmer, not a doctor.
 
Hi!

I think it's to give the thread a certain priority.

I am afraid that I don't know how, but you should think
in this direction.

cya

frag patrick.metz@epost.de
 
In general, any complicated processing in your system should be done outside the main swing/awt thread. All event processing (e.g. mouse and keyboard input) are done via this thread so all code you run in this thread should be fast and compact. If you need to do expensive calculations create another thread to do the processing there. Also, you should not have other threads manipulate the GUI components as swing is not thread safe (I'm assuming that you are using swing but awt has similar issues).

Check out these links for additional help


 
For one thing, I'm not using swing. I'm not sure what you mean about doing my processing on a seperate thread - could you explain this? And a little tidbit that might help in your diagnosis:

When I took the code from a graphics method (WarpImage) out and put it directly into my paint method, my program became responsive again, but there is still about a 5 second delay. Thanx for the help. ***
Dammit Jim, I'm a programmer, not a doctor.
 
All event processing in AWT/Swing is done on the main event thread. For instance, when you click a button or drag your mouse, these events are pushed onto the event queue for processing.

You must make these event processing methods fast otherwise they block the queue from processing other events until your event call returns.


For example, if you have an actionlistener on a button and in the actionlistener code, you invoke an expensive (ie heavy processing) method on an object or do some time consuming calculation then no further user input will be processed (eg additional button clicks) until this processing is finished.

For this reason, expensive calculations should be done in another thread to allow the event processing thread to continue servicing user events.

At this point, it may be helpful to post some of your code.

Charles
 
Note that this code is in the process of debugging, so some parts may be embarrasingly redundant (I'm only a beginner after all):

import java.awt.*;
import java.awt.geom.*;
import java.util.*;

public class Luge extends java.applet.Applet implements Runnable
{
double x = 100;
double y = 75;
double speed = 100;
double angle = 0;
double turnangle = 0;
int tatb = 0;
double nextangle = 0;
boolean readytorun = false;
Random r = new Random();
Thread runner;
Image track;
Image l1;
Image l2;
Image r1;
Image r2;
Image s1;
Image s2;
Image cart;
Image warptrack;
Image track2;
Image mybuffer;
Graphics t2;
Graphics g;

public void init()
{
track = getImage(getCodeBase(),"track.gif");
l1 = getImage(getCodeBase(),"l1.gif");
l2 = getImage(getCodeBase(),"l2.gif");
r1 = getImage(getCodeBase(),"r1.gif");
r2 = getImage(getCodeBase(),"r2.gif");
s1 = getImage(getCodeBase(),"s1.gif");
s2 = getImage(getCodeBase(),"s2.gif");
cart = getImage(getCodeBase(),"cart.gif");
track2 = createImage(200,400);
warptrack = createImage(200,400);
mybuffer = createImage(400,400);
requestFocus();
while ((!imageloaded(track))||(!imageloaded(l1))||(!imageloaded(l2))||(!imageloaded(r1))||(!imageloaded(r2))||(!imageloaded(s1))||(!imageloaded(s2))||(!imageloaded(cart))||(!imageloaded(track2))||(!imageloaded(mybuffer))||(!imageloaded(warptrack)))
{}
t2 = track2.getGraphics();
g = mybuffer.getGraphics();
readytorun=true;
}

private boolean imageloaded(Image i)
{
if((i.getHeight(this)==-1)||(i.getWidth(this)==-1))
return false;
else
return true;
}

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

public void stop()
{
runner = null;
}

public void pause(int time)
{
try {Thread.sleep(time);} catch (InterruptedException e) {System.out.println("Interruption!");}
}

public void run()
{
Thread thisThread = Thread.currentThread();
while (runner == thisThread)
{
double rr = r.nextDouble();
if (rr > .999)
tatb=35;
if ((rr > .4995)&&(rr < .5005))
tatb=0;
if (rr < .001)
tatb=-35;
if (turnangle > tatb)
turnangle -= .1;
if (turnangle < tatb)
turnangle += .1;
if (nextangle != angle)
angle += (((nextangle-angle)/Math.abs(nextangle-angle))*.1)/(.5+Math.tan(Math.toRadians(angle)));
speed += 10;
if (x<20)
{
speed /= 1.1;
x=20;
}
if (x>155)
{
speed /= 1.1;
x = 155;
}
double sp = speed;
speed = sp-(Math.abs(sp*Math.sin(Math.toRadians((angle-turnangle)))))/50;
x+=((sp*Math.sin(Math.toRadians((angle-turnangle))))*Math.cos(Math.toRadians((angle-turnangle))))/100;
y += speed/100;
//pause(50);
//angle += .1;
repaint();
pause(50);
}
}

// My input methods
public boolean keyDown(Event evt, int key)
{
System.out.println(&quot;Keydown&quot;);
if (key == Event.LEFT)
{
angle -= 3/(.5+Math.tan(Math.toRadians(angle)));
}

if (key == Event.RIGHT)
{
angle += 3/(.5+Math.tan(Math.toRadians(angle)));
}
nextangle=angle;
repaint();
return true;
}
public boolean mouseDrag(Event evt,int xx,int yy)
{
System.out.println(&quot;Mousedrag&quot;);
if ((yy<250)||(xx<200))
nextangle = -Math.atan((xx-x)/(yy-250))*(180/Math.PI);
return true;
}
public boolean mouseDown(Event evt,int xx,int yy)
{
System.out.println(&quot;Mousedown&quot;);
if ((yy<250)||(xx<200))
nextangle = -Math.atan((xx-x)/(yy-250))*(180/Math.PI);
System.out.println(nextangle);
System.out.println(xx);
System.out.println(x);
System.out.println(yy);
System.out.println(180/Math.PI);
return true;
}


public void paint(Graphics gg)
{
if (readytorun)
{
t2 = track2.getGraphics();
g = mybuffer.getGraphics();
g.setColor(Color.white);
g.fillRect(0,0,400,400);
t2.drawImage(track,0,(int)((int)(y)%400),this);
t2.drawImage(track,0,(int)(((int)(y)%400)-400),this);
// All this junk is the image-warping thing
g.drawImage(track2,
0, 0, (int)(((int)(100+turnangle*2))/2), (int)(200/2),
0, 0, (int)((200/2)*.25), (int)((400/2)*.25),
this);
g.drawImage(track2,
(int)(((int)(100+turnangle*2))/2), 0, ((int)(100+turnangle*2)), (int)(200/2),
(int)((200/2)*.25), 0, (int)(200/2), (int)((400/2)*.25),
this);

g.drawImage(track2,
0, (int)(200/2), (int)(((int)(100+turnangle*2))/2), 200,
0, (int)((400/2)*.25), (int)((200/2)*.25), (int)(400/2),
this);

g.drawImage(track2,
(int)(((int)(100+turnangle*2))/2), (int)(200/2), ((int)(100+turnangle*2)), 200,
(int)((200/2)*.25), (int)((400/2)*.25), (int)(200/2), (int)(400/2),
this);

//quarter #2

g.drawImage(track2,
((int)(100+turnangle*2)), 0, (int)((((int)(100+turnangle*2))+200)/2), (int)(200/2),
(int)(200/2), 0, (int)(200-.25*(200/2)), (int)((400/2)*.25),
this);

g.drawImage(track2,
((int)(100+turnangle*2)), (int)(200/2), (int)((((int)(100+turnangle*2))+200)/2), 200,
(int)(200/2), (int)((400/2)*.25), (int)(200-(200/2)*.25), (int)(400/2),
this);

g.drawImage(track2,
(int)((200+((int)(100+turnangle*2)))/2), 0, 200, (int)(200/2),
(int)(200-(200/2)*.25), 0, 200, (int)((400/2)*.25),
this);

g.drawImage(track2,
(int)((200+((int)(100+turnangle*2)))/2), (int)(200/2), 200, 200,
(int)(200-.25*(200/2)), (int)((400/2)*.25), 200, (int)(400/2),
this);

//quarter #3


g.drawImage(track2,
0, 200, (int)((int)(100+turnangle*2))/2, (int)((400+200)/2),
0, (int)(400/2), (int)((200/2)*.25), (int)(400-(400/2)*.25),
this);
g.drawImage(track2,
(int)(((int)(100+turnangle*2))/2), 200, ((int)(100+turnangle*2)), (int)((400+200)/2),
(int)((200/2)*.25), (int)(400/2), (int)(200/2), (int)(400-(400/2)*.25),
this);
g.drawImage(track2,
0, (int)((400+200)/2), (int)((int)(100+turnangle*2))/2, 400,
0, (int)(400-(400/2)*.25), (int)((200/2)*.25), 400,
this);

g.drawImage(track2,
(int)(((int)(100+turnangle*2))/2), (int)((400+200)/2), ((int)(100+turnangle*2)), 400,
(int)((200/2)*.25), (int)(400-(400/2)*.25), (int)(200/2), 400,
this);

//quarter #4

g.drawImage(track2,
((int)(100+turnangle*2)), 200, (int)((200+((int)(100+turnangle*2)))/2), (int)((400+200)/2),
(int)(200/2), (int)(400/2), (int)(200-(200/2)*.25), (int)(400-(400/2)*.25),
this);

g.drawImage(track2,
(int)((200+((int)(100+turnangle*2)))/2), 200, 200, (int)((400+200)/2),
(int)(200-(200/2)*.25), (int)(400/2), 200, (int)(400-(400/2)*.25),
this);

g.drawImage(track2,
((int)(100+turnangle*2)), (int)((400+200)/2), (int)((200+((int)(100+turnangle*2)))/2), 400,
(int)(200/2), (int)(400-(400/2)*.25), (int)(200-(200/2)*.25), 400,
this);

g.drawImage(track2,
(int)((200+((int)(100+turnangle*2)))/2), (int)((400+200)/2), 200, 400,
(int)(200-(200/2)*.25), (int)(400-(400/2)*.25), 200, 400,
this);
//WarpImage(track2,(int)(100+turnangle*2),200,.75,false);
//g.drawImage(warptrack,0,0,this);
if (turnangle <= -35)
g.drawImage(l2,85,5,this);
if (turnangle == 0)
g.drawImage(s2,85,5,this);
if (turnangle >= 35)
g.drawImage(r2,85,5,this);
if ((turnangle>-35)&&(turnangle<=-5))
g.drawImage(l1,85,5,this);
if ((turnangle>-5)&&(turnangle<5))
g.drawImage(s1,85,5,this);
if ((turnangle>=5)&&(turnangle<35))
g.drawImage(r1,85,5,this);
g.setColor(Color.black);
g.drawString(&quot;Speed: &quot;+(double)((double)Math.round(speed)/100)+&quot; m/s&quot;,210,30);
//System.out.println(&quot;Speed: &quot;+((int)speed)/100+&quot; m/s&quot;);
g.drawString(&quot;Distance: &quot;+(int)(y/50)+&quot; m&quot;,210,45);
//System.out.println(&quot;Distance: &quot;+(int)(y/50)+&quot; m&quot;);
Graphics2D g2 = (Graphics2D)g;
g2.translate(x,250.0);
g2.rotate(Math.toRadians(angle));
g2.translate(-25.0,-50.0);
g2.drawImage(cart,0,0,this);
gg.drawImage(mybuffer,0,0,this);
}
}

public void update(Graphics g)
{
paint(g);
}

} ***
Dammit Jim, I'm a programmer, not a doctor.
 
Wow!

This is exactly what I mean. You have a ton of expensive code in your paint method. Everytime paint is invoked it has to do ALOT of image drawing and calculating. To make things worse, you repaint every 50 ms!! This is like putting molasses in your crank case (pardon the methaphor).

IMHO you are trying to do way too much in such a simple program. You really need to refactor your code into some cooperating objects.

What may help is creating drawing threads that do the image draw and use event notification to invoke the actual paint method.

You may want to find ways to streamline your code as well. You have a bunch of disconnected if statements that should really be if-else statements. For instance, if turnangle is <= -35 it certainly isn't 0 so these are dependant checks--you dont need to check both, only one can be true. You use an if-else in cases like this, not two if statements.

Goodluck! It looks like a 'fun' program. YOu should post it online so we can take a look at it when you get it finished.
 
Thanx for the compliment. Unfortunately, I can only guess how to create 'drawing threads' as you suggest, because all of my Java programs up to this point have only used single threads. Is it something like this:

Thread runner;
Thread painter;

public void run()
{
Thread thisThread = Thread.currentThread();
if (thisThread == runner)
{
//do run code
}
else if (thisThread == painter)
{
//do paint code
}
}

Great advice, by the way! Thank you for all the help. ***
Dammit Jim, I'm a programmer, not a doctor.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top