Jpanel Graphik speichern

Status
Nicht offen für weitere Antworten.
M

me82

Gast
Hallo zusammen,

bin in Grafikprogrammierung noch recht neu und wollte mir ein Programm schreiben mit dem ich
mit der Maus in einem JPanel malen kann. Daraufhin bin ich in diesem Forum auf diesen Thread
http://forum.java.sun.com/thread.jspa?forumID=57&threadID=607073&start=1 gekommen.
Hab das ganze ein wenig umgeschieben und meinen Bedürfnissen angepasst.
Nun möchte ich das gemalte gerne speichern.

Mein erster Versuch war eine Speicherklasse st zu erstellen die das JPanel (bzw die JPanel, sollen mal mehrere werden)
in einer Liste vorhält und Serializable implementiert.
Code:
objOut = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("test")));
objOut.writeObject(st);

Fehler dabei war dann :
java.io.NotSerializableException: sun.awt.image.OffScreenImage
...
bzw das Graphics2d Object

Alle weiteren Versuche z.B. das JPanel Serializable implementieren zu lassen oder über eine
getter Methode an das Image heranzukommen schlugen fehl
Code:
public BufferedImage getImage() {
        BufferedImage img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
        img = (BufferedImage) createImage(getWidth(), getHeight());
        return img;
    }

Gleicher Fehler : java.io.NotSerializableException: ...
Die Speicherklasse hab ich natürlich dementsprechend geändert.

Meine Frage ist also, ob es eine Möglichkeit gibt, sich beim Speichern das aktuelle offscreenImage zu holen (hoffe
ich habe das richtig ausgedrückt) und dieses (bzw. mehrere bei mehreren panels (das krieg ich dann schon hin :wink: )) abzuspeichern und beim laden dann dem panel per
Code:
setImage(...) {
this.image = newImage;
repaint();
}


das offsetImage zu übergeben, dieses zeichnen und dort dann weitermalen zu können?

Das Image als jpeg in eine Datei zu schreiben funktioniert, falls ich darauf aufbauen kann. Wollt ich aber eigentlich vermeiden. (aber wenn ich das dann im Panel zeichnen kann beim Laden solls mir recht sein).

Danke schon einmal und mfg
me82
 

Schnitter

Bekanntes Mitglied
Nuja, OffScreenImage implementiert Serializable eben nicht?!
Ich weiß jetzt grad nicht, ob das eine deirner Klassen ist, aber ich denk mal eher nicht.

(Warum heißt das bei dir sun.awt.image... und nicht java.awt.image?)

Jetzt mal ne kleine Vertständnisfrage: Willst du die Panels auf eine Grafik(BufferedImage) oder direkt auf den Frame zeichnen?

Als BufferedImage würd ich einfach ImageIO benutzen ums abzuspeichern.

Wenn dus auf den Frame zeichnen willst, würd' ich eifnach via xml die Position und die Größe abspeichern.


MfG
 
M

Me82

Gast
Danke Dir erst mal für die schnelle Antwort,

Ich erklars mal ein wenig genauer,

ich habe einen JFrame, in diesem ein JTabbedPane und diesem füge ich meine DrawingPanels über ein Menü hinzu.
Soweit kein Thema.

Beim speichern laufe ich über alle panels mit
Code:
private void jmiSaveCompleteActionPerformed(java.awt.event.ActionEvent evt) {                                                
        ObjectOutputStream objOut = null;
        try {
        //jtpSites ist das JTabbedPane    
        for (int i = 0; i < jtpSites.getTabCount(); i++) {
                DrawingPanel p = (DrawingPanel) jtpSites.getComponentAt(i);
                //st is meine Speicherklasse
                st.addSite(p);
            }
            objOut = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("test.jpen")));
            objOut.writeObject(st);            
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                objOut.close();
            }
            catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

So hab ich mir das vorgestellt, aber wie Du sagts wird Serializable nicht implementiert...

Ich poste noch mal die Speicherklasse, nix besonderes
Code:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class SiteStorage implements Serializable {

    private List<DrawingPanel> allSites = new ArrayList<DrawingPanel>();
    
    public SiteStorage() {        
    }
    
    public List<DrawingPanel> getAllSites() {
        return allSites;
    }
    
    public void addSite(DrawingPanel dp) {
        allSites.add(dp);
    }
    
    public DrawingPanel get(int i) {
        return allSites.get(i);
    }
}

