Effizient zeichnen

Status
Nicht offen für weitere Antworten.
T

tuxedo

Gast
Hallo,
ich habe folgende Problem:

Ich bastle an einem Programm das mit GPS Wegpunkte aufzeichnet, in eine DB speichert und auch wieder im Programm anzeigt. Anfangs ging das noch ziemlich gut und auch schnell. Doch mittlerweile wachsen die Daten und ich stoße an die Grenzen meines Wissens.

In einem JPanel hab ich die paintMethode überschrieben und zeichne mit g.drawLine() meine aufgezeichneten Wege.

Das sieht z.B. so aus (hab mal nur die Karte aus dem Programm ausgeschnitten):

map.jpg


Aktuell sind auf dem Bild über 3000 Wegpunkte zu sehen die mit einer Linie verbunden sind. Insgesamt zeigt das Bild eine ungefähre entfernung von 20km von unten links nach oben rechts an. D.h. wenn ich in der Ortschaft unten links oder oben rechts noch mehr Daten gesammelt hätte würde er noch mehr zeichnen, auch wenn man die einzelnen Straßen wohlmöglich nur schwer erkennen könnte. Eigtl ist das sehr ineffizient. Aber siehe weiter unten bei meiner abschließenden Frage....


Meine paintMethode mach im Prinzip nur das hier:

+ Nimm den Vector in dem alle miteinander assoziierten Pixel sind und arbeite diesen Element für Element ab:
+ Wenn das mit g.drawLine zu zeichnenden Pixel-Paar im Ausschnitt der Karte liegt, zeichne dies.

Ich hab hier bewusst mal den Quellcode weggelassen da ich hier alles aufs allernötigste reduziert hab um möglichst jedes instanziieren einer Hilfsvariable zu vermeiden, um Zeit zu sparen. Sieht also mehr oder weniger ganz wild aus.

Der Vector enthät nix weiter wie eigene Pixel-Objekte in denen steht welche 2 Pixel miteinander verbunden werden müssen.

Der Vector wird in einer Endlosschleife immer wieder mit der DB angeglichen und enthält mehr Daten als aktuell gezeichnet werden müssen. Das dient dazu nicht bei jedem Zeichenvorgang eine Anfrage an die DB stellen zu müssen.

Die endlosschleife schiebt bei jedem durchlauf den Vector mit den Daten an das JPanel das die karte darstellt. Nach dem weitergeben der Daten erfolgt ein "globaler" repaint(). Erst dachte ich dass das erneute zeichnen des ganzen programmfensters so viel leistung frisst und hab mal testweise mit meine Karte neu zeichnen lassen (mapPanel.repaint()), aber das brachte keinen sichbaren Erfolg.

Dann habe ich Stück für Stück Programmteile abgeschaltet um zu sehen an welchem Teil die meisten Ressourcen drauf gehen. Und tatsächlich: Es liegt an der paintMethode die einfach viel zu viel zeichnen muss.

Ich muss dazu sagen: Die Endlosschleife hat am Ende ein sleep(1) um die CPU nicht vollends zu vereinnahmen.
Getriggert wird die Endlosschleife allerdings durch den simulierten Empfang der GPS Daten. D.h. im Moment kommen alle 10ms neue GPS-Daten rein so dass, grob gesagt, alle 10ms ein repaint() erfolgen muss um die Karte auf dem laufenden zu halten.

Für den realfall der Anwendung mag das noch schnell sein. Aber im realfal hat man auch schnell mehr zu zeichnen weil einfach mehr Daten vorhanden sind.

Ok, kommen wir zur eigentlichen Frage:

Bietet Java oder irgendeine 2D API etwas schnelleres als g.drawLine()?

Oder gibt es einen Algorithmus der mir da weiterhelfen könnte (siehe Problem weiter oben mit dem zu viel zeichnen das man eh nicht erkennen kann)?

gruß
Alex

P.S. Sorry wenn ich das falsche Sub-Board erwischt hab. Alle anderen schienen mir nicht zu passen.
 

AlArenal

Top Contributor
Endlosschleifen sind schonmal pisse. Gezeichnet werden sollte nur dann, wenn gezeichnet werden muss, d.h. wenn sich entweder an den Daten etwas ändert, oder der Controller den View entsprechend beauftragt, weil wer scrollt, zoomt, etc.
Daher grundsätzlich: MVC ansehen, verinnerlichen, einbauen!

