Results 1 to 11 of 11
  1. #1
    s3ib is offline Member
    Join Date
    Dec 2010
    Posts
    18
    Rep Power
    0

    Default 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);
    
       }
    }

  2. #2
    KevinWorkman's Avatar
    KevinWorkman is offline Crazy Cat Lady
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    3,874
    Rep Power
    8

    Default

    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 Swing
    How to Ask Questions the Smart Way
    Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!

  3. #3
    paul pasciak is offline Senior Member
    Join Date
    Jul 2008
    Posts
    125
    Rep Power
    0

    Default

    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);
       }
    }

  4. #4
    s3ib is offline Member
    Join Date
    Dec 2010
    Posts
    18
    Rep Power
    0

    Default

    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.

  5. #5
    KevinWorkman's Avatar
    KevinWorkman is offline Crazy Cat Lady
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    3,874
    Rep Power
    8

    Default

    Quote Originally Posted by paul pasciak View Post
    You almost always use getGraphics() when designing with AWT.
    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.

    Quote Originally Posted by paul pasciak View Post
    The paint(Graphics g) method automatically clears the component unless you overide update().
    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?

    Quote Originally Posted by paul pasciak View Post
    A different set of rules apply if you are using swing and JComponents
    Again, that's false. I feel sorry for the OP for having been misinformed. That's going to hurt him in the future.

    Quote Originally Posted by paul pasciak View Post
    The following alterations in your code produce
    results that are close enough to your description for my efforts.
    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!

  6. #6
    paul pasciak is offline Senior Member
    Join Date
    Jul 2008
    Posts
    125
    Rep Power
    0

    Default 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.

    -------------------------------------------
    "PP: You almost always use getGraphics() when designing with AWT."

    KW: Why would that be true?
    It's true because AWT uses this method to gain access to
    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.

    -------------------------------------------
    KW: Why wouldn't you just override the paint method?
    I did override the paint(Graphics) method.
    What's the argument here?

    -------------------------------------------
    KW:
    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!
    If the Graphics reference is null, AWT will assign the default
    graphics context.

    -------------------------------------------
    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.
    I think you are over reacting to one simple error.
    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.

    -------------------------------------------
    PP: The paint(Graphics g) method automatically clears the component unless you overide update().

    KW: So what?
    So what because The OP bypassed update(Graphics) directly.
    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)
    )

    -------------------------------------------
    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.
    I disagree.
    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.

    -------------------------------------------
    KW: Hint- what happens if the Applet has child components?
    If you have child components, in AWT you will probably
    getGraphics() of those children or getGraphicsConfiguration().
    but in this project, he didn't have child components.

    what's your point?

    -------------------------------------------
    PP: 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.
    Unfortunately, your feelings of sorrow do not translate
    into usable facts.
    Did I mention AWT does not have a paintComponent() method?

    -------------------------------------------
    KW: That's going to hurt him in the future.
    Maybe, maybe not. Can I borrow your crystal ball?

    -------------------------------------------
    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().
    Maybe by default this.getGraphics() is being used?
    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.
    ............................................
    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
    ............................................
    I did not make any Swing suggestions.
    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.

  7. #7
    KevinWorkman's Avatar
    KevinWorkman is offline Crazy Cat Lady
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    3,874
    Rep Power
    8

    Default

    Quote Originally Posted by paul pasciak View Post
    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'.
    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.

    Quote Originally Posted by paul pasciak View Post
    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.
    Okay. But that eliminates the use of getGraphics, and is what I suggested.

    Quote Originally Posted by paul pasciak View Post
    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.
    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.


    Quote Originally Posted by paul pasciak View Post
    It's true because AWT uses this method to gain access to
    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.
    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?

    Quote Originally Posted by paul pasciak View Post
    AWT does not have a paintComponent() method.
    I never claimed it did. What's your argument here?

    Quote Originally Posted by paul pasciak View Post
    I did override the paint(Graphics) method.
    What's the 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).


    Quote Originally Posted by paul pasciak View Post
    If the Graphics reference is null, AWT will assign the default graphics context.
    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?


    Quote Originally Posted by paul pasciak View Post
    I think you are over reacting to one simple error.
    But maybe you should enumerate these reasons to clarify
    your statement.
    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.

    Quote Originally Posted by paul pasciak View Post
    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.
    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?


    Quote Originally Posted by paul pasciak View Post
    So what because The OP bypassed update(Graphics) directly.
    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.
    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?

    Quote Originally Posted by paul pasciak View Post
    I disagree.
    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.
    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.

    Quote Originally Posted by paul pasciak View Post
    Unfortunately, your feelings of sorrow do not translate
    into usable facts.
    Did I mention AWT does not have a paintComponent() method?
    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.


    Quote Originally Posted by paul pasciak View Post
    Maybe by default this.getGraphics() is being used?
    just as by default update(Graphics) is being used.
    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.

    Quote Originally Posted by paul pasciak View Post
    I did not make any Swing suggestions.
    It was an AWT project.
    I made AWT recomendations, then his project worked,
    and you found one error of little significance.
    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!

  8. #8
    paul pasciak is offline Senior Member
    Join Date
    Jul 2008
    Posts
    125
    Rep Power
    0

    Default 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.

  9. #9
    s3ib is offline Member
    Join Date
    Dec 2010
    Posts
    18
    Rep Power
    0

    Default

    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:
    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);
    	}
    }
    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?

  10. #10
    KevinWorkman's Avatar
    KevinWorkman is offline Crazy Cat Lady
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    3,874
    Rep Power
    8

    Default

    Quote Originally Posted by paul pasciak View Post
    Maybe some day you will see how exceptionally torqued
    you are over this error.
    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.

    Quote Originally Posted by paul pasciak View Post
    It was an error of only one line of code.
    That's not really true either. This is the very first statement you made to the OP:

    Quote Originally Posted by paul pasciak View Post
    You almost always use getGraphics() when designing with AWT.
    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?

    Quote Originally Posted by paul pasciak View Post
    It could have been left there by mistake
    and I could have simply edited it out, making
    your rant appear event stranger.
    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.

    Quote Originally Posted by paul pasciak View Post
    I chose to highlight the error in the appropriate
    manner so that readers could learn from the
    error:
    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.

    Quote Originally Posted by paul pasciak View Post
    I hope you develope more technical means
    for emphasizing corrections beyond
    imagined senarios and personal attacks.
    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!

  11. #11
    KevinWorkman's Avatar
    KevinWorkman is offline Crazy Cat Lady
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    3,874
    Rep Power
    8

    Default

    Quote Originally Posted by s3ib View Post
    Sorry guys for making such an argument with my problem. :)
    It's not your fault.

    Quote Originally Posted by s3ib View Post
    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 do you have two different classes overriding Applet? They should probably be Components, or more likely you should use Swing instead of AWT.

    Quote Originally Posted by s3ib View Post
    Why is it so that if i call both of those methods in my main method to a single frame, one "overpaints" the other?
    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)

    Quote Originally Posted by s3ib View Post
    Why dont they draw on top of eachother so i could see both paintings?
    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.

    Quote Originally Posted by s3ib View Post
    Is it possible somehow to make two paint()-s made on sepperate classes to be merged into one frame?
    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

  1. Strategy Game: MouseListener problem
    By Controloler in forum Java Gaming
    Replies: 0
    Last Post: 12-10-2010, 03:11 AM
  2. Problem with mouseListener
    By js91723 in forum AWT / Swing
    Replies: 12
    Last Post: 05-31-2010, 07:49 PM
  3. Problem with mouseListener (REPOST)
    By js91723 in forum AWT / Swing
    Replies: 1
    Last Post: 05-31-2010, 05:15 PM
  4. MouseListener & GUI
    By Suurisa in forum New To Java
    Replies: 2
    Last Post: 10-27-2009, 12:52 AM
  5. i need help for MouseListener
    By sfaxianovic in forum New To Java
    Replies: 2
    Last Post: 08-21-2008, 03:30 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •