-
Bug
-
Resolution: Fixed
-
P2
-
1.0, 1.0.1
-
1.0.2
-
x86, sparc
-
solaris_2.5, windows_nt
-
Verified
All platforms: Container.locate(int x, int y) makes the coordinates that it sends to
Component.inside(int x, int y) relative to the component, not itself.
Component.inside(int x, int y) assumes that the coordinates that it receives are
relative to its parent, and so converts them to be relative to itself.
The result is that on a 3 X 3 grid, you can never locate the items on the last column
or row.
Steps to reproduce
Compile and run the attached code
Move the mouse over each of the buttons
// Note the output to System.out, the program never locates the last button
// in the applet
import java.awt.*;
import java.applet.Applet;
public class InsideTest extends Applet
{
private final int ROWS = 4;
private final int COLS = 3;
public void init()
{
setLayout( new GridLayout(ROWS, COLS) );
for (int i = 1; i <= ROWS * COLS; ++i )
{
add( new Button( Integer.toString( i ) ) );
}
resize(300, 300);
}
public boolean mouseMove(Event ev, int x, int y)
{
Component comp = locate(x, y);
System.out.println("Coordinates: X: " + x + " Y: " + y);
System.out.println("Component: " + comp);
return super.mouseMove(ev, x, y);
}
public static void main(String argv[])
{
AppletFrame.startApplet("InsideTest", "Component.inside() Test", argv);
}
/* I'm commenting this out to make it easier to reproduce the problem.
* Once you've reproduced the problem, try using this version of
* locate.
*
public Component locate(int x, int y)
{
if ( !inside(x, y) )
{
return null;
}
for (int i = 0 ; i < this.countComponents() ; i++)
{
Component comp = this.getComponent(i);
if ( (comp != null) && comp.inside(x, y) )
{
return comp;
}
}
return this;
} // end locate()
*
* End of commented out method locate()
*/
} // end class InsideTest
/* Generic Applet to Application Frame
* @(#)AppletFrame.java 1.4 02 Dec 1995 15:28:07
* @author Kevin A. Smith
*
* Here's a sample main() function that you can add to your applet class:
*
* public static void main(String args[])
* {
* AppletFrame.startApplet( <ClassName>, "Application Title");
* }
*
* The class AppletFrame provides a simple AWT Frame window for running
* applications.
*
*/
import java.awt.Frame;
import java.awt.Event;
import java.awt.Dimension;
import java.applet.Applet;
// Applet to Application Frame window
class AppletFrame extends Frame
{
public static void startApplet(String className,
String title,
String args[])
{
// local variables
Applet a;
Dimension appletSize;
try
{
// create an instance of your applet class
a = (Applet) Class.forName(className).newInstance();
}
catch (ClassNotFoundException e) { return; }
catch (InstantiationException e) { return; }
catch (IllegalAccessException e) { return; }
// initialize the applet
a.init();
a.start();
// create new application frame window
AppletFrame f = new AppletFrame(title);
// add applet to frame window
f.add("Center", a);
// resize frame window to fit applet
// assumes that the applet sets its own size
// otherwise, you should set a specific size here.
appletSize = a.size();
f.pack();
f.resize(appletSize);
// show the window
f.show();
} // end startApplet()
// constructor needed to pass window title to class Frame
public AppletFrame(String name)
{
// call java.awt.Frame(String) constructor
super(name);
}
// needed to allow window close
public boolean handleEvent(Event e)
{
// Window Destroy event
if (e.id == Event.WINDOW_DESTROY)
{
// exit the program
System.exit(0);
return true;
}
// it's good form to let the super class look at any
// unhandled events
return super.handleEvent(e);
} // end handleEvent()
} // end class AppletFrame
The description field as copied from bug report 1244154 follows:
From: Larry Liang <###@###.###>
This does not look like form output to me.
Hi,
There is a bug in the Container.java class,
Container.class line 349
if ((comp != null) && comp.inside(x - comp.x, y - comp.y)){
the inside() call should be:
comp.inside(x, y)
because it expects coordinates of the parent object, not relative to
the current component. This bug caused deliverEvent() to deliver
events to the wrong component. Thanks.
Larry
// This is an example program to show two bugs in AWT:
// The Container.locate() function and
// the Component.inside() function
//
// Container.locate(x, y) is supposed to return the component where the
// (x, y) coordinate falls. But in the call to comp.inside(), it incorrectly
// subtracted the location x and y value from the (x, y) parameter
// respectively, and causes the component returned by the locate function
// to be incorrect.
//
// Component.inside(x, y) is supposed to return true if the (x, y) point
// is inside the component, and false otherwise. But it fails to check
// if the (x, y) is less than the left edge and top edge. Therefore if
// the x < location().x or y < location().y, it still returns true.
//
// Usage:
// start the applet
// click in any one of the box
// The output should be:
// print the current box number
// print the box number to the right of current box
// iterate through all components of the parent, and
// print the box number of all those that have inside(x,y)
// returning a true value. If the inside function is
// correct, there should only be one box, the current box.
//
// Fix:
// In file "Container.java" line 349, replace:
// if ((comp != null) && comp.inside(x - comp.x, y - comp.y)) {
// with:
// if ((comp != null) && comp.inside(x, y)) {
//
// In file "Component.java" line 804, replace:
// return (x >= 0) && ((x-this.x) < width) && (y >= 0) && ((y-this.y) < height);
// with:
// return ((x-this.x) >= 0) && ((x-this.x) < width) && ((y-this.y) >= 0) && ((y-this.y) < height);
//
import java.awt.*;
import java.applet.*;
public class awtbug extends Applet {
static int total = 9;
public awtbug() {
setLayout(new GridLayout(1, total));
for(int i = 0; i < total; i++) {
add(new TestButton(i));
}
}
}
class TestButton extends Canvas {
public TestButton(int num) {
this.num = num;
}
public void paint(Graphics g) {
g.drawRect(0, 0, size().width - 2, size().height - 2);
g.drawString(Integer.toString(num), size().width / 2,
size().height / 2);
}
public boolean mouseDown(Event e, int x, int y) {
identify();
Container parent = getParent();
if(num < awtbug.total - 1) {
e.translate(location().x, location().y);
TestButton sibling = (TestButton) parent.locate(e.x+size().width, e.y);
System.out.print("My right hand button is: ");
sibling.identify();
}
System.out.println("("+e.x+","+e.y+") is in the following boxes:");
int cnt = parent.countComponents();
for(int i = 0; i < cnt; i++) {
TestButton box = (TestButton) parent.getComponent(i);
if(box.inside(e.x, e.y)) {
box.identify();
}
}
return(false);
}
public void identify() {
System.out.println("Button " + num);
}
int num;
}
Component.inside(int x, int y) relative to the component, not itself.
Component.inside(int x, int y) assumes that the coordinates that it receives are
relative to its parent, and so converts them to be relative to itself.
The result is that on a 3 X 3 grid, you can never locate the items on the last column
or row.
Steps to reproduce
Compile and run the attached code
Move the mouse over each of the buttons
// Note the output to System.out, the program never locates the last button
// in the applet
import java.awt.*;
import java.applet.Applet;
public class InsideTest extends Applet
{
private final int ROWS = 4;
private final int COLS = 3;
public void init()
{
setLayout( new GridLayout(ROWS, COLS) );
for (int i = 1; i <= ROWS * COLS; ++i )
{
add( new Button( Integer.toString( i ) ) );
}
resize(300, 300);
}
public boolean mouseMove(Event ev, int x, int y)
{
Component comp = locate(x, y);
System.out.println("Coordinates: X: " + x + " Y: " + y);
System.out.println("Component: " + comp);
return super.mouseMove(ev, x, y);
}
public static void main(String argv[])
{
AppletFrame.startApplet("InsideTest", "Component.inside() Test", argv);
}
/* I'm commenting this out to make it easier to reproduce the problem.
* Once you've reproduced the problem, try using this version of
* locate.
*
public Component locate(int x, int y)
{
if ( !inside(x, y) )
{
return null;
}
for (int i = 0 ; i < this.countComponents() ; i++)
{
Component comp = this.getComponent(i);
if ( (comp != null) && comp.inside(x, y) )
{
return comp;
}
}
return this;
} // end locate()
*
* End of commented out method locate()
*/
} // end class InsideTest
/* Generic Applet to Application Frame
* @(#)AppletFrame.java 1.4 02 Dec 1995 15:28:07
* @author Kevin A. Smith
*
* Here's a sample main() function that you can add to your applet class:
*
* public static void main(String args[])
* {
* AppletFrame.startApplet( <ClassName>, "Application Title");
* }
*
* The class AppletFrame provides a simple AWT Frame window for running
* applications.
*
*/
import java.awt.Frame;
import java.awt.Event;
import java.awt.Dimension;
import java.applet.Applet;
// Applet to Application Frame window
class AppletFrame extends Frame
{
public static void startApplet(String className,
String title,
String args[])
{
// local variables
Applet a;
Dimension appletSize;
try
{
// create an instance of your applet class
a = (Applet) Class.forName(className).newInstance();
}
catch (ClassNotFoundException e) { return; }
catch (InstantiationException e) { return; }
catch (IllegalAccessException e) { return; }
// initialize the applet
a.init();
a.start();
// create new application frame window
AppletFrame f = new AppletFrame(title);
// add applet to frame window
f.add("Center", a);
// resize frame window to fit applet
// assumes that the applet sets its own size
// otherwise, you should set a specific size here.
appletSize = a.size();
f.pack();
f.resize(appletSize);
// show the window
f.show();
} // end startApplet()
// constructor needed to pass window title to class Frame
public AppletFrame(String name)
{
// call java.awt.Frame(String) constructor
super(name);
}
// needed to allow window close
public boolean handleEvent(Event e)
{
// Window Destroy event
if (e.id == Event.WINDOW_DESTROY)
{
// exit the program
System.exit(0);
return true;
}
// it's good form to let the super class look at any
// unhandled events
return super.handleEvent(e);
} // end handleEvent()
} // end class AppletFrame
The description field as copied from bug report 1244154 follows:
From: Larry Liang <###@###.###>
This does not look like form output to me.
Hi,
There is a bug in the Container.java class,
Container.class line 349
if ((comp != null) && comp.inside(x - comp.x, y - comp.y)){
the inside() call should be:
comp.inside(x, y)
because it expects coordinates of the parent object, not relative to
the current component. This bug caused deliverEvent() to deliver
events to the wrong component. Thanks.
Larry
// This is an example program to show two bugs in AWT:
// The Container.locate() function and
// the Component.inside() function
//
// Container.locate(x, y) is supposed to return the component where the
// (x, y) coordinate falls. But in the call to comp.inside(), it incorrectly
// subtracted the location x and y value from the (x, y) parameter
// respectively, and causes the component returned by the locate function
// to be incorrect.
//
// Component.inside(x, y) is supposed to return true if the (x, y) point
// is inside the component, and false otherwise. But it fails to check
// if the (x, y) is less than the left edge and top edge. Therefore if
// the x < location().x or y < location().y, it still returns true.
//
// Usage:
// start the applet
// click in any one of the box
// The output should be:
// print the current box number
// print the box number to the right of current box
// iterate through all components of the parent, and
// print the box number of all those that have inside(x,y)
// returning a true value. If the inside function is
// correct, there should only be one box, the current box.
//
// Fix:
// In file "Container.java" line 349, replace:
// if ((comp != null) && comp.inside(x - comp.x, y - comp.y)) {
// with:
// if ((comp != null) && comp.inside(x, y)) {
//
// In file "Component.java" line 804, replace:
// return (x >= 0) && ((x-this.x) < width) && (y >= 0) && ((y-this.y) < height);
// with:
// return ((x-this.x) >= 0) && ((x-this.x) < width) && ((y-this.y) >= 0) && ((y-this.y) < height);
//
import java.awt.*;
import java.applet.*;
public class awtbug extends Applet {
static int total = 9;
public awtbug() {
setLayout(new GridLayout(1, total));
for(int i = 0; i < total; i++) {
add(new TestButton(i));
}
}
}
class TestButton extends Canvas {
public TestButton(int num) {
this.num = num;
}
public void paint(Graphics g) {
g.drawRect(0, 0, size().width - 2, size().height - 2);
g.drawString(Integer.toString(num), size().width / 2,
size().height / 2);
}
public boolean mouseDown(Event e, int x, int y) {
identify();
Container parent = getParent();
if(num < awtbug.total - 1) {
e.translate(location().x, location().y);
TestButton sibling = (TestButton) parent.locate(e.x+size().width, e.y);
System.out.print("My right hand button is: ");
sibling.identify();
}
System.out.println("("+e.x+","+e.y+") is in the following boxes:");
int cnt = parent.countComponents();
for(int i = 0; i < cnt; i++) {
TestButton box = (TestButton) parent.getComponent(i);
if(box.inside(e.x, e.y)) {
box.identify();
}
}
return(false);
}
public void identify() {
System.out.println("Button " + num);
}
int num;
}
- duplicates
-
JDK-1244154 fp.bugs 4175 Container.locate call to inside can cause misdelivered events
- Closed