Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— | programmieren:java:grafikkontext [2021/12/29 11:40] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Richtiger Umgang mit dem Grafikkontext ====== | ||
+ | In Delphi ist es jederzeit erlaubt, sich von einer Komponente einen Grafikkontext (= TCanvas) zu besorgen und darauf zu zeichnen. Das ist insbesondere praktisch, wenn ein Maus-Event eine grafische Reaktion (z.B. Ziehen eines Rechtecks über eine Zeichenfläche) hervorruft. Die Zeichenaktion wird einfach innerhalb der Event-Bearbeitungsmethode platziert. | ||
+ | Auch unter Java kann man sich jederzeit mit JComponent.getGraphics() einen Grafikkontext zu jeder beliebigen Komponente besorgen. Meine ersten Versuche, grafische Reaktionen auf Mausereignisse zu implementieren, | ||
+ | |||
+ | <code java> | ||
+ | public void mousePressed(MouseEvent arg0) { | ||
+ | /* | ||
+ | * Don't do this: | ||
+ | */ | ||
+ | Graphics2D g2d = (Graphics2D) getGraphics(); | ||
+ | g2d.setColor(Color.red); | ||
+ | g2d.drawRect(arg0.getX(), | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Sie produzierten zwar manchmal das richtige Ergebnis, oft kam es aber auch zu sehr seltsamen Artefakten oder zu gar keiner Reaktion. Inzwischen ist mir klar: | ||
+ | ** Zeichnen in Java ist nur innerhalb der PaintComponent(Graphics g) - Methode erlaubt! ** | ||
+ | Es gibt eine [[http:// | ||
+ | * Überschreiben der paintComponent()-Methode, | ||
+ | * Aufruf der Zeichenmethode mit repaint(new Rectangle(...)) oder paintImmediately(...). Dabei das kleinste Rechteck übergeben, das den zu zeichnenden Bereich umfasst. \\ | ||
+ | |||
+ | Ein Problem besteht weiterhin: Alles im übergebenen Rechteck muss ** komplett ** neugezeichnet werden. Im Fall eines vektororientierten Zeichenprogramms kann dies aufwändige Zeichenoperationen vieler hundert kleiner Objekte unter- und überhalb des veränderten Objekts bedeuten. Dies dauert i.a. viel zu lange. | ||
+ | |||
+ | ** Lösung: ** | ||
+ | Zu Beginn der Mausziehaktion werden zwei Puffer (BufferedImage) angelegt. In den ersten wird der Hintergrund sowie alle Objekte ** unterhalb ** des gezogenen Objekts gezeichnet. Der zweite wird zunächst transparent gefüllt. Dann werden alle Objekte hineingezeichnet, | ||
+ | |||
+ | - Ersten Puffer in den Bildschirm kopieren | ||
+ | - gezogenes Objekt zeichnen | ||
+ | - zweiten Puffer in den Bildschirm kopieren | ||
+ | \\ | ||
+ | Befinden sich viele Objekte auf dem Bildschirm, so kommt es durch das Füllen der beiden Puffer zu Beginn des " |