Results 1 to 11 of 11
Thread: MouseListener problem
- 12-28-2010, 12:42 PM #1
Member
- Join Date
- Dec 2010
- Posts
- 18
- Rep Power
- 0
MouseListener problem
I have got a little problem.
I made a program that makes a 200,200 window and when user clicks anywhere in this window the program will draw a rectangle in random place.
What i wanted to to is when the user clicks in the last-generated rectangle, there will be text "Gotcha!" to command line and the program will generate a new rectangle and delete the old rectangle.
First problem is that i cannot make the program to delete the old rectangle. If i use repaint() then program doesnt generate any (atleast visible) rectangle at all.
Second problem is that the Gotcha thing is not working. Program doesnt say Gotcha when i click the last generated rectangle. Instead it says Gotcha when i have luck and the new rectangle will pop up at the same place where i just clicked. I've tryed to put the "if" statement to different places but no help. (Same with the repaint())
Would be really thankful if someone could help.
My code(ListenToMouse.java):
Java Code:import java.awt.*; import java.awt.event.*; import java.applet.Applet; public class ListenToMouse extends Applet{ public ListenToMouse(){ addMouseListener(new listen()); } class listen extends MouseAdapter{ public void mousePressed(MouseEvent e){ Graphics g = ListenToMouse.this.getGraphics(); int x = (int) (180 * Math.random()); int y = (int) (180 * Math.random()); int pressX = e.getX(); int pressY = e.getY(); g.drawRect(x, y, 20, 10); if (pressX>x && (pressX-20)<x && pressY>y && (pressY-20)<y){ System.out.println("Gotcha!"); } } } public static void main(String[] args){ Frame f = new Frame("Click!"); f.setSize(200,200); f.add(new ListenToMouse()); f.setVisible(true); } }
- 12-28-2010, 02:25 PM #2
You are doing your painting entirely wrong. You should almost absolutely never use the getGraphics() method of a Component to do painting. Instead, override the paintComponent() method of a JPanel and add that JPanel to your Applet (or better yet, use a JApplet and set the JPanel as its root pane).
I suppose you could override Applet's paint() method and do the same thing, but I would go the JPanel route.
When you fix that part, then we can worry about the MouseListener part.
Painting in AWT and SwingHow to Ask Questions the Smart Way
Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!
- 12-28-2010, 08:14 PM #3
Senior Member
- Join Date
- Jul 2008
- Posts
- 125
- Rep Power
- 0
You almost always use getGraphics() when designing with AWT.
The paint(Graphics g) method automatically clears the
component unless you overide update().
A different set of rules apply if you are using swing and
JComponents
The following alterations in your code produce
results that are close enough to your description
for my efforts.
Java Code:import java.awt.*; import java.awt.event.*; import java.applet.Applet; public class ListenToMouse extends Applet{ int x ; int y ; int pressX; int pressY; Graphics g; public ListenToMouse(){ addMouseListener(new listen()); g = this.getGraphics(); } class listen extends MouseAdapter{ public void mousePressed(MouseEvent e){ pressX = e.getX(); pressY = e.getY(); if (pressX>x && (pressX-20)<x && pressY>y && (pressY-20)<y){ System.out.println("Gotcha!"); } x = (int) (180 * Math.random()); y = (int) (180 * Math.random()); repaint(); } } public void paint(Graphics g){ g.drawRect(x, y, 20, 10); } public static void main(String[] args){ Frame f = new Frame("Click!"); f.setSize(200,200); f.add(new ListenToMouse()); f.setVisible(true); } }
- 12-29-2010, 08:10 AM #4
Member
- Join Date
- Dec 2010
- Posts
- 18
- Rep Power
- 0
Super. Thanks paul pasciak! That excactly how I meant it to work.
Now that i look at your code i can undestand perfectly where i went wrong.
- 12-29-2010, 01:57 PM #5
I'm sorry, but that's just wrong. Why would that be true? Why wouldn't you just override the paint method? Hint: what would happen if you took out the global reference to the Graphics returned from getGraphics (which I would guess is actually null)? The reason your code works is actually because you don't use getGraphics!
In fact, you have told the OP to do pretty much exactly what I was suggesting, except you covered it up with false information about getGraphics(). There are so many reasons that's wrong, and it's been discussed so many times before.
So what? The correct way "around" this is to simply draw everything you want: maybe have a List of things to draw, if that's necessary. Hint- what happens if the Applet has child components?
Again, that's false. I feel sorry for the OP for having been misinformed. That's going to hurt him in the future.
And again, the reason your code works is because you are NOT using getGraphics(). You've done almost what I suggested- but it's just off enough that I guarantee the OP gets confused again in the future.How to Ask Questions the Smart Way
Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!
- 12-29-2010, 11:00 PM #6
Senior Member
- Join Date
- Jul 2008
- Posts
- 125
- Rep Power
- 0
Error Response
I made one error in the code I presented.
I used the getGraphics() method in a place where
the compiler would be 'unsure' if the component
is 'displayable'.
Two places in AWT code that produces proper references
to Graphics of a component is in the update(Graphics)
method or the paint(Graphics) method of those components.
This code will produce a null reference, and be useless
because it is not in update(Graphics) or paint(Graphics).
Java Code:public ListenToMouse(){ addMouseListener(new listen()); g = this.getGraphics(); <= produces "null" because } "this" is not yet 'displayable'
This error is harmless and has no effect on the performance
or design of the project.
In this project, by default AWT assigns a graphics context
to the paint(Graphics) method.
Few of the complaints by KevinWorkman on the help I provided
on this code are valid. Below I respond to the ones I think are
inaccurate.
-------------------------------------------
It's true because AWT uses this method to gain access to"PP: You almost always use getGraphics() when designing with AWT."
KW: Why would that be true?
the graphics context of components. AWT accesses the
graphics context of components in three ways:
1. getGraphics() method
2. getGraphicsConfiguration() method
3. by default
The most general of these used is getGraphics()
The OP's project relied on the getGraphics() method.
AWT does not have a paintComponent() method.
-------------------------------------------
I did override the paint(Graphics) method.KW: Why wouldn't you just override the paint method?
What's the argument here?
-------------------------------------------
If the Graphics reference is null, AWT will assign the defaultKW:
Hint: what would happen if you took out the global reference
to the Graphics returned from getGraphics
(which I would guess is actually null)?
The reason your code works is actually because you
don't use getGraphics!
graphics context.
-------------------------------------------
I think you are over reacting to one simple error.KW:
In fact, you have told the OP to do pretty much exactly what I
was suggesting, except you covered it up with false information
about getGraphics(). There are so many reasons that's wrong,
and it's been discussed so many times before.
But maybe you should enumerate these reasons to clarify
your statement.
I also disagree that I "told the OP to do pretty much exactly
what I was suggesting.." I see you suggesting to the OP to
convert his project to Swing, and then you would advise him
on his algorithm.
-------------------------------------------
So what because The OP bypassed update(Graphics) directly.PP: The paint(Graphics g) method automatically clears the component unless you overide update().
KW: So what?
As a result, his old rectangles were not being erased.
actually I'm impressed that he got a rendering without
using the paint(Graphics) method at all.
(technically, the update(graphics) method clears the display,
the sequence is:
repaint() => update(Graphics){clearComponent} => paint(Graphics)
)
-------------------------------------------
I disagree.KW: The correct way "around" this is to simply draw everything you want: maybe have a List of things to draw, if that's necessary.
The correct way "around" this is call repaint(), which
calls update(Graphics), which clears the screen, then
calls paint(Graphics) which draws a rectangle in this
case. That's how it works in AWT.
-------------------------------------------
If you have child components, in AWT you will probablyKW: Hint- what happens if the Applet has child components?
getGraphics() of those children or getGraphicsConfiguration().
but in this project, he didn't have child components.
what's your point?
-------------------------------------------
Unfortunately, your feelings of sorrow do not translatePP: A different set of rules apply if you are using swing and JComponents
KW: Again, that's false. I feel sorry for the OP for having been misinformed.
into usable facts.
Did I mention AWT does not have a paintComponent() method?
-------------------------------------------
Maybe, maybe not. Can I borrow your crystal ball?KW: That's going to hurt him in the future.
-------------------------------------------
Maybe by default this.getGraphics() is being used?PP: The following alterations in your code produce
results that are close enough to your description for my efforts.
KW: And again, the reason your code works is because you are NOT using getGraphics().
just as by default update(Graphics) is being used.
Now I'm being a prick.
-------------------------------------------
KW: You've done almost what I suggested- but it's just off enough that I guarantee
the OP gets confused again in the future.I did not make any Swing suggestions.............................................
PP:
Here's what you suggested:
..override the paintComponent() method of a JPanel and
add that JPanel to your Applet (or better yet, use a
JApplet and set the JPanel as its root pane).
I suppose you could override Applet's paint() method
and do the same thing
............................................
It was an AWT project.
I made AWT recomendations, then his project worked,
and you found one error of little significance.Last edited by paul pasciak; 12-29-2010 at 11:08 PM.
- 12-30-2010, 01:45 PM #7
Yep. You also didn't use the reference anyway, which is really curious. You tout the getGraphics() method, then use it incorrectly, and actually don't use it at all? That doesn't make much sense to me, and my only gripe is how misleading it is to the OP, who was already confused about how to do painting in the first place.
Okay. But that eliminates the use of getGraphics, and is what I suggested.
The reason the error is "harmless" is because you didn't actually use the reference! But the real harm is that it further confuses the OP, who now believes that getGraphics() is a fine and dandy way to do painting.
Yeah, AWT uses it. That doesn't mean the user should use it instead of going through the proper paint methods. For example, what happens when you resize the OP's original program?
I never claimed it did. What's your argument here?
The argument is that you say one thing, then do another (the thing I suggested), then say, "see! The first thing works!". No. Overriding paint() is the way to go. That's what you did. I don't know why you're still saying that getGraphics() is okay, even though in this thread alone we've demonstrated two ways it's not okay (the null reference and the resizing issue).
Oh really? So if you had tried to paint to the component using what you get back from getGraphics() at the very beginning of the program, using the code you posted, you wouldn't get a Null Pointer Exception?
Like I said, my gripe is not in the error itself, it's in how misleading that error is to the OP. I've given you two reasons that getGraphics() is bad, and google will provide you with plenty of others.
False. While Swing probably IS the way to go, if the OP absolutely has to use AWT, I told him to override the paint method, which is what you then did. I also pointed the OP to an official tutorial, which does not mention the getGraphics method at all. In fact, can you point me to an official tutorial that DOES recommend using a Component's getGraphics method to do painting?
Now I'm confused. Are you sticking with your argument that painting should be done using the getGraphics method, or are you now agreeing with me that it should be done by overriding the paint method?
Yeah... And how exactly would that help with drawing multiple rectangles, which is what the OP wants to do? Your "working" code only draws a single rectangle. How does that satisfy the OP's requirements at all? Note- I'm not challenging you to be a better spoonfeeder.
The fact is that your post was misleading because you tout the use of getGraphics, then don't actually use it, then actually override paint instead (which is what I said to do in the first place), then proclaim that that somehow proves that using getGraphics is correct. I'm not sure how that is more helpful to the OP (in the long run) than pointing him to an official tutorial.
I'm not really sure what you're trying to say here. You claim that using the getGraphics of a Component to do painting is correct, then do it the way I hinted at instead. I'm not sure how that proves your original point.
You made incorrect recommendations. The only thing correct about your code is that you override the paint method, which is what I already told him to do. I also pointed him to an official tutorial that says exactly the same thing. But on top of that, you used the getGraphics method, which while in your code didn't make a difference because you then ignored that reference for some reason, but for people like the OP who think all painting should be done using getGraphics, that's going to be very confusing. I'm simply warning him (and people who come across this post in the future) that your code works despite the call to getGraphics, not because of it.
Again- I'd be very curious to see an official tutorial that uses Component's getGraphics method to do painting.
Spoonfeeding is not helpful. Spoonfeeding incorrect answers is harmful.How to Ask Questions the Smart Way
Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!
- 12-30-2010, 07:50 PM #8
Senior Member
- Join Date
- Jul 2008
- Posts
- 125
- Rep Power
- 0
response to KevinWorkman
Maybe some day you will see how exceptionally torqued
you are over this error.
It was an error of only one line of code.
It could have been left there by mistake
and I could have simply edited it out, making
your rant appear event stranger.
I chose to highlight the error in the appropriate
manner so that readers could learn from the
error:
I made one error in the code I presented.
I used the getGraphics() method in a place where
the compiler would be 'unsure' if the component
is 'displayable'.
Two places in AWT code that produces proper references
to Graphics of a component is in the update(Graphics)
method or the paint(Graphics) method of those components.
This code will produce a null reference, and be useless
because it is not in update(Graphics) or paint(Graphics).
Code:
public ListenToMouse(){
____addMouseListener(new listen());
____g = this.getGraphics();______<= produces "null" because
}_______________________________"this" is not yet
________________________________'displayable'
This error is harmless and has no effect on the performance
or design of the project.
In this project, by default AWT assigns a graphics context
to the paint(Graphics) method.
I hope you develope more technical means
for emphasizing corrections beyond
imagined senarios and personal attacks.
- 12-31-2010, 12:44 AM #9
Member
- Join Date
- Dec 2010
- Posts
- 18
- Rep Power
- 0
Sorry guys for making such an argument with my problem. :)
One more question that i cant quite well understand.
If i have two classes. One is my main class and another one has only one method: paint(). My main class also has paint() method. Why is it so that if i call both of those methods in my main method to a single frame, one "overpaints" the other? Why dont they draw on top of eachother so i could see both paintings? Is it possible somehow to make two paint()-s made on sepperate classes to be merged into one frame?
my code:
If i compile and run this it only draws anotherGraphics(). I can understand that it draws that what has been called later than the others. But how could i make it draw them both?Java Code:import java.awt.*; import java.applet.Applet; class anotherGraphics extends Applet{ public void paint(Graphics s){ s.drawRect(10,10,10,10); } } public class mainGraphics extends Applet{ public void paint(Graphics g){ g.drawLine(100,10,100,300); g.drawLine(200,10,200,300); g.drawLine(10,100,300,100); g.drawLine(10,200,300,200); } public static void main(String[] args){ Frame f = new Frame("Program"); f.setSize(320,342); f.add(new mainGraphics()); f.add(new anotherGraphics()); f.setVisible(true); } }
- 01-03-2011, 01:10 PM #10
Hm, I doubt it. I don't really feel "exceptionally torqued". You don't know me, so it's a bit pointless to assume I feel a certain way. You provided bad advice. I pointed out that bad advice. You became defensive over it while simultaneously admitting you were wrong, which doesn't really make sense. But I'm not really that worried about it.
That's not really true either. This is the very first statement you made to the OP:
Do you still stand by that statement? Or do you now see how that can be really misleading and confusing to a newbie programmer just figuring out how painting works?
So your best argument is that your advice could have been put in by mistake, or edited out after the OP already followed your faulty advice? Interesting.
Fair enough, but then I don't understand your defensiveness when you admit that you're wrong where I said you were wrong. I'm not sure what we're debating about at all, in fact.
I pointed out several "technical" reasons your advice was faulty. And it's not an "imagined scenario" that misleading a newbie will lead to bad assumptions and more bugs in the future.How to Ask Questions the Smart Way
Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!
- 01-03-2011, 01:20 PM #11
It's not your fault.
Why do you have two different classes overriding Applet? They should probably be Components, or more likely you should use Swing instead of AWT.
According to the Frame API (Frame (Java Platform SE 6)), the default layout is BorderLayout. Basically, adding two Components to the same location of a BorderLayout causes the first Component to be replaced by the second Component. Recommended reading: Lesson: Laying Out Components Within a Container (The Java™ Tutorials > Creating a GUI With JFC/Swing)
That's not really how it works. Did you read the tutorial I posted? I suppose you could do this with a different layout manager and transparency (if that's even supported in AWT), but you almost definitely want to rethink your design.
You can either merge the paint() methods into one function of one class that extends Applet (or like I said, Component or a Swing JComponent or JPanel), or you can call the two class's paint() methods from a single Component's paint() method. In that case, that means that your two classes almost definitely shouldn't extend anything.
Let me know if that makes sense.How to Ask Questions the Smart Way
Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!
Similar Threads
-
Strategy Game: MouseListener problem
By Controloler in forum Java GamingReplies: 0Last Post: 12-10-2010, 03:11 AM -
Problem with mouseListener
By js91723 in forum AWT / SwingReplies: 12Last Post: 05-31-2010, 07:49 PM -
Problem with mouseListener (REPOST)
By js91723 in forum AWT / SwingReplies: 1Last Post: 05-31-2010, 05:15 PM -
MouseListener & GUI
By Suurisa in forum New To JavaReplies: 2Last Post: 10-27-2009, 12:52 AM -
i need help for MouseListener
By sfaxianovic in forum New To JavaReplies: 2Last Post: 08-21-2008, 03:30 AM


LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks