# Allgemeine Frage zu Java2D (Eigene Impl.)



## Kr0e (26. Jan 2010)

Hallo,

Angenommen ich wollte Swing nicht mit Java2D als 2D Fenster auf dem Desktop zeichnen lassen, sondern virtuell.
Kann ich irgendwie Swing sagen, dass es eine andere "Graphics" Implementierung nutzen soll ? Z.b. eine eigene ?

Hab das PRoblem schon recht lange und bisher keine gute Lösung gefunden.

Schreibe ein 3D Projekt und brauche eine 3D GUI. Swing ist ja ansich ne prima Sache, aber mein bisheriger Ansatz (Die einzelnen Komponenten zusätzlich mit "paintComponent()" in ein BufferedImage zu rendern, war nicht ausreichend performant)

Geschwindigkeit ist mir SEHR wichtig. Dieses BufferedImage muss nebenbei auch noch später onch in eine 3D Texture konvertiert werden, was auch Zeit kostet.

Erstmal eine generelle Frage: Ist es möglich ein Java Fenster virtuell genauso schnell zu rendern, wie mit Java2D (Achja, ist Java2D eigentlich hardwarebeschleunigt ? Doofe Frage vlt. aber hab mich bisher nicht so stark damit beschäftigt)

Mein erster Ansatz hatte noch ein Problem. Man kann vlt. einzelne Komponenten zeichnen, aber ein JFrame zum Beispiel is ja schon ein natives Fenster wenn ich nciht irre, sprich ein Fenster das von Windows/Linux/Mac bereitgestellt wird... Wenn ich mich irre, einfahc reinrufen 

Vlt. habt ihr irgendwelche Ideen oder Tipps, die mir helfen könnten, das Vorhaben umzusetzen!

Gruß,

Chris


----------



## Marco13 (26. Jan 2010)

_Schreibe ein 3D Projekt und brauche eine 3D GUI. Swing ist ja ansich ne prima Sache, aber mein bisheriger Ansatz (Die einzelnen Komponenten zusätzlich mit "paintComponent()" in ein BufferedImage zu rendern, war nicht ausreichend performant)

Geschwindigkeit ist mir SEHR wichtig. Dieses BufferedImage muss nebenbei auch noch später onch in eine 3D Texture konvertiert werden, was auch Zeit kostet.
_

Eigentlich sollte das schon schnell sein. Es kann aber auch stark(!) vom BufferedImage.TYPE_* des BufferedImages abhängen.

BTW: Das klingt ziemlich nach Swogl 


_Erstmal eine generelle Frage: Ist es möglich ein Java Fenster virtuell genauso schnell zu rendern, wie mit Java2D (Achja, ist Java2D eigentlich hardwarebeschleunigt ? Doofe Frage vlt. aber hab mich bisher nicht so stark damit beschäftigt)_

Java2D ist mal mehr mal weniger Hardwarebeschleunigt - hängt von der Version und den Startparametern ab. Aber im allgemeinen schon: New Features in Java 2D(TM) Technology


_Mein erster Ansatz hatte noch ein Problem. Man kann vlt. einzelne Komponenten zeichnen, aber ein JFrame zum Beispiel is ja schon ein natives Fenster wenn ich nciht irre, sprich ein Fenster das von Windows/Linux/Mac bereitgestellt wird... Wenn ich mich irre, einfahc reinrufen _

Ja, einen kompletten Frame in eine Textur zu zeichnen ... Hm. Könnte schwierig werden. Ein JInternalFrame wäre weniger Problematisch. Im Endeffekt ist aber doch die ContentPane das, was in der Textur landen soll, oder täusche ich mich?


----------



## Kr0e (26. Jan 2010)

Ja, prinzipiell ja. Swogl hab ich mir schonmal angeschaut. Wie macht Swogl das ? Das war doch glaub ich dein Projekt, wenn ich nicht irre. Was genau nutzt Swogl ? BufferedImages die dann später konvertiert werden ? Ich denke da an Listboxen ... Kaum wird die Scrollbar minimal bewegt, msus die Textur neu gezeichnet werden ...