Was Java2D angeht, bin ich zwar keine Guru, was die interne Implementierung in der VM angeht, würde aber darauf wetten dass es füür derart komplexe Strukturen performanter ist einen GeneralPath zu benutzen, anstatt tausende Linien einzeln zu zeichnen.
 
T

tuxedo

Gast
Servus,
danke für die schnelle Antwort. Aber ich könnt mir selbst in den Hintern beissen....

Statt Einfach nur "Graphics" zu verwenden hab ich eben mal kurz gegoogelt und das hier eingebaut:

Code:
Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

Und statt mit "g" hab ich dann mit "g2" gezeichnet.
Und siehe da: Das Ding rennt wie sau.
"Wie sau" bedeutet:
Zwar noch immer eine sehr hohe CPU-Last, aber die Anzeige ruckelt nichtmehr, egal ob ich jetzt 1000 oder 5000 Wegpunkte zeichne. Und die GUI reagiert viel schneller auf Benutzereingaben wie verändern des Zooms...

Was die Endlosschleife angeht:
Das hast du wohl nicht ganz verstanden oder ich habs schlecht erklärt (wohl eher letzteres, schreibe ja nicht zum ersten mal Programme):

Ich schreibs mal im Pseudo-Code nieder:

Code:
while(true){

if (buffer!=empty) {
getDataFromBuffer();
putDataIntoDB();
showOldAndNewDataOnMap();
}
sleep(1);
}

Also nur wenn in meinem Empfangspuffer wirklich Daten da sind, werden diese auch abgeholt, verarbeitet und gezeichnet.
Das Prinzip des MVC ist mit durchaus bekannt. Jedoch ist das standard-MVC-Vrfahren wie man es in vielen Büchern nachlesen und in einigen Vorlesungen hört nicht immer anwendbar (nicht immer heisst nicht "nie").

Was GeneralPath betrifft:
Hör ich jetzt zum ersten mal. Hab gleich google angeworfen und die ersten Brocken gelesen. Hört sich interessant an. Mal sehen wie ich das einbauen kann.
Danke hierfür. Man lernt eben nie aus.

gruß
Alex
 

AlArenal

Top Contributor
Und wenn du das Antialiasing ausschaltest, gehts noch schneller ;)
Gern genommener Kniff ist z.B. während aufwändiger Opertationen, z.B. wenn man scrollt, live zoomt oder animiert, das Antialiasing auszuschalten (weil es heftig Performance kostet) und dann am Ende wieder zu aktivieren, wenn nur noch der 'Endzustand' gezeichnet wird (letzter Frame der Animation, kein weiterer Zoom, Endpunkt des Scrollings erreicht, ...).

Nochmal zu deiner Schleife:
Wäre es nicht sinniger, wenn der Buffer per Event meldet, wenn er neue Daten hat? Wenn ich das sleep sehe, wird mir beim Gedanken daran den AWT Event Dispatcher Thread schlafen zu legen irgendwie unwohl..
 
T

tuxedo

Gast
Du wirst mir das jetzt vielleicht nicht glauben, aber wenn ich
Code:
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
mache und somit AA generell abschalte ruckelts wieder wie vorher....
Vielleicht mach ich da ja was falsch?

Das mit dem Buffer und dem Event:
Der Buffer dient mir dazu den Empfangsthread von der GUI abzukoppeln. Ich hätte ja ach gleich Empfang mit der GUI direkt verbinden können. Aber wenn das eine mal hängt beeinträchtigt es das andere. Dank dem Buffer hab ich hier Spielraum. Hängt die GUI mal kann ich noch weiter Empfangen.

Mit dem sleep(1) lege ich ja auch nicht die GUI schlafen. Ich habe Logik, Empfangstel und GUI je in eine Klasse gesteckt und über eine Starter-Klasse diese 3 Instanziiert und miteinander verbunden, sprich die nötigen Referenzen untereinander gesetzt. Die GUI instanziiert sich noch weitere Klassen, so z.B. den Tacho oder auch die Karte...
Wenn ich jetzt im Logikteil ein sleep(1) mache lege ich doch nicht die GUI schlafen? Oder bin ich da jetzt falsch?
 

AlArenal

