-
Bug
-
Resolution: Fixed
-
P2
-
1.0
-
1.0.2
-
sparc
-
solaris_2.5
-
Verified
I have my own implementation of an ImageButton widget, and I'm trying to get keyboard navigation
to work. My widget is subclassed from Canvas, and it appears to have some problems with focus/
traversal. Run the enclosed applet, and click on "awt but 1". Notice the black Motif rectangle around
the button once it gets the focus. Now hit TAB, and the focus goes to "awt but 2". Hit TAB again,
and focus goes to my custom image button. Notice it also has a black focus-rectangle. I had to
implement that myself, I assume because Canvas is not included in the tab-group by default.
But if that is the only way to implement all the missing widgets, shouldn't there be some way for
this to happen automatically? (I know, probably not, but I'm just asking).
Now hit TAB again. I'm watching for the TAB key, and I call nextFocus() on the Canvas/ImageButton
and on its parent (p = getParent() then p.nextFocus()). Neither seems to work, though maybe I'm just
doing something wrong.
Attached:
bugcase.java
IButton.java
bug.html
bugcase.java
--------------------
import java.awt.*;
import java.awt.image.*;
import java.applet.*;
public class bugcase extends Applet {
private boolean notloaded = true;
Graphics myg;
Button awt_pb1, awt_pb2;
IButton i_pb;
synchronized public void init()
{
// Space the components out a little
setLayout (new FlowLayout(FlowLayout.LEFT, 10, 10));
IButton i_pb = new IButton("info.gif");
add(i_pb);
awt_pb1 = new Button ("awt but 1");
add (awt_pb1);
awt_pb2 = new Button ("awt but 2");
add (awt_pb2);
}
}
--------------------
IButton.java
=========================
/*
* @(#)IButton.java
*/
import java.awt.*;
public class IButton extends Canvas {
private final static int MIN_WIDTH = 30;
private final static int MIN_HEIGHT = 30;
int pixelMin_, pixelMax_;
boolean isPressed_;
boolean hasFocus_;
Image currImg_;
int currImgW_, currImgH_;
int myW_, myH_;
Container p_parent;
/**
* Constructs a Button.
* @param img - The image to be displayed in this button.
*/
public IButton (String name) {
MediaTracker tracker = new MediaTracker(this);
isPressed_ = hasFocus_ = false;
if (name != null) {
currImg_ = Toolkit.getDefaultToolkit().getImage(name);
tracker.addImage(currImg_, 0);
try {
tracker.waitForID(0);
} catch (InterruptedException e) {
return;
}
}
else currImg_ = null;
if (currImg_ == null)
resize(MIN_WIDTH, MIN_HEIGHT);
else {
currImgW_ = currImg_.getWidth(this);
currImgH_ = currImg_.getHeight(this);
}
myW_ = (currImgW_ < MIN_WIDTH) ? MIN_WIDTH : currImgW_;
myH_ = (currImgH_ < MIN_HEIGHT) ? MIN_HEIGHT : currImgH_;
resize(myW_+1, myH_+1);
}
public boolean gotFocus(Event e, Object what) {
hasFocus_ = true;
System.out.println(" ***IN got focus");
System.out.println(" e.key = " + (char)e.key);
Graphics g = getGraphics();
g.setColor(Color.black);
g.drawRect(0, 0, myW_, myH_);
return super.gotFocus(e, what);
}
public boolean lostFocus(Event e, Object what) {
hasFocus_ = false;
System.out.println("lost focus");
Graphics g = getGraphics();
g.setColor(getBackground());
g.drawRect(0, 0, myW_, myH_);
return super.lostFocus(e, what);
}
public boolean handleEvent(Event e) {
if (e.id == Event.ACTION_EVENT) {
System.out.println(" action event in handleEvent()");
repaint();
/* return true; */
}
else if (e.id == Event.KEY_PRESS) {
if (e.key == /* TAB */ 9) {
int n = p_parent.countComponents();
System.out.println(n + " components in panel");
for(int i=0; i<n; i++)
p_parent.nextFocus();
/*
if (p_parent.getComponent(i) == this) {
System.out.println("Found at position " + i);
Component m = p_parent.getComponent(i+1);
m.requestFocus();
break;
}
*/
}
}
else if (e.id == Event.KEY_RELEASE) {
System.out.println("got key release");
}
return super.handleEvent(e);
}
/**
* Sets the height of the Button.
* @param num - The new height.
* */
public void SetHeight (int num) {
if (num < MIN_HEIGHT)
num = MIN_HEIGHT;
resize(size().width, num);
repaint();
}
/**
* Sets the width of the Button.
* @param num - The new width.
* */
public void SetWidth (int num) {
if (num < MIN_WIDTH)
num = MIN_WIDTH;
resize(num, size().height);
repaint();
}
public Dimension minimumSize() {
return size();
}
public Dimension preferredSize() {
return size();
}
/**
* Sets the image which will be displayed in the button.
* @param pix - The new image.
* */
public void SetImage (Image pix) {
if (pix == null)
return;
currImg_ = pix;
currImgW_ = currImg_.getWidth(this);
currImgH_ = currImg_.getHeight(this);
myW_ = (currImgW_ < MIN_WIDTH) ? MIN_WIDTH : currImgW_;
myH_ = (currImgH_ < MIN_HEIGHT) ? MIN_HEIGHT : currImgH_;
resize(myW_+1, myH_+1);
repaint();
}
/**
* An internal method used to handle repaint events.
*/
public void paint(Graphics g) {
if (p_parent == null)
p_parent = this.getParent();
if (hasFocus_) {
g.setColor(Color.black);
g.drawRect(0, 0, myW_, myH_);
}
Color c = getBackground();
g.setColor(c);
if (isPressed_)
{
g.setColor(c.brighter());
g.fill3DRect(1, 1, myW_, myH_, false);
}
else
g.fill3DRect(1, 1, myW_-1, myH_-1, true);
g.drawImage(currImg_, (myW_-currImgW_)/2, (myH_-currImgH_)/2, this);
}
/**
* An internal method used to handle mouse down events.
*/
public boolean mouseDown (Event e, int x, int y) {
System.out.println("IButton: mouseDown");
isPressed_ = true;
requestFocus();
hasFocus_ = true;
paint(getGraphics());
return true;
}
/**
* An internal method used to handle mouse up events.
*/
public boolean mouseUp (Event e, int x, int y) {
System.out.println("IButton: mouseUp");
isPressed_ = false;
paint(getGraphics());
Event event = new Event(this, Event.ACTION_EVENT, (Object) "IButton");
return true;
}
}
=========================
bug.html
__________________________________
<html>
<applet code=bugcase.class width=420 height=220>
</applet>
</html>
__________________________________
to work. My widget is subclassed from Canvas, and it appears to have some problems with focus/
traversal. Run the enclosed applet, and click on "awt but 1". Notice the black Motif rectangle around
the button once it gets the focus. Now hit TAB, and the focus goes to "awt but 2". Hit TAB again,
and focus goes to my custom image button. Notice it also has a black focus-rectangle. I had to
implement that myself, I assume because Canvas is not included in the tab-group by default.
But if that is the only way to implement all the missing widgets, shouldn't there be some way for
this to happen automatically? (I know, probably not, but I'm just asking).
Now hit TAB again. I'm watching for the TAB key, and I call nextFocus() on the Canvas/ImageButton
and on its parent (p = getParent() then p.nextFocus()). Neither seems to work, though maybe I'm just
doing something wrong.
Attached:
bugcase.java
IButton.java
bug.html
bugcase.java
--------------------
import java.awt.*;
import java.awt.image.*;
import java.applet.*;
public class bugcase extends Applet {
private boolean notloaded = true;
Graphics myg;
Button awt_pb1, awt_pb2;
IButton i_pb;
synchronized public void init()
{
// Space the components out a little
setLayout (new FlowLayout(FlowLayout.LEFT, 10, 10));
IButton i_pb = new IButton("info.gif");
add(i_pb);
awt_pb1 = new Button ("awt but 1");
add (awt_pb1);
awt_pb2 = new Button ("awt but 2");
add (awt_pb2);
}
}
--------------------
IButton.java
=========================
/*
* @(#)IButton.java
*/
import java.awt.*;
public class IButton extends Canvas {
private final static int MIN_WIDTH = 30;
private final static int MIN_HEIGHT = 30;
int pixelMin_, pixelMax_;
boolean isPressed_;
boolean hasFocus_;
Image currImg_;
int currImgW_, currImgH_;
int myW_, myH_;
Container p_parent;
/**
* Constructs a Button.
* @param img - The image to be displayed in this button.
*/
public IButton (String name) {
MediaTracker tracker = new MediaTracker(this);
isPressed_ = hasFocus_ = false;
if (name != null) {
currImg_ = Toolkit.getDefaultToolkit().getImage(name);
tracker.addImage(currImg_, 0);
try {
tracker.waitForID(0);
} catch (InterruptedException e) {
return;
}
}
else currImg_ = null;
if (currImg_ == null)
resize(MIN_WIDTH, MIN_HEIGHT);
else {
currImgW_ = currImg_.getWidth(this);
currImgH_ = currImg_.getHeight(this);
}
myW_ = (currImgW_ < MIN_WIDTH) ? MIN_WIDTH : currImgW_;
myH_ = (currImgH_ < MIN_HEIGHT) ? MIN_HEIGHT : currImgH_;
resize(myW_+1, myH_+1);
}
public boolean gotFocus(Event e, Object what) {
hasFocus_ = true;
System.out.println(" ***IN got focus");
System.out.println(" e.key = " + (char)e.key);
Graphics g = getGraphics();
g.setColor(Color.black);
g.drawRect(0, 0, myW_, myH_);
return super.gotFocus(e, what);
}
public boolean lostFocus(Event e, Object what) {
hasFocus_ = false;
System.out.println("lost focus");
Graphics g = getGraphics();
g.setColor(getBackground());
g.drawRect(0, 0, myW_, myH_);
return super.lostFocus(e, what);
}
public boolean handleEvent(Event e) {
if (e.id == Event.ACTION_EVENT) {
System.out.println(" action event in handleEvent()");
repaint();
/* return true; */
}
else if (e.id == Event.KEY_PRESS) {
if (e.key == /* TAB */ 9) {
int n = p_parent.countComponents();
System.out.println(n + " components in panel");
for(int i=0; i<n; i++)
p_parent.nextFocus();
/*
if (p_parent.getComponent(i) == this) {
System.out.println("Found at position " + i);
Component m = p_parent.getComponent(i+1);
m.requestFocus();
break;
}
*/
}
}
else if (e.id == Event.KEY_RELEASE) {
System.out.println("got key release");
}
return super.handleEvent(e);
}
/**
* Sets the height of the Button.
* @param num - The new height.
* */
public void SetHeight (int num) {
if (num < MIN_HEIGHT)
num = MIN_HEIGHT;
resize(size().width, num);
repaint();
}
/**
* Sets the width of the Button.
* @param num - The new width.
* */
public void SetWidth (int num) {
if (num < MIN_WIDTH)
num = MIN_WIDTH;
resize(num, size().height);
repaint();
}
public Dimension minimumSize() {
return size();
}
public Dimension preferredSize() {
return size();
}
/**
* Sets the image which will be displayed in the button.
* @param pix - The new image.
* */
public void SetImage (Image pix) {
if (pix == null)
return;
currImg_ = pix;
currImgW_ = currImg_.getWidth(this);
currImgH_ = currImg_.getHeight(this);
myW_ = (currImgW_ < MIN_WIDTH) ? MIN_WIDTH : currImgW_;
myH_ = (currImgH_ < MIN_HEIGHT) ? MIN_HEIGHT : currImgH_;
resize(myW_+1, myH_+1);
repaint();
}
/**
* An internal method used to handle repaint events.
*/
public void paint(Graphics g) {
if (p_parent == null)
p_parent = this.getParent();
if (hasFocus_) {
g.setColor(Color.black);
g.drawRect(0, 0, myW_, myH_);
}
Color c = getBackground();
g.setColor(c);
if (isPressed_)
{
g.setColor(c.brighter());
g.fill3DRect(1, 1, myW_, myH_, false);
}
else
g.fill3DRect(1, 1, myW_-1, myH_-1, true);
g.drawImage(currImg_, (myW_-currImgW_)/2, (myH_-currImgH_)/2, this);
}
/**
* An internal method used to handle mouse down events.
*/
public boolean mouseDown (Event e, int x, int y) {
System.out.println("IButton: mouseDown");
isPressed_ = true;
requestFocus();
hasFocus_ = true;
paint(getGraphics());
return true;
}
/**
* An internal method used to handle mouse up events.
*/
public boolean mouseUp (Event e, int x, int y) {
System.out.println("IButton: mouseUp");
isPressed_ = false;
paint(getGraphics());
Event event = new Event(this, Event.ACTION_EVENT, (Object) "IButton");
return true;
}
}
=========================
bug.html
__________________________________
<html>
<applet code=bugcase.class width=420 height=220>
</applet>
</html>
__________________________________