Und zu guter Letzt das JPanel zum zeichnen, wollte es eh in Codeschnipsel u. Projekte stellen also warum nid
gleich so... :wink:

Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.JColorChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class DrawingPanel extends JPanel implements MouseListener, MouseMotionListener {
    
    //Zum testen nicht serialisieren
    private transient Image image;
    private transient Graphics2D g2d;
    
    private int brushSize = 3;
    private Point lastPoint;
    private Color paintColor = Color.BLACK;
    
    private JMenuBar bar = new JMenuBar();
    private JMenu options = new JMenu("Optionen");
    private JMenuItem increasePen = new JMenuItem("Stift vergrößern");
    private JMenuItem decreasePen = new JMenuItem("Stift verkleinern");
    private JMenuItem normalPen = new JMenuItem("Stift zurücksetzen");
    private JMenuItem color = new JMenuItem("Farbe wählen");

    public DrawingPanel() {
        addMouseListener(this);
        addMouseMotionListener(this);
        this.setLayout(new BorderLayout());
        increasePen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_MASK));
        increasePen.setMnemonic('+');
        increasePen.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                brushSize++;                
            }
        });
        decreasePen.setMnemonic('-');
        decreasePen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_MASK));
        decreasePen.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if(brushSize > 1) {
                    brushSize--;
                }
            }
        });
        normalPen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.CTRL_MASK));
        normalPen.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {                
                brushSize = 3;
            }
        });
        
        color.setMnemonic('C');
        color.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
        color.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                paintColor = JColorChooser.showDialog(null, "Farbe auswählen", Color.BLACK);
            }
        });
        
        options.setMnemonic('O');
        options.add(increasePen);
        options.add(decreasePen);
        options.add(normalPen);
        options.addSeparator();
        options.add(color);
        bar.add(options);
        add(bar, BorderLayout.PAGE_START);        
    }

    public void mouseClicked(MouseEvent e) {        
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {        
    }

    public void mouseMoved(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
        lastPoint = e.getPoint();
        draw(lastPoint);        
    }

    public void mouseDragged(MouseEvent e) {
        if(!e.isShiftDown()) {
            double xDelta = e.getX() - lastPoint.getX();
            double yDelta = e.getY() - lastPoint.getY();
            double delta = Math.max(Math.abs(xDelta), Math.abs(yDelta));
            double xIncrement = xDelta / delta;
            double yIncrement = yDelta / delta;

            double xStart = lastPoint.getX();
            double yStart = lastPoint.getY();

            for (int i = 0; i < delta; i++) {
                Point interpolated = new Point((int) xStart, (int) yStart);
                draw(interpolated);
                xStart += xIncrement;
                yStart += yIncrement;
            }

            draw(e.getPoint());
            lastPoint = e.getPoint();
        }
        else {
            g2d.setColor(Color.WHITE);
            g2d.fillRect(e.getX(), e.getY(), 30, 30);
            drawGrid();
            repaint();
        }        
    }    

    //wird nicht verwendet. War einer meiner erfolglosen Tests
    public BufferedImage getImage() {
        BufferedImage img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
        img = (BufferedImage) createImage(getWidth(), getHeight());
        return img;
    }
    
    //Ebenso nicht verwendet...
    public void setImage(Image i) {
        image = i;
        repaint();
    }
    
    private void drawGrid() {
        setColor(Color.BLACK);
        for (int i = bar.getHeight(); i < getHeight(); i += 30) {
            g2d.drawLine(0, i, getWidth(), i);
        }
        for (int i = 0; i < getWidth(); i += 30) {
            g2d.drawLine(i, 0, i, getHeight());
        }        
        setColor(paintColor);
    }
    
    private void setColor(Color newColor) {
        g2d.setColor(newColor);
    }
    
    private void draw(Point start) {
        setColor(paintColor);
        int x = start.x - (brushSize / 2) + 1;
        int y = start.y - (brushSize / 2) + 1;
        g2d.fillOval(x, y, brushSize, brushSize);
        repaint(x, y, brushSize, brushSize);
    }    

    public void clearPaint() {
        g2d.setColor(Color.white);
        g2d.fillRect(0, 0, getWidth(), getHeight());
        drawGrid();
        
        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        if (image == null) {
            image = createImage(getWidth(), getHeight());
            
            g2d = (Graphics2D) image.getGraphics();

            g2d.setColor(Color.white);
            g2d.fillRect(0, 0, getWidth(), getHeight());
            
            drawGrid();

            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);

        }
        
        Rectangle r = g.getClipBounds();
        g.drawImage(image, r.x, r.y, r.width + r.x, r.height + r.y,
                r.x, r.y, r.width + r.x, r.height + r.y, null);
    }
}

