# Wenn Mauszeiger in der Nähe vom Kreis, soll Kreis an eine andere Stelle springen



## kenux (16. Jun 2009)

Hallo,

in meinem AWT/Swing-Programm soll beim Start ein Kreis sein. Wenn man mit dem Mauszeiger sich dem Kreis bis auf wenige Pixel nähert, soll der Kreis an eine zufällig generierte Stelle springen.
Ich habe schonmal folgenden Code geschrieben, aber leider weiß ich jetzt nicht wie ich das alles weiterführen kann:


```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;


// Klasse MausPunktFarbe
class Kreis2 extends JFrame {
	
	// Konstruktor
	public Kreis2() 
	{
		// setzt Fenstertitel
		super("Kreis2");
		// Hintergrundfarbe
		setBackground(Color.white);
		// Groesse Panel
		setSize(new Dimension(300, 300));
		// Fenstergroesse nicht veraenderbar
		setResizable(false);
		// Reaktion auf Programm beenden
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// Instanz von Panel
		Panel malen = new Panel();
		// Panel ins Zentrum setzen
		add(malen, BorderLayout.CENTER);
		// den Frame anzeigen
		setVisible(true);
	}

public static void main(String[] args) {
	// erzeuge eine neue Instanz des MausPunktFarbe-JFrames
	new Kreis2();	
	}
}// Ende Klasse;


// Klasse Panel
class Panel extends JPanel implements MouseListener {
	
	private int z_x;
	private int z_y;
	
	// Konstruktor
	public Panel() 
	{
		// MouseListener hinzufuegen
		addMouseListener(this);
	}
	
	public void paint(Graphics g) {
    setBackground(Color.white);

    // Kreis zeichnen
    //g.setColor(Color.black);
    //g.fillOval(60,60,20,20);
	
	
	// Zufallsstelle
	z_x = (int) (Math.random()*30);
	z_y = (int) (Math.random()*30);
	g.fillOval(z_x,z_y,20,20);
	
  }
	
	// Maus-Klick-Event
	public void mouseEntered(MouseEvent me) 
	{
		int mx = me.getX();
		int my = me.getY();
		
		// Maustaste links
		if (z_x == MouseEvent.BUTTON1 && z_y == MouseEvent.BUTTON1) {
			
			//repaint();
			System.out.println("Hallo");
		}
	
	}
	
// Dummies
public void mousePressed(MouseEvent me) {}
public void mouseReleased(MouseEvent me) {}
public void mouseClicked(MouseEvent me) {}
public void mouseExited(MouseEvent me) {}
}//Ende Klasse;
```


----------



## manunana89 (16. Jun 2009)

Theoretisch könntest du nach Berührung des Kreises oder Balles doch einfach die Variablen z_x und z_y per random neu bestimmen lassen und den Ball neu zeichen lassen.


----------



## kenux (16. Jun 2009)

manunana89 hat gesagt.:


> Theoretisch könntest du nach Berührung des Kreises oder Balles doch einfach die Variablen z_x und z_y per random neu bestimmen lassen und den Ball neu zeichen lassen.



wie kann ich denn z.b. abfragen ob mit dem Mauszeiger genau auf den Kreis geklickt wurde?


----------



## Michael... (16. Jun 2009)

kenux hat gesagt.:


> wie kann ich denn z.b. abfragen ob mit dem Mauszeiger genau auf den Kreis geklickt wurde?


Wenn Du mit auf den Kreis auf die Kreislinie und in den Kreis meinst, kannst Du z.B. ein Arc2D.Float verwenden. Diese Klasse besitzt die Methode contains(...) mit der Du überrprüfen kannst, ob der Mausklick innerhalb des Kreises war.


----------



## Ebenius (16. Jun 2009)

