I've tried to make a class that allows one to annotate an image
by clicking with the mouse; each mouse click will place a little "X"
or other graphic at that location. The class is user-configurable, with
callbacks to handle what happens when you click, and a list
of callbacks to draw the graphics.
The puzzle: after I click on the image, the repaint draws
the image origin _at the location of the mouse click_,
rather than at 0,0, though I do not ask it to do this.
I've produced a simplified example, where the "image" is a just a
red square. There is a base class "GRJImage" with a paintComponent
method that does this:
Graphics g2 = g.create();
g2.setColor(Color.red);
g2.fillRect(0, 0, getWidth(), getHeight()); // testing, show the
problem
Then a derived class "GRJTestImage" handles all the mouse callback stuff.
It's paintComponent() is like this:
Graphics g2 = g1.create(); // save the context
super.paintComponent(g1); // draw the red rectangle
int npts = _drawList.size(); //d raw the graphics
for( int i = 0; i < npts; i++ ) {
Drawable d = (Drawable)_drawList.get(i); d.draw(g2);
}
g2.dispose();
I do not see what is causing the fillRect to draw at a location
other than 0,0! And various fiddling with copying the Graphics
object and reusing it has not resolved it.
(Btw, this is a followup to a question several months ago...
Great thanks to several people who pointed out that I should be
overriding paintComponent() rather than paint(). I read through
the rendering tutorials suggested and rewrote the code, but still
have the same problem. Took a couple months off hoping it would
just go away... :).
Here are two files that isolate the problem. If you compile and run,
you will see a red rectangle. Increase the window size.
Then click inside the window, and the red rectangle will
move so it's upper-left is at the mouse location, rather
than covering the whole window.
This is with jdk1.4 on 10.3.8, though the problem has been with me
on earlier releases, and I believe it is my programming rather
than an apple bug.
public Dimension getPreferredSize()
{
return new Dimension(_xres, _yres);
}
public void paintComponent(Graphics g)
{
Graphics g2 = g.create();
if (_verbose > 1) System.out.println("GRJImage.paint");
if (isOpaque()) {
//&& ((_xres != getWidth()) || (_yres != getHeight()))) {
// this is the specified desired behaviour for paintComponent,
// but is inefficient, so warn if we end up doing it.
System.out.println("PAINTING BACKGROUND "+_xres+" "+getWidth());
g2.setColor(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
}
g2.setColor(Color.red);
g2.fillRect(0, 0, getWidth(), getHeight()); // testing, show the
problem
g2.dispose();
} //paintComponent
} //GRJImage
----------------GRJTestImage.java----------------
// GRJTestImage.java - debug the interface mouseclick puzzle
/**
* displays an image, with manipulatible drawn overlays.
*
* _drawList is an arrayList of things to draw, each is passed
* the Graphics2D and maintains its own location. Each also
* has a clicked() method that gets called when the image is clicked
* near it.
*
* _clickList is a list of callbacks to call on each mouseClick.
* Register something with this in order to get something onto the
drawlist.
*
* Example usage:
* create an OnClick whose call() method creates a drawable
* located at the click location, adds it to the drawList,
* and optionally removes itself from the clickList.
*
* <pre>
* GRJTestImage p = new GRJTestImage(pic);
p.addDrawable(_trackMarker);
GRJTestImage.OnClick c = new GRJTestImage.OnClick() {
public void call(int x, int y) {
Drawable d = new GRJTestImage.plusMarker(x,y, Color.red);
p.addDrawable(d);
}
};
p.addOnClick(c);
*/
public class GRJTestImage extends GRJImage
{
final GRJTestImage _p;
ArrayList _drawList = new ArrayList();
ArrayList _clickList = new ArrayList();
int _lx, _ly; // location of last mouse click
// an OnClick handler is a high level click dispatcher
// c.f. drawable, which also does mouse handling, but is intended
// to be a single object such as a point or curve.
public interface OnClick
{
void call(int x, int y);
}
public void addOnClick(OnClick c)
{
System.out.println("adding clickable "+c);
_clickList.add(c);
}
public void removeOnClick(OnClick c)
{
System.out.println("removing clickable "+c);
_clickList.remove(c);
}
public void clearOnClick()
{
_clickList.clear();
}
public interface Drawable
{
// GRJTestImage makes a copy of g, so this method does not need
// to restore its state, at least if the next draw() knows
// how to reset what this one changed
void draw(Graphics g);
// formerly had getX/getY to let the caller see if a mouse click is
// near this object. That does not work for a polyline, so
// have the object itself do the test.
// int getX(); int getY();
// did this event hit near us == should we be called with
click/press/...
boolean hit(MouseEvent evt);
if (false)
setDebugGraphicsOptions(DebugGraphics.LOG_OPTION|
//DebugGraphics.FLASH_OPTION|
DebugGraphics.BUFFERED_OPTION);
_p = this;
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt)
{
System.out.println("mouse clicked.");
super.mouseClicked(evt);
_lx = evt.getX();
_ly = evt.getY();
// call all the "clickables"
for( int i = 0; i < _clickList.size(); i++ ) {
System.out.println("calling clickable #"+i+", "+_lx+","+_ly);
OnClick c = (OnClick)_clickList.get(i);
c.call(_lx, _ly);
}
// note call all the drawables also, let them handle
// mouse events as well!
System.out.println("calling drawables.click");
for( int i = 0; i < _drawList.size(); i++ ) {
System.out.println("calling drawable #"+i);
Drawable d = (Drawable)_drawList.get(i);
if (d.hit(evt)) d.click(evt, _p);
else System.out.println("missed hit");
}
repaint();
} //mouseClicked
public void mousePressed(MouseEvent evt)
{
System.out.println("mouse pressed.");
super.mousePressed(evt);
System.out.println("calling drawables.press");
if (false)
for( int i = 0; i < _drawList.size(); i++ ) {
System.out.println("calling drawable #"+i);
Drawable d = (Drawable)_drawList.get(i);
if (d.hit(evt)) d.press(evt, _p);
}
repaint();
} //mousePressed
public void mouseReleased(MouseEvent evt)
{
System.out.println("mouse released.");
super.mouseReleased(evt);
System.out.println("calling drawables.release");
for( int i = 0; i < _drawList.size(); i++ ) {
System.out.println("calling drawable #"+i);
Drawable d = (Drawable)_drawList.get(i);
if (d.hit(evt)) d.release(evt, _p);
}
repaint();
} //mouseReleased
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
System.out.println("calling drawables.drag");
for( int i = 0; i < _drawList.size(); i++ ) {
System.out.println("calling drawable #"+i);
Drawable d = (Drawable)_drawList.get(i);
if (d.hit(e)) d.drag(e, _p);
}
}
});
} //constructor
public void paintComponent(Graphics g1)
{
if (_verbose > 1) System.out.println("GRJTestImage.paint");
Graphics g2 = g1.create();
super.paintComponent(g1);
int npts = _drawList.size();
for( int i = 0; i < npts; i++ ) {
System.out.println("calling drawable #"+i);
Drawable d = (Drawable)_drawList.get(i);
d.draw(g2);
}
public static GRJTestImage showme()
{
JFrame f = new JFrame("foo");
GRJTestImage p = new GRJTestImage();
f.getContentPane().add(p);
//f.setSize(xres+20, yres+20);
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
f.setVisible(true);
f.repaint();
return p;
} //showme
public static void main(String[] cmdline)
{
System.out.println("GRJTestImage");
final GRJTestImage p = GRJTestImage.showme();
OnClick c = new OnClick() {
public void call(int x, int y) {
Drawable d = new GRJTestImage.plusMarker(x,y, Color.red);
p.addDrawable(d);
p.removeOnClick(this);
}
};
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Java-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/java-dev/email@hidden