----------



## Marco13 (26. Jan 2010)

Im Endeffekt ist's ein BufferedImage, das später in eine Textur kopiert wird. Praktischerweise erledigt die meiste Arbeit dabei die Klasse TextureRenderer (JOGL, NativeWindow and NEWT APIs) (code unter Java? Binding for the OpenGL® API: jogl SCM: src: jogl: classes: com: sun: opengl: util: awt: TextureRenderer.java &mdash; Project Kenai). Da malt man über ein Graphics2D indirekt in ein BufferedImage, das dann in eine Texture (code unter Java? Binding for the OpenGL® API: jogl SCM: src: jogl: classes: com: sun: opengl: util: texture: Texture.java &mdash; Project Kenai) kopiert wird.

Die Frage nach den Updates ist berechtigt. Bisher war das bei mir noch nicht so das Performance-Bottleneck. Es wird zwar schon eine Dirty Rectangle Detection gemacht (geht auch recht einfach mit einem eigenen RepaintManager), und es sind auch schon Ansätze drin, die dann auf die Textur anzuwenden, aber das ist ein bißchen frickelig, weil bei JScrollPanes intern schon einige ... "Tricks" verwendet werden, um das Scrollen schneller zu machen, und diese "Tricks" machen das ganze dann ein bißchen komplizierter, aber das steht schon als "todo" auf meiner Liste. Wann auch immer ich mal mit Swogl weitermache(n kann). Im Moment ist die Situation rund um JOGL ziemlich diffus, da sind die Prioritäten im Moment bei mir auch ein bißchen woanders...


----------



## Marco13 (26. Jan 2010)

Oh ja, ich erinnere mich: http://www.java-forum.org/awt-swing-swt/88844-swing-bild-rendern.html


----------



## Kr0e (26. Jan 2010)

Hmm, hab sowas ähnlcihes auch mal selber gemacht aber mit der jMonkeyEngine... Die haben auch nen TextureRenderer, und traten die selben Performanceprobleme auf.

Hab grad nochmal was gesucht und bin dann darauf gestoßen:

http://jext.free.fr/javapolis05_extremeswing.pdf

Die machen das wohl auch mit BufferedImage aber iwie durch OpenGL beschleunigt..

"-Dsun.java2d.opengl=true"

Ansich ist ja die Idee total genial... Allein deshalb weil keine GUI mit Swing mithalten kann... Allein die Tatsache, dass es Matisse GUI Builder gibt bei NetBeans... Alles andere ist "rumgefrickel" ... Ich werde dran bleiben, wenn ich was herausfinde, schreib ichs hier nochmal.. Dann kannste damit vlt. Swogl auch etwas "pimpen".. WObei Swogl übrigens ansich shcon ziemlich cool ist 

Gruß,
Chris


----------



## Kr0e (26. Jan 2010)

Nachtrag:

Wenn Swing opengl nutzen kann, dann muss man doch irgendwie an die TextureId kommen 

New Features in Java 2D(TM) Technology

Die nutzen auch nen texture renderer


----------



## Marco13 (26. Jan 2010)

Naja, die Verwendung der Texturen (sofern es überhaupt welche sind) ist wohl zu gut "versteckt", als dass man da durch die API drankäme. Vielleicht ist es aber auch das (erstmal naheliegend erscheinende) glDrawPixels, was dort verwendet wird...


----------



## Kr0e (26. Jan 2010)

Hmm, nungut das hilft alles nichts 

ICh denke man muss dafür eine Ebene tiefer eingreifen... Das JFrame darf garnicht auf die normale Art und Weise gezeichnet werden.

Hättest du (oder auch andere) vlt. irgendeine Idee, wie man genau dort was ändern könnte ? Es gibt Agile2D ... Das Framework nutzt ein OpenGL-Graphics Objekt (von Graphics2D) und implementiert alle Funktionen mit OpenGL... drawLine usw wird dann quasi direkt auf eine OpenGL Textur übertragen... Die Frage ist, (Hab jetzt noch keinen Blick in das Framework geworfen) wie es es schafft, Java2D zu sagen, dass es andere Graphics Objekte nutzen soll... 

