Java: anklickbare graphische Objekte effizient implementieren

Hiho.

zur Zeit stellt sich uns folgendes Problem:

(vorweg, das Programm dient zur Visualisierung von Graphenalgorithmen)
Stellt euch in einem Java Programm eine Zeichenflaeche vor, in dieser Flaeche liegen
sagen wir ca. 200 Knotenobjeke (Ableitungen von JComponent, optisch sind das einfach nur 40x40 grosse Kreise) beliebig angeordnet. Von diesen Knoten aus gehen zu beliebigen anderen Knoten gerichtete Kantenobjekte (auch Ableitungen von JComponent) .. also optisch kann man sich das so vorstellen, 200 Kreise beliebig angeordnet und im Extremfall fuehrt von jedem Kreis zu alle anderen jeweils eine Kante (einfach nur eine Linie mit Pfeilspitze) ... soweit erstmal klar hoffe ich.

Die Kanten sind von JComponent abgeleitet damit sie Mausereignisse empfangen koennen, Problem dabei ist natuerlich das ein JComponent a) im Prinzip ein riesiges Rechteck ist (aber nur die Linie diagonal durch das Rechteck interessiert) und b) sich diese Kantenobjekte sehr leicht ueberlagern, aber nur das oberste Objekt das Mausereignis erhaelt. Noch gesagt werden muss, dass alle Kanten um ihre "Linie" herum ein unsichtbares Polygon verwalten das fuer die Mausklickerkennung dient.

Weiterhin liegen diese Kanten in einem JLayeredPane, wodurch man eine Z-Ordnung auf allen Kanten erhaelt. Die bisherige Loesung sieht wie folgt aus: die Kante die das Mausereignis erhaelt prueft zunaechst ob ihr eigenes Polygon getroffen wurde, wenn nicht prueft sie die Polygone aller Kanten die sie selbst ueberlagert (eben wegen der Z Ordnung geht das recht effizient) und reicht ggfs das Mausereignis weiter. Dieser 'Mechanismus' wird a) dafuer benutzt das man Kanten direkt anklicken kann als User und weiterhin Kanten auch 'gehighlighted' werden... dh. wenn der User mit Maus ueber eines dieser Polygon faehrt blinkt die Linie auf.

Ok, das Ganze klappt soweit schon sehr gut... allerdings nur fuer kleinere Graphen (mit wenigen Kantenobjekten... so bis 1.000-3.000 stueck oder so) . Bei grossen Graphen mit sagen wir 10.000 Kanten wuerde das Ganze prinzipiell auch noch funktionieren, allerdings stoesst Java dabei an seine Grenzen... allein das Hinzufuegen (also JLayeredPane.add(blaa); ) dieser 10k Kanten dauert mehrere Minuten und Java wird im Prozessmonitor dann mit 200+ MB an Speichernutzung gelistet.

Das Problem bzw die Frage ist jetzt wie man das Ganze auch bei sehr vielen Kanten noch effizient loesen kann? Bedingung ist das man die Kanten nach wie vor zumindest direkt anklicken kann (auf Highlighting verzichten wir zur Not)

Bisherige Ideen von uns waren folgende, einmal koennte man die Kanten direkt durch die Zeichenflaechen zeichnen lassen (dadurch erspart man sich den riesen Overhead den die Ableitung von JComponent mit sich bringt)... das Problem dabei ist natuerlich das die Kanten a) dann keine Mausevents mehr bekommen und man mehr oder minder bei jedem Mausklick _alle_ Kanten auf "getroffen-worden-sein" testen muss. Bei 40k Kanten dauert das ca. 3 sekunden (2.6 Ghz Rechner)... also unakzeptabel langsam. Dadurch das man die Kanten direkt zeichnet verliert man ja zudem auch die Z-Ordnung so das man immer alle testen muss.
Eine andere Idee war, alle Kanten in einem einzigen Objekt welches von JComponent abgeleitet worden ist zu verwalten.. hat so ca. diesselben Schwaechen wie die Direkt-Zeichnen Loesung.. man hat nur direkt die MausEvents und ein paar nuetzliche Methoden die Jcomponent mitbringt.
Ein weiterer riesen Nachteil beider Ansaetze ist das das effiziente Zeichnen extrem schwierig wird (einfach immer _alle_ Kanten zu zeichnen ist indiskutabel)..

So... hoffe es ist klar geworden worum's sich dreht (ansonsten ruhig nachfragen)... vielleicht stand jemand schon mal vor einem aehnlichen Problem und/oder hat eine gute Loesung parat? :)
 
ich kann dir zwar bei deinem problem direkt auch nicht helfen aber ich würde dir empfehlen das problem mal im java technology forum zu posten
ich behaupte mal dass dir dort wesentlich besser und kompetenter geholfen werden kann als hier
http://forum.java.sun.com

edit:
mich würde mal interessieren wie ihr das problem nun gelöst habt ?!
 
wir haben uns vorerst entschieden es so zu lassen wie es ist... die Graphgroessen fuer die das Programm mehr oder weniger unbenutzbar wird sind mehr als praxisfern, aber dumm ist es halt trotzdem das da dann Ende im Gelaende ist :)

der Tipp mit dem Java Tech Forum war btw sehr gut.. sehr faehige Leute dort, hier der Thread dazu:
http://forum.java.sun.com/thread.jsp?forum=57&thread=531283&tstart=165&trange=15

diverse Tests haben nebenbei auch gezeigt das das Problem nicht daran begruendet ist das man von JComponent ableitet (wir dachten das erzeugt zuviel overhead) .. aehnlich wie im Forum beschrieben haben wir uns einen Kantencontainer gebaut der eine beliebige (aber feste) Anzahl von Kanten aufnehmen kann.. die Kanten selbst waren dann nur noch 'normale' Objekte... Ergebnis, das Objekt-Erzeugen selbst (egal wie 'klein' die Objekte sind) reisst das Ganze nach unten.

Bleibt vllt noch zu sagen das das Ganze im Rahmen eines Softwarepraktikums hier an der Uni entwickelt wird (wir (4 Mann) sind eine Gruppe von 7) .. und zusammen mit einer anderen Gruppe haben wir, wenn man so will, das geilste Programm (die anderen Gruppen sind eher weniger die Programmierfreaks..) ... also da wir eh schon weit oberhalb aller Mindestforderungen sind wird uns das Problem nicht reinreissen, der Schein inkl. Note < 2.x ist uns sicher :)
 
Zurück
Oben