Top Contributor
Wenn du nicht explizit mit Threads arbeitest läuft bei dir alles im AWT Event Dispatcher Thread (meist kurz EDT) und der ist fürs Zeichnen und die Event-Verarbeitung zuständig. Legst du den Thread schlafen, oder machst du sonst etwas, was unbestimmt viel Zeit benötigt (I/O jeder Art, wie DB-Abfragen, Datei I/O, Netzwerkkram, ..) werden in der Zeit keine Events verarbeiet und es wird auch nicht neu gezeichnet.
Derart murksig entwickelte Software bringt viele immer dazu zu sagen Java/Swing sei langsam, ganz einfach weil der User dann diverse Verzögerungen bemerkt.
 
T

tuxedo

Gast
hi,
okay, wieder was gelernt. D.h. wenn ich sleep behalten will muss meine Logikklasse auch als Thread laufen. Dann kann ich explizit diesen Thread schlafen legen (this.sleep(1)), richtig?

Muss ich dazu meine GUI-Klasse (extends JFrame) auch nochmal explizit als Thread laufen lassen oder läuf die swing-technisch schon ausreichend genug als Thread?

Wie war das jetzt mit dem AA? Hast du ne Ahnung warum das bei mir abgeschaltet langsamer läuft als angeschaltet?
 

AlArenal

Top Contributor
alex0801 hat gesagt.:
hi,
okay, wieder was gelernt. D.h. wenn ich sleep behalten will muss meine Logikklasse auch als Thread laufen. Dann kann ich explizit diesen Thread schlafen legen (this.sleep(1)), richtig?

Yo. Wobei mir der Sinn des sleep noch abgeht.

Muss ich dazu meine GUI-Klasse (extends JFrame) auch nochmal explizit als Thread laufen lassen oder läuf die swing-technisch schon ausreichend genug als Thread?

Ich hole mal was aus:
Standardmäßig hat eine Swing-Anwendung zwei Threads, den Main Application Thread, der die #main ausführt und den EDT, der Event-Handling, Zeichnen und Layout übernimmt. Alles was mit dem GUI zu tun hat, sollte auch im EDT erledigt werden, d.h man sollte auf die Idee kommen den Text eines Labels in einem anderen Thread zu setzen. In dem Zusammenhang empfehle ich immer sich folgendes auch ruhig mehrmals in Ruhe anzuschauen:
http://www.javalobby.org/eps/galbraith-swing-2/

Wie war das jetzt mit dem AA? Hast du ne Ahnung warum das bei mir abgeschaltet langsamer läuft als angeschaltet?

Nope. Klingt für mich nicht logisch. Kann höchstens sein, dass das eine bei dir hardware-beschleuningt ist und das andere nicht, nur macht es sorum m.E. keinen Sinn *achselzuck*
 
T

tuxedo

Gast
Der Link ist klasse. Ich werds mir reinziehen.

So far: thanks a lot ...

- Alex

[UPDATE]
Nochmals vielen Dank für den Link. Hab die erste Präsentation auch angesehen. Der Typ hat mich begeistert. Is schon krass was man mit nur wenigen Zeilen zusätzlichen Code bewirken kann. Ist die Präsentation schon irgendwo hier im Forum bei den FAQs oder so verlinkt? Denke speziell Teil2 sollte sich jeder reinziehen der gute GUIs basteln will.
 
T

tuxedo

Gast
Okay, hab weitere Tests gemacht, meine Logik von der GUI mittels eigenem Thread abgekoppelt etc...

Ein problem hab ich aber noch:
Da alles zeichnen im EDT passiert und ich ne Menge zu zeichnen hab legt das zeitweise die restliche GUI lahm...

Gibts ne Möglichkeit die GUI von meiner Karten-Komponente die so viel zu tun hat zu entkoppeln?!
Sprich: Kann ich das zeichnen dieser einen Komponente in nem anderen Thread als dem EDT laufen lassen?

Oder hab ich keine andere Wahl als meine Zeichenroutine so schnell zu machen dass der EDT keine Performanceprobleme damit bekommt?

- Alex
 
T

tuxedo

Gast
Hätte doch früher schon mich mit GenerelPath befassen sollen. Hab vor dem zeichnen meinen Vector in Generalpath gesteckt und nur noch ein

Code:
g2.draw(map);