Wenn man das irgendwie hinkriegen würde, wären damit die Performanceproblem gelöst... Java2D würde dann wirklich nur die Sachen neuzeichnen (Undzwar hardwarebeschleunigt!) die auch neugezeichnet werden müssen... Und es müssen keine Images mehr konvertiert werden.. Bei großen Images ist das ja praktisch unmöglich, wenn man einigermaßen gute FPS-Zahlen haben will...

Gruß,
Chris


----------



## Marco13 (26. Jan 2010)

Also, du willst zwar ein JFrame erstellen, DAS dann aber nicht anzeigen, sondern komplett in eine Textur rendern? Das könnte (wie du ja schon gesagt hat) schwierig werden... JFrame ist eben ein Top-Level-Container. Es ist schon scher genug (bis unmöglich) "normale" Components zu rendern, die NICHT sichtbar (oder zumindest nicht Teil eines sichtbaren Frames) sind. (Bei Swogl wird da ja auch übel Getrickst...  aber das nicht zuletzt wegen den Event-Handling... brauchst du das eigentlich auch?  )

Inwieweit man da also "tiefer" ansetzen kann, weiß ich nicht. Agile2D kannte ich nicht, aber habe mich bei den ersten Suchergebnissen gefragt, inwieweit das noch gewartet wird, und (vielleicht noch wichtiger) inwieweit sich das von Swing mit ....opengl=true unterscheidet (letzteres ist ja immerhin offiziell von Sun, da kann man wenigstens meckern, wenn irgendwas nicht funktioniert  ). Ich hatte mir zwar auch schon ein paar mal vorgenommen, mir den Quellcode vom JDK anzusehen (also den nativen Teil) aber das könnten die sprichwörtlichen Kanonen für die Spatzen sein...


----------



## Kr0e (26. Jan 2010)

Du meinst mit Eventhandling, die weiterleitung von Events ? Sprich wenn die Maus gerdückt ist, dem JFrame das dann (Wenn es nicht angezeigt wird) das irgendwie klarzumachen ?

Ich errinnere mich da an was... Ich glaube das JFrame nimmt auch kein Input an wen es "offiziell" nicht angezeigt wird oder ?

Ok, muss ja kein JFrame sein.. Hast schon recht, auch normale Components sind schwer. Ich wollte halt ganz gern etwas "komplettes".

Zur Zeit benutze ich FengGUI für OpenGL. Die ist ansich ganz gut, aber leider zu "buggy". TextBoxen und ähnliches hängen sich (warum auch immer) irgendwann auf, der Cursor wird nicht richtig versetzt usw. Swing ist halt schon ziemlich gut, deswegen kam die Idee. Vorallem weil Swing ständig und offiziell erweitert wird und eben der Editor... Das "3D-Eventhandling" hab ich dafür bereits geschrieben. Also Mousepicking usw...


----------



## Marco13 (27. Jan 2010)

Kr0e hat gesagt.:


> Du meinst mit Eventhandling, die weiterleitung von Events ? Sprich wenn die Maus gerdückt ist, dem JFrame das dann (Wenn es nicht angezeigt wird) das irgendwie klarzumachen ?
> Ich errinnere mich da an was... Ich glaube das JFrame nimmt auch kein Input an wen es "offiziell" nicht angezeigt wird oder ?
> ...
> Das "3D-Eventhandling" hab ich dafür bereits geschrieben. Also Mousepicking usw...



Da sagst du so lapidar  Irgendein Hauptfenster muss es ja geben, und NUR das kann erstmal die Events einfangen. Die dann geeignet weiterzuleiten (mit Focus, Mouse Dragging bei SplitPanes & Co) ist IMHO alles andere als trivial....




Kr0e hat gesagt.:


> Ok, muss ja kein JFrame sein.. Hast schon recht, auch normale Components sind schwer. Ich wollte halt ganz gern etwas "komplettes".
> 
> Zur Zeit benutze ich FengGUI für OpenGL. Die ist ansich ganz gut, aber leider zu "buggy". TextBoxen und ähnliches hängen sich (warum auch immer) irgendwann auf, der Cursor wird nicht richtig versetzt usw. Swing ist halt schon ziemlich gut, deswegen kam die Idee. Vorallem weil Swing ständig und offiziell erweitert wird und eben der Editor...



Ja, FengGUI hatte ich auch mal gesehen, aber nicht näher angesehen wie dort genau das Rendering passiert... 
Kann man eigentlich Fragen, was das "Gesamtziel" ist, oder ist das Verschlusssache?


----------



## Kr0e (27. Jan 2010)

Ne klar darf man das fragen. xD
FengGUI rendert mit reinem OpenGL auch Text usw. Ist von daher unheimlich flott. Aber leider sehr dürftig was Components angeht... Und viele Standardkomponenten sind einfacg noch zu verbuggt um die richtig einzusetzen...

Zu dem Gesamtziel:

Das Projekt heißt FoxNet. Das Projekt gleicht etwas "Wonderland" von SUN. Aber ich hatte die Idee bevor ich was von Wonderland gelesen hab. (Ehrlich!) Aber bei Wonderland geht es ansich um was anderes. Die haben da nen X11 Server der auf Linux läuft, der dann z.B. Firefox für viele Leute gleichzeitig starten kann und per Remote an alle anderen Übertragen werden kann... Mein Plan war jetzt nicht derart hochgesteckt...

Es gibt eine 3D Welt (Ähnlich einer Bibliothek). Jeder steuert einen Avatar (Firstperson). Es gibt nun Leinwandähnliche Objekte auf denen dann irgendwas abgebildet werden kann. Man kann mit anderen Avataren (Usern) dann einen Livechat oder Audiochat starten... Webcam wäre da auch möglich. Ein weiteres Plus ist die Netzwerk Geschichte. Es sollen die User untereinander Dateien austauschen können... Aber da jeder einen geringen Upload i.d.R. hat wäre das viel zu langsam. Angenommen 5 Leute in einer Group besitzen eine Datei, dann wird die entsprechend von 5 Leuten angefordert. Undzwar jenachdem wie hoch der Upload der jeweiligen Person ist. Das steht alles soweit... 

Ich wollte jetzt die 3D Umgebung (Ich will nämlich mein Projekt ausschließlich für den 3D Betrieb bauen) mit einer umfangreichen GUI ergänzen... Swing wäre quasi perfekt...

Nochmal kurz zu dem Swing Prioblem...

Schau mal hier: (Aus: Java ist auch eine Insel)

14.15.2 Pure Java AWT Toolkit (PJA)  toptop

Eine andere Lösung für das Problem ist das Pure Java AWT Toolkit (kurz PJA). Diese hundertprozentige Java-Implementierung ist eine Unterklasse von Graphics und implementiert die Methoden ohne nativen Code. So kann auf einen speziellen Server verzichtet werden, es lassen sich Ressourcen schonen und dennoch Bilder im Hintergrund berechnen. Die Installation ist dabei nicht kompliziert, und da die Bibliothek unter der GNU General Public Licence liegt, lassen sich die Quellen zur Not auch modifizieren. Das Ersatz-AWT wird dabei einfach über die Umgebungsvariable java.awt eingeführt. Der Verweis zeigt auf com.eteks.awt.PJAToolkit, und dann sind keine Modifikationen an den Programmen mehr erforderlich. Die grafische Klasse nutzt nun nicht mehr das native Standard-AWT, sondern PJA.

Das PJAToolkit rendert in einigen Fällen die grafischen Primitiven anders als es die Java-API-Dokumentation beschreibt. So erläutert die Hilfe von Eteks etwa, dass unter MacOS SansSerif anders dargestellt wird und die Ellispsen etwas anders aussehen könnten, da sie mit Bresenham gezeichnet werden.

Die Bibliothek kann mit Beispielprogrammen (GIF generieren, Font-Auszüge erstellen, Servlet erstellt Diagramm, …), FAQ, Quellcode, Jar-Archiven unter eTeks : PJA Toolkit bezogen werden. Im Download befindet sich auch eine Batch-Datei, die zeigt, wie die Variable gesetzt wird und wie die beiden Jar-Dateien heißen, die eingebunden werden müssen. PJA steht unter der GNU General Public License, und der Quellcode kann wie immer eingesehen und modifiziert werden


Hört sich das nicht irgendwie genau danach an ?! Mal schauen inwiefern das irgendwie hilfreich ist..


Gruß, Chris


----------



## Marco13 (27. Jan 2010)

Zugegeben, ich kannte auch weder "Wonderland" noch PJA (sollte mich da mal mehr einlesen...) aber letzteres sieht schon interessant aus. Es ist auch GPL, d.h. man könnte im Prinzip das dort verwendete "PJAImage" direkt durch eine GL-Textur bzw. einen Pixel-Array ersetzen (falls das überhaupt nötig ist: Es wird ja darin schon in einen int-Array geschrieben, und den könnte man im Prinzip 1:1 in eine Textur kopieren). 

An sich ist der Ansatz cool. Ein nicht unerhebliches Problem ist aber: Es ist nur ein Graphics. Und kein Graphics2D. Wenn man Swing verwendet, castet man an 1000 Stellen ganz selbstverständlich ein Graphics nach Graphics2D, und das würde da halt krachen 

Aber nochmal zum einfachsten Ansatz zurück: Wenn man ein BufferedImage vom TYPE_INT_RGB erstellt, und dort (mit dem entsprechenden Graphics oder Graphics2D) reinzeichnet, dann ist das _schnell_. Und von diesem BufferedImage kann man sich über's Raster und den DataBuffer ja _auch_ den Pixel-Array abholen, der direkt als Texturdaten verwendet werden kann. (In Anlehnung an deine Aussage
_Und es müssen keine Images mehr konvertiert werden.. Bei großen Images ist das ja praktisch unmöglich, wenn man einigermaßen gute FPS-Zahlen haben will..._
- was meinst du mit "konvertieren" genau?) Oder anders: Konntest du rausfinden, wo genau da die Performanceprobleme herkommen?


----------



## Kr0e (27. Jan 2010)

Stimmt, das ist kein Graphics2D  Ist mir garnicht aufgefallen. Nagut, das ist natürlich ein Problem.
Aber vlt kann man ja in diesen Ansatz weiter investieren... (Alternatives Toolkit + GraphicsEnviroment)

Zum Punkt konvertieren:

Nagut, das Abbilden einer bestimmten Komponente in ein BufferedImage ist wirklich nicht das Problem (Bei mir vergehen 0-1 ms (Also quasi nichts) bis paintComponent fertig ist. (Natürlich auf ein BufferedImage jetzt!))

Ok, konvertieren muss man nicht, wenn man direkt eine OpenGL Textur erstellt, die vom selben Typ ist. Aber braucht nicht schon allein das Umkopieren von BufferedImage nach Grafikspeicher ne gewisse Zeit (Ich glaube simples Verschieben von Referenzen reicht da nicht) ? Und wenn man jetzt 30 oder 50 mal pro Sekunde 1024*768 integer Variablen kopieren muss... Klar, wenn die Textur einmal im Speicher ist, wird sie super schnell dargestellt...

Nochmal zu Swogl (Hab mir den Quellcode immernoch nicht komplett angeschaut ), wie genau renderst du denn die SwoglComponent ? Du hast eben was von "dreckigen Tricks" oder so geschrieben... Als ich das damals gemacht hab, war das extrems unschön. Vlt. ist deine Lösung besser.

Ich hab von Frame abgeleitet, dann isVisible, isShowing und isDisplayable mit true überschrieben. Außerdem noch "getGraphics()"
mit einem Graphics Objekt von einem BufferedImage überschrieben. setUndecorated(true)!

Dann hab ich ein JDesktopPane hinzugefügt. Darin konnte ich dann schliesslich JInternalFrames korrekt darstellen. Leider war EventHandling unter Mac sone Sache...

Da ich grad Zeit hab, werde ich mal einen genaueren Blick in Swogl werfen...

