Prinzipien Der Grafikanzeige In Windows
 
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern

Kopiert aus SwingMultithreading

Unter DOS war der Grafikbildschirm unmittelbar zugänglich, Turbo-Pascal & Co unterstützten eine Grafikprogrammierung. Die Regel war: Wurde eine Linie programmtechnisch gezeichnet, dann war sie auch sichtbar. Ganz einfach.

Bei der Arbeit mit mehreren Fenstern (möchte hier nicht Windows sagen, da dieses Wort als Markenname reserviert ist) geht das so nicht mehr. Ist etwas programmtechnisch einmal gezeichnet, dann kann es danach aufgrund von Bedienereingriffen, die mit dem Programm selbst nichts zu tun haben, wieder von der Bildfläche verschwinden müsssen, muss danach wieder auftauchen (Fenster aktivieren, verschieben usw.), ohne dass das eigentliche Programm (sprich: der Anwender-Thread), das inhaltlich für die Grafik verantwortlich ist, dazu ablaufen sollte . Nun gibt es generell zwei Möglichkeiten, das notwendige Verdecken und Neuzeichnen zu realisieren:

  1. Das Gezeichnete wird in einem Speicher als Grafik aufgehoben und vom Betriebssystem nach Bedarf auf den sichtbaren Teil des Bildschirmes (in den Grafikspeicher) kopiert.
  2. Es wird immer neu gezeichnet, wenn das Bild vom Betriebssystem aktualisiert werden muss. Damit wird nicht das Bild selbst irgendwo aufgehoben, sondern stattdesse sind die Regeln für die Erstellung des Bildes (das ist der Inhalt der paint()-Methode) dem Betriebssystem bekannt.
Die erste Variante ist einfach verstehbar (und handhabbar), benötigt aber sehr viel Speicherplatz, jeweils ein kompletter Grafikspeicher pro Applikation. Dieser war in den Anfangszeiten von PCs mit grafischer Oberfläche nicht verfügbar. Soche Versuche gab es Ende der 80-ger in kleinen Ansätzen. Daher hat man sich bei MS-Windows für die zweite Variante entschieden. Andere Entwicklungen liefen parallel in adäquate Richtungen.

Hat man ein Textverarbeitungsprogramm, dann dauert ein Bild-Neuaufbau mit Wysiwig und allem weniger als 1 Sekunde, (so viel ist da auch nicht zu tun), die Infos, die das Aussehen des Bildes letztlich bestimmen, sind die abgelegten Texte mit ihren Formatierungen etc. Der Inhalt der paint()-Routine ist dabei sehr stabil, es ist der Algorithmus des Darstellens von Text + Bildern laut wysiwig. Immer das Gleiche.

Baut man eine komplexere Grafik auf, die möglicherweise in der paint()-Methode Infos von wo ganz anders (aus dem Netzwerk) holen oder lange Berechnungen ausführen muss, dann ist dieses Verfahren nicht so gut. Um eine (Teil-)Grafik zu ändern, müssen erst die zugrundeliegenden Daten geändert vorliegen, dann muss ggf. die gesamte Grafik neu gezeichnet werden. Es gibt also eine Zweiteilung: Der Anwender-Thread ändert die zugrundeliegenden Daten, und teilt dann mit repaint() dem System mit, dass neu gezeichnet werden muss. Die paint()-Routine sollte auch ggf. so intelligent sein, nicht zuviel Rechenzeit zu verbrauchen für bereits gezeichnetes, und nichts unsinnig zu überzeichnen, Problem der bewegten Bilder. Man hätte es viel einfacher, wenn man auf eine Grafikfläche direkt zeichnen würde, und das System kopiert nach den aktuellen Fenster-Notwendigkeiten die richtigen Pixels auf den Grafikspeicher zusammen.

D.h. bei komplexen Grafiken ist das nicht mehr so einfach. Ich habe vor ein paar jahren eine Klasse GraphicStore? unter C++ geschrieben. Diese speicherte, was der Anwender in seinem Thread als Linien, Flächen usw. sehen wollte, mit Befehlscodes ähnlich wmf windows meta format. Die paint()-Routine hat dann abgearbeitet, was in diesem Store stand. Damit ist eine interessante Trennung von Aussehen-Bestimmung (im Anwender-Thread) und paint() (im System-Grafik-Thread) erreicht. Die paint()-Routine ist programmtechnisch stabil, nicht vom Anwenderproblem abhängig , und kann auch geschickt optimiert werden. - Im Grunde ist das Arbeiten mit grafischen Grundelementen eines Dialoges (Box, JLabel, JFileChooser? usw.) nicht anderes. Deren paint()-Methode ist fix, sie werden von außen mit Daten versorgt.

Eine andere interessante Sache in dem Zusammenhang ist die Möglichkeit des Zeichnen in einen Buffer anstatt auf ein Grafikgerät und die Darstellung im Grafikgerät mit copy des Bufferinhaltes. Die Doppel-Bufferung in swing zur Vermeidung von flackerten Bildern bei bewegeter Grafik ist deren konsequente Nutzung. Dann ist das ganze wieder wie bei Variante 1. oben: Direktes Zeichnen:

Dann ist man eigentlich genau bei der oben beschriebenen ersten Variante.

Konkrete Erfahrungen kann ich erst später beitragen (Kontakt mit swing ist bei mir erst neu, 1/2 Jahr, leider anderes zu tun), ich werde das Thema aber wahrscheinlich auch beruflich brauchen.

- dies sei ein Erstbeitrag zur Diskussion. Hartmut Schorrig.


Ja, nur ein paar Anmerkungen.

Das erste Problem in Windows war/ist imho, dass der Programmierer bei der Implementierung der paint-Methode allein gelassen wurde. D. h. er musste selbst darauf kommen, dass er im Prinzip für jedes Fenster ein Objekt definieren muss (imlpizit oder explizit), das weiß, wie es sich selbst (möglichst noch effizient) zeichnet.

Das zweite Problem dieser Methode war/ist, dass ein Neuzeichnen oft mit Löschen des Hintergrundes und Daraufzeichnen verbunden ist, daraus kamen/kommen oft unerwünschte Flackereffekte. Konsequenz war die verwendung von Buffern, in die man zuerst verdeckt zeichnet und die man dann auf den Bildschirm knallt. Wiederum: im Win32 API keine - nicht einmal seelische Unterstützung.

Jetzt sollte man über Buffer, DoppelBuffer? und TripelBuffer? reden, die für Effizienz für MultiMedia/Spiele? interessant sind.

Swing schien immer sehr großzügig mit Buffern und Speicher generell umzugehen, was zu enormem Speicherbedarf und teilweise darüber weder zu Verlangsamungen geführt hat. Ein Mini-Programm mit 30 MB Speicherbedarf schien mal ein Problem und fast inakzeptabel. Wie das heute ist, weiß ich nicht. Wahrscheinlich ist der Speicherbedarf noch höher, es fällt aber nicht mehr so auf. Alternativ stehen jetzt Applikations/GUI/Umgebungen zur Verfügung, der Swing vermeiden und ein nativeres Aussehen haben. Zum Beispiel bei Eclipse. Erfahrung damit habe ich nicht.

-- HelmutLeitner 18. März 2006 12:01 CET


Swing und Speicherplatz/Zeit: Ich habe angefangen mit AWT, weil ich dachte, müsste reiche. Ich habe gelesen, dass swing hungrig ist. Meine Feststellung war aber dann: AWT ist nur ein Relikt. Swing baut darauf auf, Java und Grafik = swing, habe ich schnell gemerkt. ...SWT-Eclipse - am Rande gehört.

Ich habe dann eine Applikation programmiert, die sehr viele Zahlen in einer Matrix darstellen soll, und zwar mit schneller Refreshrate, <300 ms. In einem Container habe ich mehrere 100 JComponent-Instanzen angeordnet, selbstgeschrieben mit eigener paint-Methode. Ich hatte Befürchtungen, dass das ganze lahmt, zuviel CPU-Zeit braucht. War aber nicht. (!!!) Ich habe das Ganze von vornherein so ausgelegt, dass nur diejenige JComponent ein repaint() bekommt, die neue Daten anzeigen soll. Das sind zwar innerhalb einer Sekunde 10 oder 20, aber nicht alle 250! Das ganze braucht nur wenige % Rechenzeit bei meinem alten 800MHz-Notebook, Speicher ? ist genug da (512 MByte RAM). Ich kann also nicht bestätigen, dass Swing irgendwie ein Fresser ist. Es kommt sehr auf die Art der Programmierung an. [Rest des Kommentars bei SwingMultithreading] ... --Hartmut Schorrig


KategorieGrafikProgrammierung
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 18. April 2006 12:22 (diff))
Suchbegriff: gesucht wird
im Titel
im Text