Vllt kann ja jemand damit schon was anfangen und um zu Zeigen was ich machen möchte.
Wie man sieht würde ich gerne beim speichern alle Panels durchgehn und diese speichern.

@Schnitter
Hab verstanden warum das nicht klappt, danke Dir. Wollte nur zeigen wie ich mir das ganze gedacht habe :wink:
Seh nur leider noch keine Lösung...

Warum da sun.awt.image.OffScreenImage steht kann ich leider nid sagen...

Anfang Exception :

java.io.NotSerializableException: sun.awt.image.OffScreenImage
at java.io_ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
at java.io_ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
at java.io_ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
at java.io_ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
...
So rauskopiert.

Mfg
me82
 

Marco13

Top Contributor
Hm - willst du wirklich die Panels serialisieren? Das sollte man eigentlich nich (für langfistige Speicherung) machen. Da ist die Kompatibilität zwischen verschiedenen Java-Versionen nicht zugesichert. Wenn du nur die Bilder speichern willst, kannst du sowas machen wie
BufferedImage bi = new BufferedImage(...);
drawPanel.paintComponent(bi.getGraphics());
ImageIO.write(bi, ...);
 
M

me82

Gast
Danke für deine Antwort, ich dachte die Panels zu serialisieren wäre die einfachste Lösung.
Ich werde es heute abend mal mit deinem Vorschlag versuchen die Images wegzuschreiben
und dann diese wieder zu laden.

mfg
 
M

me82

Gast
Also ich habs nun doch so gemacht, dass ich die Panels als *.jpg speichere ( evtl noch in einer Datenstruktur zusammengefasst) und beim laden dann das Image pro Panel neu setzte ( paar Änderungen warn noch nötig aber alles halb so wild).

Die dazugehörigen Einstellungen wie Farbe oder Pinselgröße speichere ich dann separat entweder in einer
Property-Datei ( da hab ich mir mal ne Library geschrieben zum einfachen verwalten) oder in XML...mal schauen

Würde denn Interesse an so einem Programm bestehn, dann würde ich es erstens nicht nur für mich entwickeln, sondern besser :wink: , und auch mal in die Projekte stellen.
Meine Intention war es beim lernen, in meinem Fall Mathe, nicht immer 30 Seiten ausm Block verbrauchen zu müssen und das ganze auch mal mit anderen schnell austauschen zu können. Is natürlich Gewöhnungssache und nen Pen/Tablet is zu empfehlen aber kann ganz praktisch sein. :wink:

Schreibt doch mal was ihr von so nem Ersatzblock haltet... :toll: :bloed:
(Natürlich dann in besserer Form, hab ja dann nen Anreiz)

mfg
me82
 

Marco13