Anmerkungen zu Deinem Beispiel oben: 
Dein Panel ist ein JComponent-Derivat. Überschreib nicht _paint_ sondern _paintComponent_ zum Zeichnen.
Zeile 52 ist unsinn. Die Hintergrundfarbe einer Komponente setzt man nicht in der paint/paintComponent-Methode. Außerdem zeichnet die Komponente überhaupt keinen Hintergrund, weil Du die super-paint-Methode nicht aufrufst (und den Hintergrund auch nicht selbst zeichnest). So in etwa sollte die paint-Methode aussehen:
[java=51]protected void paintComponent(Graphics g) {
    super.paintComponent(g); // paints the background

    // Kreis zeichnen
    //g.setColor(Color.black);
    //g.fillOval(60,60,20,20);


    // Zufallsstelle
    z_x = (int) (Math.random()*30);
    z_y = (int) (Math.random()*30);
    g.fillOval(z_x,z_y,20,20);

}[/code]
Die Farbe kann man dann im Konstruktor setzen:
[java=44]// Konstruktor
public Panel()
{
    // MouseListener hinzufuegen
    addMouseListener(this);
    setBackground(Color.WHITE);
}[/code]
Zeile 73 funktioniert so auch nicht. So prüft man, ob die linke Maustaste gedrückt wurde: [java=72]// Maustaste links
if (SwingUtilities.isLeftMouseButton(me)) {[/code]
Alternativ kann man auch ohne die Utilities-Klasse prüfen (sollte man sich aber sparen): [java=72]// Maustaste links
if ((anEvent.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {[/code]



kenux hat gesagt.:


> wie kann ich denn z.b. abfragen ob mit dem Mauszeiger genau auf den Kreis geklickt wurde?


Ich würde dazu das Paket java.awt.geom benutzen. Dieses Paket bietet Dir einfache graphische Objekte. Die Objekte lassen sich zeichnen, können aber auch überprüfen, ob sie sich mit anderen Objekten schneiden, ob ein Punkt im inneren des Objektes liegt, usw. Dazu würdest Du die Member-Variablen z_x und z_y durch ein Arc2D.Float ersetzen. Hier mal ein Beispiel mit einem zentrierten Kreis in einem Frame. Wenn die Maus gedrückt, bewegt, ... wird, gibt's auf der Konsole die Information, ob der Zeiger sich im Kreis oder außerhalb befindet:

```
/* (@)CirclePaint.java */

/* Copyright 2009 Sebastian Haufe

 * Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       [url]http://www.apache.org/licenses/LICENSE-2.0[/url]

 * Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

package com.ebenius;

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Arc2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class CirclePaint extends JPanel
  implements MouseListener, MouseMotionListener {

  private Arc2D.Float circle;

  /** Creates a new {@code CirclePaint}. */
  public CirclePaint() {
    circle = new Arc2D.Float(0, 0, 20, 20, 0, 360, Arc2D.CHORD);
    addMouseListener(this);
    addMouseMotionListener(this);
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    circle.x = (getWidth() - circle.width) / 2;
    circle.y = (getHeight() - circle.height) / 2;

    final Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(getForeground());
    g2d.fill(circle);
  }

  // -------------------------------------------------------------------------
  // Implementing MouseListener
  // -------------------------------------------------------------------------

  public void mouseClicked(MouseEvent e) {
    final String inOrOut =
          circle.contains(e.getPoint()) ? "Inside" : "Outside";
    System.out.println("Clicked: " + inOrOut);
  }

  public void mouseEntered(MouseEvent e) {
    final String inOrOut =
          circle.contains(e.getPoint()) ? "Inside" : "Outside";
    System.out.println("Entered: " + inOrOut);
  }

  public void mouseExited(MouseEvent e) {
    final String inOrOut =
          circle.contains(e.getPoint()) ? "Inside" : "Outside";
    System.out.println("Exited: " + inOrOut);
  }

  public void mousePressed(MouseEvent e) {
    final String inOrOut =
          circle.contains(e.getPoint()) ? "Inside" : "Outside";
    System.out.println("Pressed: " + inOrOut);
  }

  public void mouseReleased(MouseEvent e) {
    final String inOrOut =
          circle.contains(e.getPoint()) ? "Inside" : "Outside";
    System.out.println("Released: " + inOrOut);
  }

  // -------------------------------------------------------------------------
  // Implementing MouseMotionListener
  // -------------------------------------------------------------------------

  public void mouseDragged(MouseEvent e) {
    final String inOrOut =
          circle.contains(e.getPoint()) ? "Inside" : "Outside";
    System.out.println("Dragged: " + inOrOut);
  }

  public void mouseMoved(MouseEvent e) {
    final String inOrOut =
          circle.contains(e.getPoint()) ? "Inside" : "Outside";
    System.out.println("Moved: " + inOrOut);
  }

  // -------------------------------------------------------------------------
  // Program Entry Point
  // -------------------------------------------------------------------------

  /**
   * Test main method.
   * 
   * @param args ignored
   */
  public static void main(String[] args) {
    final JPanel contentPane = new JPanel(new BorderLayout(6, 6));
    contentPane.add(new CirclePaint());

    final JFrame f = new JFrame("Test Frame: CirclePaint"); //$NON-NLS-1$
    f.setContentPane(contentPane);
    f.pack();
    f.setLocationRelativeTo(null);
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
}
```
Ich hoffe, das hilft Dir weiter.

Ebenius


----------



## kenux (16. Jun 2009)

Vielen Dank, jetzt weiß ich zumindestens wie es funktioniert.

Noch eine Frage, wie kann mi Hilfe "mouseEntered" den Kreis an eine andere Stelle springen lassen, wenn sich der Mauszeiger dem Kreis nähert (nicht berührt) ?


----------



## Ebenius (16. Jun 2009)

_mouseEntered_ ist dabei wohl der falsche Event. _mouseEntered_ bedeutet, dass der Mauszeiger die Komponente (also die _Panel_-Instanz) betritt. Du willst sicher _mouseMoved_ (aus dem MouseMotionListener) verwenden.

Was bedeutet denn "nähern"? Meinst Du, wenn der Mauszeiger genau fünf Pixel vom Rand des Kreises weg ist? Mach Dir doch einfach einen zweiten Kreis mit dem selben Zentrum und größerer Ausdehnung und frag dann diesen zweiten Kreis, ob der Mauspunkt innerhalb dessen liegt.

Ebenius


----------



## kenux (16. Jun 2009)

ja genau, also sagen wir mal der Mauszeiger nähert sich dem Kreisrand um 5 pixel zu, dann soll der Kreis an eine andere Stelle springen.


----------



## Ebenius (16. Jun 2009)

kenux hat gesagt.:


> ja genau, also sagen wir mal der Mauszeiger nähert sich dem Kreisrand um 5 pixel zu, dann soll der Kreis an eine andere Stelle springen.


In dem Fall steht der Lösungsansatz bereits zwei Beiträge weiter oben.

Ebenius


----------