gemacht. Und siehe da: Das geht sau schnell. Und wenn ich AA jetzt ausschalte gehts, wie du anfangs schon sagtest, nochmal schneller.

Jetzt kann ich auch die ganze Karte mit aktuell rund 5000 Wegpunkten im 5ms Takt neu zeichnen ohne dass beim rein oder rauszoomen eine Verzögerung der GUI erkennbar ist. Okay, die CPU-Last ist immernoch bei 70% (3,1Ghz Sempron), aber im echten Leben liefert der GPS Empfänger die Signale auch nur rund alle 277ms.
Vielen Dank nochmals für die Tipps,

gruß
Alex
 

transsib

Mitglied
Hallo Alex!

Verrätst Du mir, welches GPS Du verwendest? Weiter oben schreibst Du, dass es mit bis zu 100 Hz (alle 10 ms) sendet. Da kannte ich bislang nur die VBox, die das so schnell schafft!?

Weshalb zeichnest Du die Karte alle 5 ms neu? Das menschliche Auge kann doch ohnehin maximal 25 Bilder in der Sekunde, also alle 40 ms ein Bild, wahrnehmen. Selbst Bewegungen mit 10 Bildern pro Sekunde werden noch als einigermaßen "weich" wahrgenommen".

Neugierige Grüße,

Oliver
 
T

tuxedo

Gast
Da man ja schlecht beim Programmieren mit dem GPS-Empfänger durch die gegend rennen kann haben wir nen GPS-Satz-Simulator gebastelt. Das ist auch ganz praktisch um aufgezeichnete Fahrten nochmal abzuspielen. Und da kommen die Sätze so schnell weswegen auch so oft hintereinander gezeichnet wird.