Gruß,
Chris


----------



## Kr0e (27. Jan 2010)

Ach und nochwas !
Angenommen ich wollte Swogl nutzen... Ist es möglich das so "umzuschrauben", dass es z.B. mit der jME läuft ? Ohne jetzt komplett Swogl zu ändern...


----------



## Kr0e (27. Jan 2010)

Ok, hab nun verstanden wie Swogl das macht. Aber Vorraussetzung ist, dass es ein JFrame oder Frame oder was auch immer gibt, wo das jeweilige JPanel einer SwoglComponent hinzugefügt wird.

Gibt es evt. eine Möglichkeit einfach nur ein JPanel z.b. ohne JFrame direkt in ein BufferedImage zu zeichnen ?

irgendwas wie das hier:


```
JPanel p = new JPanel();
p.setSize(400, 400);
p.setVisible();
p.paint(...);
```

Der Code klappt natürlich nicht. isShowing von dem JPanel ist nämlich false. Aber einfach überschreiben ist doch auch keine Lösung.

Gruß,
Chris


----------



## Marco13 (27. Jan 2010)

Ja, wie gesagt, der Ansatz direkt in "irgendeinen" Pixel-Puffer zu rendern ist cool, aber dort ALLE Funktionalitäten von Graphics bzw. Graphics2D nachzubauen (inklusive Blending, Antialiasing, usw) wäre schon extrem aufwändig. Oder anders gesagt: Der Ansatz würde vielleicht 50000 Zeilen brauchen, und bufferedImage.createGraphics ist EINE Zeile, wo man sicher sein kann, dass alles funktioniert...

Zum Umkopieren... da könnte man sich jetzt verschiedene Ansätze vorstellen ... ist jetzt nur ganz grob rumgesponnen, aber am effizientesten KÖNNTE es sein, dem BufferedImage einen DataBuffer unterzujubeln, der direkt an den von OpenGL (mit MapBuffer) geholten Buffer weiterdelegiert... (Zumindest ist das die einzige Möglichkeit, die ich sehe, um _überhaupt_ um ein Kopieren rumzukommen). Ob DA dann das Zeichnen nur noch 0-1ms braucht, ist eine andere Frage, aber selbst wenn das _etwas_ langsamer wäre, wäre das ja OK. Es kann aber auch gut sein, dass es effizienter wäre, das BufferedImage schön "wie es das gewohnt ist" in seinen DataBuffer schreiben zu lassen, und dann die Daten einmal als Block umzukopieren - ja, das muss dann 30 mal pro Sekunde gemacht werden, aber sooo viele wirklich konzeptionelle Alternativen sehe ich da nicht...

Ja, bei Swogl wird halt "gefakt", in dem Sinne, dass die Components einfach in eine ScrollPane gepackt werden, die _hinter_ der eigentlichen GL-Component des SwoglContainers liegt. Damit braucht man sich um visible, showing, Graphics & Co schon keine Gedanken mehr zu machen, und das Event-Handling wird... naja, zumindest "handhabbar".

Theoretisch kann man mit SwingUtilities (Java Platform SE 6) eine "beliebige" (eigentlich auch nicht-sichtbare) Component malen, aber bei ein paar Tests hat das (zumindest im Kontext von Swogl) nicht soo toll funktioniert... Und vernünftiges Event-Handling (und die richtig fiesen Sachen, wie "MouseOver-Effekte" bei Buttons, oder blinkende Cursor...) könnten damit eklig werden. Ich hatte mir auch mal den Quellcode dieser Methode angesehen, und bei einigem, was dort gemacht wird, pendelte ich schon stark von ???:L in Richtung :autsch: ...


----------



## Kr0e (28. Jan 2010)

Hi,
hab nun eine Lösung gefunden. Ich nutze nun Java TWL. Ist eine OpenGL GUI. Aber die ist wirklich gut im Gegensatz zu FengGUI.
Schade, dass es so schwer ist, Swing umzukrempeln.
Trotzdem danke für deine Tipps und Hilfe.

Gruß Chris


----------

