Java-Forum.org  

Zurück   Java-Forum.org > Java - Programmierung > AWT, Swing, JavaFX & SWT

AWT, Swing, JavaFX & SWT: BufferedImage auf JPanel

Themen zur Programmierung von Benutzer-Oberflächen (GUI, Applet) sowie zur Grafikprogrammierung (2D / 3D)

Antwort    
Themen-Optionen Thema durchsuchen Ansicht
Alt 28.12.2011, 21:53   #1
papabaer1707
 
BufferedImage auf JPanel - Standard BufferedImage auf JPanel

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:

Java Code: Quelltext in neuem Fenster öffnen
  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import java.awt.image.BufferedImage;
  4. import javax.swing.*;
  5. import javax.swing.event.*;
  6.  
  7. public class PaintSWING extends JFrame {
  8.     // Anfang Attribute
  9.     private byte[][] myColorField = new byte[20][20];
  10.     private BufferedImage zeichenImage;
  11.     private MyCanvasPanel zeichenflaeche = new MyCanvasPanel(zeichenImage);
  12.     private JButton btnDraw = new JButton();
  13.  
  14.     // Ende Attribute
  15.     public PaintSWING(String title) {
  16.         // Frame-Initialisierung
  17.         super(title);
  18.         setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
  19.  
  20.         int frameWidth = 510;
  21.         int frameHeight = 572;
  22.         setSize(frameWidth, frameHeight);
  23.  
  24.         Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
  25.         int x = (d.width - getSize().width) / 2;
  26.         int y = (d.height - getSize().height) / 2;
  27.         setLocation(x, y);
  28.  
  29.         Container cp = getContentPane();
  30.         cp.setLayout(null);
  31.         // Anfang Komponenten
  32.         zeichenflaeche.setBounds(7, 2, 500, 500);
  33.         zeichenflaeche.setBackground(Color.WHITE);
  34.         cp.add(zeichenflaeche);
  35.         // Initialisieren / Angleichen der Zeichenflächen
  36.         zeichenflaeche.init();
  37.         btnDraw.setBounds(424, 512, 75, 25);
  38.         btnDraw.setText("Draw");
  39.         btnDraw.setMargin(new Insets(2, 2, 2, 2));
  40.         btnDraw.addActionListener(new ActionListener() {
  41.                 public void actionPerformed(ActionEvent evt) {
  42.                     btnDraw_ActionPerformed(evt);
  43.                 }
  44.             });
  45.         cp.add(btnDraw);
  46.         // Ende Komponenten
  47.         setResizable(false);
  48.         setVisible(true);
  49.  
  50.         zeichenflaeche.repaint();
  51.     }
  52.  
  53.     // Anfang Methoden
  54.     public void btnDraw_ActionPerformed(ActionEvent evt) {
  55.         Graphics g = zeichenImage.getGraphics();
  56.  
  57.         for (int x = 0; x < 19; x++) {
  58.             for (int y = 0; y < 19; y++) {
  59.                 int ro = (int) Math.random()*255;
  60.                 int ge = (int) Math.random()*255;
  61.                 int bl = (int) Math.random()*255;
  62.                 g.setColor(new Color(ro, ge, bl));
  63.                 g.fillRect(x * 10, y * 10, 9, 9);
  64.             }
  65.         }
  66.         zeichenflaeche.repaint();
  67.     }
  68.  
  69.     // Ende Methoden
  70.     public static void main(String[] args) {
  71.         new PaintSWING("Zeichnen in SWING");
  72.     }
  73. }

... und ...

Java Code: Quelltext in neuem Fenster öffnen
  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import java.awt.image.BufferedImage;
  4. import javax.swing.*;
  5. import javax.swing.event.*;
  6.  
  7. public class MyCanvasPanel extends JPanel {
  8.     private BufferedImage zeichenImage;
  9.  
  10.     public MyCanvasPanel(BufferedImage zeichenImage) {
  11.         this.zeichenImage = zeichenImage;
  12.     }
  13.    
  14.     public void init() {
  15.         zeichenImage = GraphicsEnvironment.getLocalGraphicsEnvironment()
  16.                                           .getDefaultScreenDevice()
  17.                                           .getDefaultConfiguration()
  18.                                           .createCompatibleImage(this.getWidth(),
  19.                 this.getHeight());
  20.     }
  21.  
  22.     @Override
  23.     public void paintComponent(Graphics g) {
  24.         super.paintComponent(g);
  25.         g.drawImage(zeichenImage, 0, 0, this);
  26.     }
  27. }

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 ...
 

 
Anzeige
 

AW: BufferedImage auf JPanel



 
Alt 28.12.2011, 22:01   #2
 
BufferedImage auf JPanel - Standard AW: BufferedImage auf JPanel