Aber ich tippe mal darauf dass du meinen letzten Post nicht aufmerksam gelesen hast. Da gings nur drum DASS es jetzt möglich ist so schnell zu zeichnen.
Und da steht auch das der echte Empfänger nur alle ~277ms ein GPRMC-Satz liefert, und nicht alle 10ms
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Welt möglichst effizient malen... Spiele- und Multimedia-Programmierung 7
M Bilder effizient speichern/serialisieren Spiele- und Multimedia-Programmierung 10
E relevanter bereich einer isometrischen karte zeichnen (AffineTransform) Spiele- und Multimedia-Programmierung 0
SaftigMelo Kreissegment zeichnen Spiele- und Multimedia-Programmierung 2
E Buttons neu zeichnen im GridLayout Spiele- und Multimedia-Programmierung 2
A Zeichnen außerhalb der paint-Methode Spiele- und Multimedia-Programmierung 6
E Isometrische Tiles mit unterschiedlicher Größe an korrekter Position zeichnen Spiele- und Multimedia-Programmierung 1
Androbin Mein Spiel will sich nicht zeichnen lassen !!! Spiele- und Multimedia-Programmierung 7
J Int Wert auf JFrame zeichnen Spiele- und Multimedia-Programmierung 3
H [ANIMATION] Hintergrundbild nur einmal zeichnen Spiele- und Multimedia-Programmierung 3
R [lwjgl] Cursor -> versetzt Zeichnen / Bild ist umgedreht Spiele- und Multimedia-Programmierung 2
M Methoden eine Map zu zeichnen Spiele- und Multimedia-Programmierung 5
aze Nicht rechteckiges Bild zeichnen Spiele- und Multimedia-Programmierung 5
F nur Ausschnitt eines Image zeichnen Spiele- und Multimedia-Programmierung 9
T 3D Graphen Zeichnen Spiele- und Multimedia-Programmierung 19
F Kurven zeichnen Spiele- und Multimedia-Programmierung 2
E Keine Werte zum Zeichnen werden Übergeben Spiele- und Multimedia-Programmierung 3
A Halbkreise zeichnen lassen? Spiele- und Multimedia-Programmierung 2
F Lineal mit Zahlen zeichnen Spiele- und Multimedia-Programmierung 7
N Linie mit Rand zeichnen Spiele- und Multimedia-Programmierung 10
A Mehrere geometrische Objekte in JPanel zeichnen Spiele- und Multimedia-Programmierung 4
A Optimiertes Zeichnen - wie? Spiele- und Multimedia-Programmierung 8
data89 Koordinaten in Koordinatensystem zeichnen Spiele- und Multimedia-Programmierung 11
M Binärbaum ohne Überlappung zeichnen Spiele- und Multimedia-Programmierung 3
H Decke zeichnen mit Hilfe eines Polygons Spiele- und Multimedia-Programmierung 2
B 1)JButtons zeichnen 2)Kolisionsabfrage von zwei Objekten Spiele- und Multimedia-Programmierung 9
G Linie im Applet zeichnen Spiele- und Multimedia-Programmierung 5
G Schüsse zeichnen, Fehler? Spiele- und Multimedia-Programmierung 3
S Dreieck zeichnen Spiele- und Multimedia-Programmierung 9
G Überlagern von Strings beim zeichnen verhindern Spiele- und Multimedia-Programmierung 3
C Objekt bei Buttonklick zeichnen Spiele- und Multimedia-Programmierung 16
G Geschwungene Klammer zeichnen Spiele- und Multimedia-Programmierung 5
F Neu zeichnen verhindern Spiele- und Multimedia-Programmierung 25
J Zeichnen in BufferedImage und dieses in Datei speichern Spiele- und Multimedia-Programmierung 2
O Funktion zeichnen Spiele- und Multimedia-Programmierung 11
A Lissajous Figuren zeichnen Spiele- und Multimedia-Programmierung 1
G Maus springt --> Free-Hand-Zeichnen Spiele- und Multimedia-Programmierung 2
L Schüsse zeichnen Spiele- und Multimedia-Programmierung 13
M Eigene Strings zeichnen Spiele- und Multimedia-Programmierung 4
T Blitz berechnen und zeichnen Spiele- und Multimedia-Programmierung 13
M auswahlkreis zeichnen (schräg) Spiele- und Multimedia-Programmierung 4
N Logik: Grenz-/Frontlinie zeichnen Spiele- und Multimedia-Programmierung 4
M Grafikprogramm, zeichnen mit Maus Spiele- und Multimedia-Programmierung 7
G Problem beim Zeichnen von LineArrays Spiele- und Multimedia-Programmierung 9
P linie in bild zeichnen Spiele- und Multimedia-Programmierung 2
G Auf 3D Box zeichnen Spiele- und Multimedia-Programmierung 4
K mit Canvas übereinander zeichnen Spiele- und Multimedia-Programmierung 4
G 3D Raum zeichnen Spiele- und Multimedia-Programmierung 7
H Kreis zeichnen mittels Schleife & drawLine Spiele- und Multimedia-Programmierung 4
B Probleme beim zeichnen Spiele- und Multimedia-Programmierung 15
N Bild zu zeichnen (drawImage) klappt nur manchmal?? Spiele- und Multimedia-Programmierung 8
H mit Java2D Markierung über JTable zeichnen und diese bewegen Spiele- und Multimedia-Programmierung 2
C Graphische Benutzerschnittstelle, Problem beim Zeichnen Spiele- und Multimedia-Programmierung 4
J schnellste alternative um in java zu "zeichnen" Spiele- und Multimedia-Programmierung 17
conan2 Objekte in richtiger Z-Reihenfolge zeichnen Spiele- und Multimedia-Programmierung 2
G Punkte in Java3D zeichnen Spiele- und Multimedia-Programmierung 2
S Pixel zeichnen Spiele- und Multimedia-Programmierung 3
S Bild in Speicherbild zeichnen = Nichts? Spiele- und Multimedia-Programmierung 3
G Farbig zeichnen ohne java.awt.Color? Spiele- und Multimedia-Programmierung 5
S Wie kann ich das Zeichnen der Grafik feiner machen? Spiele- und Multimedia-Programmierung 9
M Wie kann man Kreisringe zeichnen ? Spiele- und Multimedia-Programmierung 12
C Graphics 2D Zeichnen Spiele- und Multimedia-Programmierung 4
R Kreuz lässt sich nicht zeichnen Spiele- und Multimedia-Programmierung 11
F einzelne Polygone(Graphics) schneller als and. Fig. zeichnen Spiele- und Multimedia-Programmierung 3
K Kugeln und Zylinder zeichnen Spiele- und Multimedia-Programmierung 4
L ein Rechteck zeichnen Spiele- und Multimedia-Programmierung 6

Ähnliche Java Themen

Neue Themen


Oben