Top Contributor
Ohne deinen Enthusiasmus dämpfen zu wollen: Du solltest nicht darauf bauen, dass irgendjemand so ein Programm braucht. Die Idee, mehrere Seiten "zusammengepackt" zu speichern ist ganz lustig (obwohl ich bisher noch nichts gefunden habe, was einen Block und einen Bleistift ersetzen könnte) aber manchmal ist Programmieren ja auch ein bißchen Selbstzweck :wink:
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
R JPanel wird erst im Fullscreen angezeigt Spiele- und Multimedia-Programmierung 1
P selectedItem aus einem Methodenerstellten JPanel auslesen. Spiele- und Multimedia-Programmierung 5
M JPanel mit Graphics2D Objekten mit JScrollpane Spiele- und Multimedia-Programmierung 6
K JPanel wechseln & Neu starten - SnakeSpiel Spiele- und Multimedia-Programmierung 2
A paintComponent in JPanel in JFrame Spiele- und Multimedia-Programmierung 7
N JPanel Inhalt aktualisiert nach Thread.sleep nicht Spiele- und Multimedia-Programmierung 2
S Thread und jpanel-paintcomponent kombinierbar?? Spiele- und Multimedia-Programmierung 14
E Animiertes JPanel dynamisch wechseln Spiele- und Multimedia-Programmierung 3
W Panel/JPAnel createImage() Exception Spiele- und Multimedia-Programmierung 2
R Probleme mit JPanel!KeyListener geht nicht Spiele- und Multimedia-Programmierung 6
T Problem bei LinkedList / JPanel Spiele- und Multimedia-Programmierung 4
C 2D Sprites an die JPanel Größe (Auflösung) anpassen/skalieren Spiele- und Multimedia-Programmierung 3
F Vektorgrafik in JPanel Spiele- und Multimedia-Programmierung 5
E Active Rendering im FSEM auf ein JPanel? Spiele- und Multimedia-Programmierung 4
L 2D-Spiele ruckeln auf JPanel Spiele- und Multimedia-Programmierung 7
A Mehrere geometrische Objekte in JPanel zeichnen Spiele- und Multimedia-Programmierung 4
X JPanel dynamisch (Koordinatensystem)? Spiele- und Multimedia-Programmierung 30
DamienX Canvas vs JPanel Spiele- und Multimedia-Programmierung 15
S Problem mit JPanel bzw p a i n t Spiele- und Multimedia-Programmierung 6
K stringWidth bei Graphics von JPanel und Printer unterschiedl Spiele- und Multimedia-Programmierung 4
R SimpleUniverse in JPanel Spiele- und Multimedia-Programmierung 4
M 1. Menüleiste wird doppelt gezeichnet 2. awt auf ein jpanel Spiele- und Multimedia-Programmierung 4
M Jpanel mit Keylistener Spiele- und Multimedia-Programmierung 6
D 2D Graphic Objekte in ein JPanel einfügen Spiele- und Multimedia-Programmierung 2
W Graphik über den Bildschirm legen (Windows) Spiele- und Multimedia-Programmierung 9
N Java-Rollenspiel-Graphik Spiele- und Multimedia-Programmierung 12
C Speichern von Daten mit Mysql Spiele- und Multimedia-Programmierung 4
J Fertigungstechnik.. PLS HALP.. Quellcode vom Text in java-Klasse speichern Spiele- und Multimedia-Programmierung 2
M Bilder effizient speichern/serialisieren Spiele- und Multimedia-Programmierung 10
Devil0s 2D Stadt Generator/2D Welt speichern OHNE Tiles Spiele- und Multimedia-Programmierung 5
N [SLICK] Rectangle in Array Speichern Spiele- und Multimedia-Programmierung 3
M MJPEG Stream aufnehmen (Speichern und von VirtualDub weiterverarbeiten lassen). Spiele- und Multimedia-Programmierung 2
A Speichern un Laden mit Serializable Spiele- und Multimedia-Programmierung 4
B Daten speichern: Reflexion vs Serializable Spiele- und Multimedia-Programmierung 8
A PNG pixelweise/blockweise speichern? Spiele- und Multimedia-Programmierung 2
F Programm für Bildbearbeitung gesucht: Skalieren und Speichern Spiele- und Multimedia-Programmierung 6
Y Jede Aktion sofort speichern Spiele- und Multimedia-Programmierung 5
aze Java 3D : 3D Objekte speichern und später wieder einlesen Spiele- und Multimedia-Programmierung 9
H Speichern und Öffnen von einem Zeichenprogramm Spiele- und Multimedia-Programmierung 4
S benutzerdefiniertes Tileset in Datei speichern Spiele- und Multimedia-Programmierung 3
J Zeichnen in BufferedImage und dieses in Datei speichern Spiele- und Multimedia-Programmierung 2
A Bilder(BMP) speichern Spiele- und Multimedia-Programmierung 2
H Jpeg Bildinformation in ein Char Array speichern? Spiele- und Multimedia-Programmierung 4
U JPG in größe ändern und speichern Spiele- und Multimedia-Programmierung 3
G highscore in *.dat speichern! Spiele- und Multimedia-Programmierung 8
H Bilder speichern 2 - Methode richten? Spiele- und Multimedia-Programmierung 2
H Bilder speichern Spiele- und Multimedia-Programmierung 3
S Inhalt von Canvas3D als jpg - File speichern Spiele- und Multimedia-Programmierung 2
K Java2d Bild als JPG oder so speichern Spiele- und Multimedia-Programmierung 10

Ähnliche Java Themen

Neue Themen


Oben