BufferedImage auf JPanel

Dieses Thema BufferedImage auf JPanel im Forum "AWT, Swing, JavaFX & SWT" wurde erstellt von papabaer1707, 28. Dez. 2011.

Thema: BufferedImage auf JPanel In vielen Beiträgen findet man die Möglichkeit auf JPanels mittels der Methode paintComponent zu zeichnen. Als...

  1. In vielen Beiträgen findet man die Möglichkeit auf JPanels mittels der Methode paintComponent zu zeichnen. Als Nachteil könnte sich hier herausstellen, dass ALLES in dieser Methode gezeichnet werden muss. Als eine Alternative, dies zu umgehen, wird die Verwendung eines BufferedImage genannt, welches dann zu gegebener Zeit (in PaintComponent) aufkopiert wird. Diesen Ansatz habe ich mal probiert umzusetzen, allerdings funktioniert es nicht richtig. Erst mal mein Ansatz:

    Code (Java):
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;
    import javax.swing.*;
    import javax.swing.event.*;

    public class PaintSWING extends JFrame {
        // Anfang Attribute
        private byte[][] myColorField = new byte[20][20];
        private BufferedImage zeichenImage;
        private MyCanvasPanel zeichenflaeche = new MyCanvasPanel(zeichenImage);
        private JButton btnDraw = new JButton();

        // Ende Attribute
        public PaintSWING(String title) {
            // Frame-Initialisierung
            super(title);
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

            int frameWidth = 510;
            int frameHeight = 572;
            setSize(frameWidth, frameHeight);

            Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
            int x = (d.width - getSize().width) / 2;
            int y = (d.height - getSize().height) / 2;
            setLocation(x, y);

            Container cp = getContentPane();
            cp.setLayout(null);
            // Anfang Komponenten
            zeichenflaeche.setBounds(7, 2, 500, 500);
            zeichenflaeche.setBackground(Color.WHITE);
            cp.add(zeichenflaeche);
            // Initialisieren / Angleichen der Zeichenflächen
            zeichenflaeche.init();
            btnDraw.setBounds(424, 512, 75, 25);
            btnDraw.setText("Draw");
            btnDraw.setMargin(new Insets(2, 2, 2, 2));
            btnDraw.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        btnDraw_ActionPerformed(evt);
                    }
                });
            cp.add(btnDraw);
            // Ende Komponenten
            setResizable(false);
            setVisible(true);

            zeichenflaeche.repaint();
        }

        // Anfang Methoden
        public void btnDraw_ActionPerformed(ActionEvent evt) {
            Graphics g = zeichenImage.getGraphics();

            for (int x = 0; x < 19; x++) {
                for (int y = 0; y < 19; y++) {
                    int ro = (int) Math.random()*255;
                    int ge = (int) Math.random()*255;
                    int bl = (int) Math.random()*255;
                    g.setColor(new Color(ro, ge, bl));
                    g.fillRect(x * 10, y * 10, 9, 9);
                }
            }
            zeichenflaeche.repaint();
        }

        // Ende Methoden
        public static void main(String[] args) {
            new PaintSWING("Zeichnen in SWING");
        }
    }
    ... und ...

    Code (Java):
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;
    import javax.swing.*;
    import javax.swing.event.*;

    public class MyCanvasPanel extends JPanel {
        private BufferedImage zeichenImage;

        public MyCanvasPanel(BufferedImage zeichenImage) {
            this.zeichenImage = zeichenImage;
        }
       
        public void init() {
            zeichenImage = GraphicsEnvironment.getLocalGraphicsEnvironment()
                                              .getDefaultScreenDevice()
                                              .getDefaultConfiguration()
                                              .createCompatibleImage(this.getWidth(),
                    this.getHeight());
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(zeichenImage, 0, 0, this);
        }
    }
    Nun meine Fragen:
    1. Der Zugriff scheint eigentlich zu funktionieren - nach dem Start erhalte ich ein schwarzes Bild. Dies müsste nach Durchlesen anderer Beiträge zu erwarten sein. Drücke ich jedoch auf den Button sehe ich keine Änderung :(. Liegt es am Zeichnen oder am Zugriff auf das Image beim Kopieren?
    2. Muss ich eigentlich die beiden Images (in den jeweiligen Methoden) angleichen, aslo die Methode init() verwenden? Sieht für mich ein bisschen komisch aus, ohne wirklich zu erkennen warum.
    3. Weshalb benötige ich hier eigentlich das @Override? Zum Überschreiben brauiche ich das sonst eigentlich nie ...
     
  2. Hinweis: KOSTENLOSE Java-Grundlagen DVD. Sichere dir hier den kostenlosen Zugriff auf 7 Stunden Video Java-Know How und starte richtig durch!
  3. Versuchs mal mit
    Code (Java):
    Graphics2D g = zeichenImage.createGraphics();
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    //...hier alle g.tueEtwasAktionen
    g.dispose();
    auf deinem BufferedImage

    Gruß Vanny
     
    Zuletzt von einem Moderator bearbeitet: 28. Dez. 2011
  4. Hm, musste erstmal noch etwas korrigieren:

    Code (Java):
    private BufferedImage zeichenImage = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB);
    Aber die Änderung in Graphics2D zeigt keine Änderung.
     
    Zuletzt bearbeitet: 28. Dez. 2011
  5. hast du auch .createGraphics(); benutzt anstelle von .getGraphics(); ?
    hast du dein g auch mit g.dispose(); geschlossen?

    [EDIT]und 1x1Pixel ist auch recht klein :p[/EDIT]
     
  6. Jupp, genauso:

    Code (Java):
        public void btnDraw_ActionPerformed(ActionEvent evt) {
            Graphics2D g = zeichenImage.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            for (int x = 0; x < 19; x++) {
                for (int y = 0; y < 19; y++) {
                    int ro = (int) Math.random()*255;
                    int ge = (int) Math.random()*255;
                    int bl = (int) Math.random()*255;
                    g.setColor(new Color(ro, ge, bl));
                    g.fillRect(x * 10, y * 10, 9, 9);
                }
            }
            g.dispose();
            zeichenflaeche.repaint();
        }
    Das finale Bild müsste ein 20x20-Bild sein, bei dem jedes Quadrat die Kantenlänge 10px hat ...
     
    Zuletzt bearbeitet: 28. Dez. 2011
  7. Liegt an deinem
    Code (Text):
    init()
    , welches
    Code (Text):
    zeichenImage
    einfach als neues BufferedImage setzt. Im Code von PaintSWING malst du aber auf der alten Referenz rum.
     
  8. Hm, wenn ich das init rausnehme, habe ich den gleichen Effekt, nur dass die ganze Fläche weiß statt schwarz ist - gezeichnet wird trotzdem nichts. Kann es dann hier daran liegen, dass die Größe nicht stimmen?

    Kann das zwar ändern:
    Code (Java):
        private BufferedImage zeichenImage = new BufferedImage(1000,1000,BufferedImage.TYPE_INT_RGB);
    ... nur die Größe wäre am Besten genauso groß, wie die Zeichenfläche.
     
    Zuletzt bearbeitet: 28. Dez. 2011
  9. habs mal so nachgebaut:
    Code (Java):
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.image.BufferedImage;

    import javax.swing.JPanel;


    public class ZeichenPanel extends JPanel{

        private static final long serialVersionUID = 1L;
        private BufferedImage bim;
        private int rasterX = 19, rasterY = 19, tilesWidth = 9, tilesHeight = 9;
       
        public ZeichenPanel(){
            zeichneImage();
            repaint();
        }
       
        private void zeichneImage(){
            bim = new BufferedImage(rasterX*tilesWidth, rasterY*tilesHeight, BufferedImage.TYPE_INT_RGB);
           
            Graphics2D g2d = bim.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
           
            for (int x = 0; x < rasterX; x++) {
                for (int y = 0; y < resterY; y++) {
                    int ro = (int) Math.random()*255;
                    int ge = (int) Math.random()*255;
                    int bl = (int) Math.random()*255;
                    System.out.println(ro + ", " + ge + ", " + bl);
                    g2d.setColor(new Color(ro, ge, bl));
                    g2d.fillRect(x * (tilesWidth+1), y * (tilesHeight+1), tilesWidth, tilesHeight);
                }
            }
            g2d.dispose();
        }
       
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            if(bim != null){
                g.drawImage(bim, 0, 0, bim.getWidth(), bim.getHeight(), null);
            }
        }
    }
    und das sysout gibt nur "0, 0, 0" also is das mit dem schwarzen bild kein Wunder :p

    [EDIT]
    ich bin mal nich so
    Code (Java):
    int ro = (int) (Math.random()*255);
                    int ge = (int) (Math.random()*255);
                    int bl = (int) (Math.random()*255);
    löst dein Problem :p
    [/EDIT]
     
    Zuletzt von einem Moderator bearbeitet: 28. Dez. 2011
  10. Oje, so ein Fehler - lasse den ständig auf 0 rumhüpfen.

    Scheint nun ganz gut zu funktionieren - hatte ja doch die richtigen Ideen (bis auf eine Ausnahme :)).

    Wie kann ich nun die Größen anpassen. Im Grunde kann ich die Größe des Image so groß machen, dass es keine Probleme gibt. Ist das egal, oder macht es überhaupt Sinn diese Anpassung vorzunehmen?
     
  11. schau dir meinen Code an, da is die Größe je nach Raster und Rechteckgröße angepasst.

    ...oder wie darf man deine Frage verstehen?

    [EDIT]
    habs nochmal angepasst
    Code (Java):
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.image.BufferedImage;

    import javax.swing.JPanel;


    public class ZeichenPanel extends JPanel{

        private static final long serialVersionUID = 1L;
        private BufferedImage bim;
        private int rasterX = 19, rasterY = 19, tilesWidth = 9, tilesHeight = 9;
       
        public ZeichenPanel(){
            zeichneImage();
            repaint();
        }
       
        private void zeichneImage(){
            bim = new BufferedImage(rasterX*(tilesWidth+1), rasterY*(tilesHeight+1), BufferedImage.TYPE_INT_RGB);
            this.setPreferredSize(new Dimension(bim.getWidth(), bim.getHeight()));
            Graphics2D g2d = bim.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
           
            for (int x = 0; x < 19; x++) {
                for (int y = 0; y < 19; y++) {
                    int ro = (int) (Math.random()*255);
                    int ge = (int) (Math.random()*255);
                    int bl = (int) (Math.random()*255);
                    System.out.println(ro + ", " + ge + ", " + bl);
                    g2d.setColor(new Color(ro, ge, bl));
                    g2d.fillRect(x * (tilesWidth+1), y * (tilesHeight+1), tilesWidth, tilesHeight);
                }
            }
            g2d.dispose();
        }
       
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            if(bim != null){
                g.drawImage(bim, 0, 0, bim.getWidth(), bim.getHeight(), null);
            }
        }
    }
     
    dann in deinem JFrame nochmal pack(); und es passt.
    [/EDIT]
     
    Zuletzt von einem Moderator bearbeitet: 29. Dez. 2011
  12. Ja, das stimmt, nur ist dieses (wenn auch künstlerisch wertvolle) Bild nur als Beispiel gedacht. Gezeichnet werden könnten ja beliebige Figuren. Bei mir habe ich ich ein Panel mit einer vorgegebenen Größe und ein Image, welches ich gerne an diese Größe (automatisch) anpassen möchte. Ich denke mal, dass ich das zu kompliziert sehe ... ich kenne die Größe des Panels, also gebe ich die Größe des Images so ein - automatisch wäre nur schöner :)

    ... sehe schon - war zu schnell für deine Ergänzung ...
     
  13. dann übergib doch die Größe des Panels an dein Image :p???:L
     
  14. Kostenlose Java-Grundlagen DVD im Wert von 29,95 € heute kostenlos sichern (Klick)
Die Seite wird geladen...

BufferedImage auf JPanel - Ähnliche Themen

Forum Datum
JPanel Graphic2D als BufferedImage Speichern AWT, Swing, JavaFX & SWT 28. Nov. 2013
JPanel in Bufferedimage AWT, Swing, JavaFX & SWT 8. Juni 2010
JPanel - BufferedImage - zeichnen großer Bilder AWT, Swing, JavaFX & SWT 19. Juni 2009
BufferedImage und ByteArray Allgemeine Java-Themen 1. Sep. 2015
BufferedImage, Thread Concurrency Allgemeine Java-Themen 18. Aug. 2015
Interessante Stellenangebote


Weitere Stellenanzeigen

Stellenanzeige Mediadaten