Überlappende Objekte im JLayeredPane



  • Hallo zusammen,

    ich füge einem JLayeredPane mehrere Objekte hinzu, die von JComponent abgeleitet sind. Ich wollte, dass sich die Objekte überlappen, daher JLayeredPane. Wenn ich dann das MouseEvents abfangen will, komme ich auf auf die unter einem Objekt (nämlich dem obersten Objekt) liegenden Objekte überhaupt nicht ran. Existiert eine Methode, mit der sich alle mit einem Objekt überscheidenden Objekte ermittlen lassen - sowas wie

    this.getOverlappingJComponents()
    

    ? Ich habe die Klasse JComponent etc. schon durchsucht - jedoch nichts nützliches gefunden. Ich habe zwar eine elegante Lösung gefunden, die ist jedoch von Performance her nicht akzeptable. Ich habe die Überwachung beim Parentobjekt (JLayeredPane) registriert (parent.addMouseMotionListener(this)). Allerdings dauert es bei mehreren hunderten (oder tausenden) Objekten (mein Fall) eine Ewigkeit dauert und es flattert.

    So schaut der Konstruktor der auf dem JLayeredPane platzierten JComponenten aus:

    //abgeleitet von JComponent
    	public MyJComponent(Rectangle rect, JComponent parent) {
    		setOpaque(false);
    		setBounds(rect);
                      this.addMouseMotionListener(this);
    
    /*früher:		parent.addMouseMotionListener(this);*/
    	}
    

    Dann möchte ich bei MouseMove auch die eventuell drunterliegenden MyJComponents ermitteln:

    public void mouseMoved(MouseEvent me) {
                    if(getBounds().contains(me.getPoint())) {
                          tueWas();
                    } else {
                     /*
                      ALLE ÜBERLAPPENDEN OBJEKTE DURCHLAUFEN !!!!
                      for(...) {
                      }
                      */
    	}
    

    Danke im Voraus für Vorschläge

    Kati



  • hack für getOverlappingComponents() :

    ArrayList getOverlappingComponents(Container c,Component ofThis)
    {
    	int x1 = ofThis.getX();
    	int y1= ofThis.getY();
    	int x2= x1+ ofThis.getWidth();
    	int y2= y1+ ofThis.getHeight();
    	Component[] all=c.getComponents();
    	ArrayList overComs= new ArrayList();
    	for (int i=0;i<all.length;++i)
    	{
    		Component a= all[i];
    		int ax1= a.getX();
    		int ay1= a.getY();
    		int ax2= ax1+ a.getWidth();
    		int ay2= ay1+ a.getHeight();
    		if (x2> ax1 && x1 < ax2 && y2>ay1 && y1<ay2)
    		   overComs.add(a);
    
    	}
    	return overComs;
    }
    

    Aufruf zB:

    ArrayList al= getOverlappingComponents(layerPane,button);
    

    in al sind dann alle Komponenten drin die den button überlappen

    cu crass



  • Hallo crass,

    danke für deine Antwort, aber den Code kann ich auch selbst schreiben. 😉 Ich dachte nur, dass es vielleicht irgendwo eine Information drüber gekapselt wird (Component, JComponent oder ähnliches) und daher hättes ich nicht alles doppelt und dreifach machen müssen, sondern mich einfach einer solchen Methode bedienen können. Ok, also selbst die Objekte durchlaufen und Koordinaten vergleichen... Von der Performanz her ist aber dennoch besser, als die ursprüngliche Lösung.

    Kati



  • ich wollt dir nicht die Arbeit wegnehmen, ich hatt nur lust was zu coden;)

    cu crass



  • Die Überprüfung ob der Punkt innerhalb der Komponente liegt würde ich der Klasse Component überlassen. Die bietet nämlich zwei Methoden namens contains(int x, int y) und eine contains(Point p) Variante ... die for-Schleife kann also reduziert werden.



  • Hallo Cengiz !

    ja, aber die Schleife bleibt mir trotzdem nicht erspart ! Ich muss nämlich alle anderen Objekte durchlaufen und wenigstens x- oder y-Koordinate auswerten. Die, die zutreffen, kommen dann in die engere Auswahl, in der dann die Objekte entfernt werden, deren Koordinate (x- oder y - wie oben erwähnt) zwar innerhalb des betrachteten Objekts (x1, x2) liegen, aber dennoch sich mit diesem nicht schneiden (kann ja sein). Und erst dann kommt die Umrechnerei (weil ja mit MouseEvent me.getX() und me.getY() Koordinaten relativ zum zu behandelnden Objekt geliefert werden... ja, wahrscheinlich hört sich das jetzt ziemlich unverständlich an - die Implementierung ist aber relativ einfach. Ich muss nur schauen, dass ich den Rechenaufwand möglichst reduzieren kann. Und contains() finden im Code natürlich Dauereinsatz, also keine Sorge, ich stöbre andauernd in der Doku und nutze SDK so weit möglich...

    Kati



  • Du meinst also ich kann jetzt ruhig schlafen? 🙂



  • Ja, Cengiz, ich wollte dich nur ein bisschen beruhigen, weil sonst glaubst du ich führe da furchbare Sachen auf, die als Java-Todsünden gelten und jeder Java-Freak mich für diese erschießen würde 😃 NEIN, ich bin sehr, sehr brav...
    🙄

    kati



  • Cengiz bring mich um... ich habe schon alle gemacht isInside() etc. und jetzt finde ich die Methode:

    intersects
    public boolean intersects(Rectangle r)Determines whether or not this Rectangle and the specified Rectangle intersect. Two rectangles intersect if their intersection is nonempty. 
    
    Parameters:
    r - the specified Rectangle 
    Returns:
    true if the specified Rectangle and this Rectangle intersect; false otherwise.
    

    ... man kann nie genug vorsichtig sein.

    kati



  • Tja 🙂
    Da gabs im österreichischen Fernsehen doch mal so eine Kindersendung über Verkehrssituationen und wie man sich verhalten soll ... der Typ hieß glaub ich 'Helmi' (hatte nen süßen Helm auf; sah aus wie ein Stopp-Schild)

    Der hatte immer den Spruch "Augen auf, Ohren auf Helmi ist da!" 🙂 🙂

    Edit: Hab den Kerle gefunden ... http://www.helmi.at das ist wohl so etwas wie ein Nationalmasskottchen 😉



  • hallo cengiz,

    naja, den Kerl kenne ich nicht - es wird wohl dran liegen, dass ich am Samstag um 7.00 noch schlafe. Außerdem bin ich keine Österreicherin 😉 ok, studieren und hackeln tue ich schon da... 🙄


Anmelden zum Antworten