Versuchs mal mit
Java Code: Quelltext in neuem Fenster öffnen
  1. Graphics2D g = zeichenImage.createGraphics();
  2. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  3. //...hier alle g.tueEtwasAktionen
  4. g.dispose();
auf deinem BufferedImage

Gruß Vanny
 
Alt 28.12.2011, 22:10   #3
papabaer1707
Themenstarter
 
BufferedImage auf JPanel - Standard AW: BufferedImage auf JPanel

Hm, musste erstmal noch etwas korrigieren:

Java Code: Quelltext in neuem Fenster öffnen
  1. private BufferedImage zeichenImage = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB);

Aber die Änderung in Graphics2D zeigt keine Änderung.
 
Alt 28.12.2011, 22:14   #4
 
BufferedImage auf JPanel - Standard AW: BufferedImage auf JPanel

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
 
Alt 28.12.2011, 22:16   #5
papabaer1707
Themenstarter
 
BufferedImage auf JPanel - Standard AW: BufferedImage auf JPanel

Jupp, genauso:

Java Code: Quelltext in neuem Fenster öffnen
  1. public void btnDraw_ActionPerformed(ActionEvent evt) {
  2.         Graphics2D g = zeichenImage.createGraphics();
  3.         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  4.  
  5.         for (int x = 0; x < 19; x++) {
  6.             for (int y = 0; y < 19; y++) {
  7.                 int ro = (int) Math.random()*255;
  8.                 int ge = (int) Math.random()*255;
  9.                 int bl = (int) Math.random()*255;
  10.                 g.setColor(new Color(ro, ge, bl));
  11.                 g.fillRect(x * 10, y * 10, 9, 9);
  12.             }
  13.         }
  14.         g.dispose();
  15.         zeichenflaeche.repaint();
  16.     }

Das finale Bild müsste ein 20x20-Bild sein, bei dem jedes Quadrat die Kantenlänge 10px hat ...
 
Alt 28.12.2011, 22:21   #6
xehpuk
 
BufferedImage auf JPanel - Standard AW: BufferedImage auf JPanel

Liegt an deinem init() , welches zeichenImage einfach als neues BufferedImage setzt. Im Code von PaintSWING malst du aber auf der alten Referenz rum.
 
Alt 28.12.2011, 22:26   #7
papabaer1707
Themenstarter
 
BufferedImage auf JPanel - Standard AW: BufferedImage auf JPanel

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:
Java Code: Quelltext in neuem Fenster öffnen
  1. 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.
 
Alt 28.12.2011, 22:34   #8
 
BufferedImage auf JPanel - Standard AW: BufferedImage auf JPanel

habs mal so nachgebaut:
Java Code: Quelltext in neuem Fenster öffnen
  1. import java.awt.Color;
  2. import java.awt.Graphics;
  3. import java.awt.Graphics2D;
  4. import java.awt.RenderingHints;
  5. import java.awt.image.BufferedImage;
  6.  
  7. import javax.swing.JPanel;
  8.  
  9.  
  10. public class ZeichenPanel extends JPanel{
  11.  
  12.     private static final long serialVersionUID = 1L;
  13.     private BufferedImage bim;
  14.     private int rasterX = 19, rasterY = 19, tilesWidth = 9, tilesHeight = 9;
  15.    
  16.     public ZeichenPanel(){
  17.         zeichneImage();
  18.         repaint();
  19.     }
  20.    
  21.     private void zeichneImage(){
  22.         bim = new BufferedImage(rasterX*tilesWidth, rasterY*tilesHeight, BufferedImage.TYPE_INT_RGB);
  23.        
  24.         Graphics2D g2d = bim.createGraphics();
  25.         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  26.        
  27.         for (int x = 0; x < rasterX; x++) {
  28.             for (int y = 0; y < resterY; y++) {
  29.                 int ro = (int) Math.random()*255;
  30.                 int ge = (int) Math.random()*255;
  31.                 int bl = (int) Math.random()*255;
  32.                 System.out.println(ro + ", " + ge + ", " + bl);
  33.                 g2d.setColor(new Color(ro, ge, bl));
  34.                 g2d.fillRect(x * (tilesWidth+1), y * (tilesHeight+1), tilesWidth, tilesHeight);
  35.             }
  36.         }
  37.         g2d.dispose();
  38.     }
  39.    
  40.     public void paintComponent(Graphics g){
  41.         super.paintComponent(g);
  42.         if(bim != null){
  43.             g.drawImage(bim, 0, 0, bim.getWidth(), bim.getHeight(), null);
  44.         }
  45.     }
  46. }

und das sysout gibt nur "0, 0, 0" also is das mit dem schwarzen bild kein Wunder :P

Edit:

ich bin mal nich so
Java Code: Quelltext in neuem Fenster öffnen
  1. int ro = (int) (Math.random()*255);
  2.                 int ge = (int) (Math.random()*255);
  3.                 int bl = (int) (Math.random()*255);
löst dein Problem :P
Miniaturansicht angehängter Grafiken
BufferedImage auf JPanel-bunt.png  
 
Alt 28.12.2011, 22:48   #9
papabaer1707
Themenstarter
 
BufferedImage auf JPanel - Standard AW: BufferedImage auf JPanel

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?
 
Alt 28.12.2011, 22:52   #10
 
BufferedImage auf JPanel - Standard AW: BufferedImage auf JPanel

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
Java Code: Quelltext in neuem Fenster öffnen
  1. import java.awt.Color;
  2. import java.awt.Dimension;
  3. import java.awt.Graphics;
  4. import java.awt.Graphics2D;
  5. import java.awt.RenderingHints;
  6. import java.awt.image.BufferedImage;
  7.  
  8. import javax.swing.JPanel;
  9.  
  10.  
  11. public class ZeichenPanel extends JPanel{
  12.  
  13.     private static final long serialVersionUID = 1L;
  14.     private BufferedImage bim;
  15.     private int rasterX = 19, rasterY = 19, tilesWidth = 9, tilesHeight = 9;
  16.    
  17.     public ZeichenPanel(){
  18.         zeichneImage();
  19.         repaint();
  20.     }
  21.    
  22.     private void zeichneImage(){
  23.         bim = new BufferedImage(rasterX*(tilesWidth+1), rasterY*(tilesHeight+1), BufferedImage.TYPE_INT_RGB);
  24.         this.setPreferredSize(new Dimension(bim.getWidth(), bim.getHeight()));
  25.         Graphics2D g2d = bim.createGraphics();
  26.         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  27.        
  28.         for (int x = 0; x < 19; x++) {
  29.             for (int y = 0; y < 19; y++) {
  30.                 int ro = (int) (Math.random()*255);
  31.                 int ge = (int) (Math.random()*255);
  32.                 int bl = (int) (Math.random()*255);
  33.                 System.out.println(ro + ", " + ge + ", " + bl);
  34.                 g2d.setColor(new Color(ro, ge, bl));
  35.                 g2d.fillRect(x * (tilesWidth+1), y * (tilesHeight+1), tilesWidth, tilesHeight);
  36.             }
  37.         }
  38.         g2d.dispose();
  39.     }
  40.    
  41.     public void paintComponent(Graphics g){
  42.         super.paintComponent(g);
  43.         if(bim != null){
  44.             g.drawImage(bim, 0, 0, bim.getWidth(), bim.getHeight(), null);
  45.         }
  46.     }
  47. }
dann in deinem JFrame nochmal pack(); und es passt.
 
Antwort    

Zurück   Java-Forum.org > Java - Programmierung > AWT, Swing, JavaFX & SWT

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Ähnliche Themen: BufferedImage auf JPanel

JPanel Graphic2D als BufferedImage Speichern
JPanel Graphic2D als BufferedImage Speichern: Hallo zusammen, ich bin gerade dabei mir ein kleines Zeichenprogramm zu schreiben, nur leider klappt das mit dem Speichern nicht so wirklich. Also ich habe eine Klasse PaintBrushDrawingBoard...
BufferedImage -> Feature Extraktion. Unterschiedliche BufferedImage imageTypes problem
BufferedImage -> Feature Extraktion. Unterschiedliche BufferedImage imageTypes problem: Hallo ihr Lieben. Ich bin gerade dabei mit Hilfe einer Library einen einfachen Bilder-Ähnlichkeits Berechner zu proggen. Hierfür habe ich Bilder in unterschiedlichen Formaten. Falls ich: ...
JPanel in Bufferedimage
JPanel in Bufferedimage: Hallo liebe Leute, ich arbeite gerade im Rahmen eines privaten Spielchens an einem sich zufällig erstelltendem Terrain welches auf Basis von Perlin Noise geschieht. Wenn alles erfolgreich durch ist...
JPanel - BufferedImage - zeichnen großer Bilder
JPanel - BufferedImage - zeichnen großer Bilder: Hi zusammen, ich habe eine Frage, bzw. ein Problem mit der Effizienz meines Programms. Stell euch vor, ihr müsst riesige Daten in einem JPanel abbilden. DAs Zeichnen dieses Panels dauert sehr...
Jpanel -> BufferedImage konvertieren
Jpanel -> BufferedImage konvertieren: Hi, ich hab hier ein JPanel auf dem ein paar Komponenten liegen. Ich brauche von diesem Panel ein BufferedImage. Wie mache ich das?




Sie betrachten gerade BufferedImage auf JPanel