Swing Validieren von deserializierten Objekten

predatorline

Mitglied
Hallo,
Ich habe ein kleines Programm geschrieben, indem ein Benutzer Linien zwischen zwei JLabels zeichnen kann.
Es besteht ebenfalls die Möglichkeit, die Linien zu speichern und zu laden.
Das Fenster ist veränderbar und die Zeichnungen werden dynamisch der Fenstergröße angepasst.
Nun mein Problem besteht beim laden der Linien. Durch die Deserializierung sind die geladenen JLabels(von denen ich Linien gezeichnet hatte) nicht mehr validiert.

Gibt es eine Möglichkeit die JLabels mit den geladenen JLabels zu ersetzen(validieren) , oder ist meine Umsetzung komplett falsch?

Eine andere Lösung hatte ich, indem ich die Linien als Image Speichere und wieder lade. Doch wenn ich das Image der Fenstergröße anpasse werden die Linien "unscharf". Diese Lösung habe ich im Code auskommentiert.

Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;

public class Window extends JFrame implements Serializable{

    private JPanel contentPane;
    private LinkedList<Shape> lines = new LinkedList<Shape>();
    private JLabel[] labelsArray = new JLabel[200];
    private JLabel drawFrom;
    private JLabel drawTo;
    private JLabel[] saveDrawingsFrom = new JLabel[200];
    private JLabel[] saveDrawingsTo = new JLabel[200];
    private int mouseClicksCounter = 0;
    private int drawLinesCounter = 0;
    private JPanel panelMid;
    private BufferedImage drawImage;
    private BufferedImage readImage = null;
   
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Window frame = new Window();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
       
    public Window() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 900, 500);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);
       
        //MouseListener fuer das Zeichnen von Linien
        MouseListener labelListener = new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                mouseClicksCounter ++;
                if(mouseClicksCounter == 1){
                    Border line = new LineBorder(Color.red, 4);
                    ((JLabel) e.getSource()).setBorder(line);
                    drawFrom = (JLabel) e.getSource();
                }
                if(mouseClicksCounter == 2){
                    drawTo = (JLabel) e.getSource();
                    mouseClicksCounter = 0;
                    if(drawFrom.equals(drawTo)){
                        //wenn wir denselben Label anklicken nichts machen..
                    }
                    else{
                        //Speichere die JLabels von denen wir eine Linien zeichen muessen
                        saveDrawingsFrom[drawLinesCounter] = drawFrom;
                        saveDrawingsTo[drawLinesCounter] = drawTo;
                        drawLinesCounter++;
                        panelMid.repaint();  //rufe paintComponent(..) von JPanel auf
                    }
                    drawFrom.setBorder(null);
                    drawTo.setBorder(null);
                }
            }   
        };
        //panelMid
        panelMid = new JPanel(new GridLayout(0,20 , 0, 0)){
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
               
                lines.clear();
               
                //Geladenes Image der JPanel größe anpassen
//                if(readImage != null){
//                    ImageFilter replicate = new ReplicateScaleFilter(getWidth(), getHeight());
//                    ImageProducer prod = new FilteredImageSource(readImage.getSource(),replicate);
//                    Image croppedImage = createImage(prod);
//                    g.drawImage(croppedImage, 0, 0, null);
//                }
                //Iteration durch alle JLabels von denen wir eine Linie zeichen
                for(int i = 0;i< drawLinesCounter ; i++){
                    Point fromPoint = new Point();
                    Point toPoint = new Point();
                    fromPoint.x = saveDrawingsFrom[i].getX() + saveDrawingsFrom[i].getWidth()/2;
                    fromPoint.y = saveDrawingsFrom[i].getY() + saveDrawingsFrom[i].getHeight()/2;
                    toPoint.x = saveDrawingsTo[i].getX() + saveDrawingsTo[i].getWidth()/2;
                    toPoint.y = saveDrawingsTo[i].getY() + saveDrawingsTo[i].getHeight()/2;
                    //Speichere die Linien in einer Liste
                    Shape drawShape = new Line2D.Double(fromPoint, toPoint);
                    lines.add(drawShape);
                }
                drawImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = drawImage.createGraphics();
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setPaint(Color.black);
                g2d.setStroke(new BasicStroke(3));
                for(Shape shape : lines){
                    g2d.draw(shape); //Zeiche alle Linien auf dem Image
                }
                g.drawImage(drawImage, 0, 0, null);
            }
        };
        contentPane.add(panelMid, BorderLayout.CENTER);
       
        JPanel panelSouth = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
        contentPane.add(panelSouth, BorderLayout.SOUTH);
        JButton btnSave = new JButton("Save");
        JButton btnLoad = new JButton("Load");
        ActionListener btnListener = new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                if(e.getSource().equals(btnSave)){
                    try {
                    FileOutputStream fos  = new FileOutputStream("saveDrawingsFrom.ser");
                    ObjectOutputStream oos = new ObjectOutputStream(fos);
                    oos.writeObject(saveDrawingsFrom);
                   
                    fos  = new FileOutputStream("saveDrawingsTo.ser");
                    oos = new ObjectOutputStream(fos);
                    oos.writeObject(saveDrawingsTo);
                   
                    fos  = new FileOutputStream("drawLinesCounter.ser");
                    oos = new ObjectOutputStream(fos);
                    oos.writeInt(drawLinesCounter);
   
                    oos.close();
                    fos.close();
                    //Speichere drawImage
//                    ImageIO.write(drawImage, "png", new File("save.png"));
                    JOptionPane.showMessageDialog(null, "Saved");
                   
                } catch(Exception ex) {
                    ex.printStackTrace();
                }
                }
                else{
                    try {
                        FileInputStream fos  = new FileInputStream("saveDrawingsFrom.ser");
                        ObjectInputStream ois = new ObjectInputStream(fos);
                        //Hier funktioniert keine validierung
                        saveDrawingsFrom = (JLabel[]) ois.readObject();
                       
                        fos  = new FileInputStream("saveDrawingsTo.ser");
                        ois = new ObjectInputStream(fos);
                        //Hier funktioniert keine validierung
                        saveDrawingsTo = (JLabel[]) ois.readObject();
                       
                        fos  = new FileInputStream("drawLinesCounter.ser");
                        ois = new ObjectInputStream(fos);
                        drawLinesCounter = ois.readInt();
       
                        ois.close();
                        fos.close();
                        //Lade Image
//                        readImage = ImageIO.read(new File("save.png"));
//                        drawLinesCounter=0;
                        JOptionPane.showMessageDialog(null, "Read");
                        drawLinesCounter=0;
                       
                        panelMid.repaint();
                    } catch(Exception ex) {
                        ex.printStackTrace();
                    }
                   
                }
            }
        };
        btnSave.addActionListener(btnListener);
        btnLoad.addActionListener(btnListener);
        panelSouth.add(btnLoad);
        panelSouth.add(btnSave);
       
        //Draw all Labels on the Middle Panel
        for(int i = 0;i< labelsArray.length;i++){
            labelsArray[i] = new JLabel("X");
            labelsArray[i].setFont(new Font("Tahoma", Font.BOLD, 15));
            labelsArray[i].setHorizontalAlignment(SwingConstants.CENTER);
            labelsArray[i].addMouseListener(labelListener);
            panelMid.add(labelsArray[i]);
        }
    }
}
 
K

kneitzel

Gast
Also das Kernproblem ist aus meiner Sicht, dass Du GUI Elemente serialisierst. Dies ist so zumindest unüblich. Normalerweise serialisiert man lediglich die Daten, die durch die GUI angezeigt werden.

Somit ist oft eine Trennung zwischen den eigentlichen Daten und der GUI angebracht. Das hat dann auch den Vorteil, dass man die ganze Business Logik in Unit-Tests prüfen kann.

Und beim Speichern wäre ich auch etwas vorsichtiger mit der Nutzung der Object Streams. Die benötigen halt genau die Klasse, die Du da einmal verwendet hast. Updates zu der Klasse machen das Laden ggf. deutlich schwerer. Da gibt es zwar auch einige Ansätze, aber ich habe die Erfahrung gemacht, dass z.B. die Nutzung von XML Daten deutlich einfacher ist.

Konrad
 

predatorline

Mitglied
Also das Kernproblem ist aus meiner Sicht, dass Du GUI Elemente serialisierst. Dies ist so zumindest unüblich. Normalerweise serialisiert man lediglich die Daten, die durch die GUI angezeigt werden.
Konrad
Das mit dem serializieren von GUI Elementen ist mir bewusst, wodurch ich Anfangs mit dem einfachen speichern von Images probiert hatte. Doch das "resizen" des Bildes liefert "unscharfe" Ergebnisse, wie bereits erwähnt. Auf andere Lösungen bin ich leider nicht gestoßen. Das Serializieren war nur eine "Versuchsoption" gewesen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D JavaFX Textfeld Eingabe validieren AWT, Swing, JavaFX & SWT 5
M Swing JTextField live validieren und Rahmenfarbe ändern AWT, Swing, JavaFX & SWT 3
D SWT StyledText-Feld Validieren??? AWT, Swing, JavaFX & SWT 3
Encera ArrayList mit eigenen Objekten in JavaFX sortieren und ausgeben AWT, Swing, JavaFX & SWT 50
ExceptionOfExpectation MouseListener-Objekte zu den Graphics-Objekten einfügen AWT, Swing, JavaFX & SWT 3
W Clear Canvas und anschließendes neues Erstellen von Objekten auf Canvas aus ArrayList AWT, Swing, JavaFX & SWT 4
J Drag and Drop von eigenen Objekten AWT, Swing, JavaFX & SWT 3
I Umgang mit vielen Objekten AWT, Swing, JavaFX & SWT 3
J LayoutManager GridBagLayout, probleme mit Anordnung von Objekten AWT, Swing, JavaFX & SWT 6
perlenfischer1984 JavaFX : JTreeView mit verschieden Objekten AWT, Swing, JavaFX & SWT 0
M Java FX Dreidimensionale Anordnung von Objekten AWT, Swing, JavaFX & SWT 4
P Vorteile von Tooltip nutzen (wird über allen anderen Objekten angezeigt) AWT, Swing, JavaFX & SWT 3
I Paint-Methode von nicht statischen Objekten aufrufen AWT, Swing, JavaFX & SWT 3
G JavaFX Binding von Objekten AWT, Swing, JavaFX & SWT 4
P Swing JList mit Objekten - Name anzeigen AWT, Swing, JavaFX & SWT 5
J Mit mehreren in Objekten in JFrame printen? AWT, Swing, JavaFX & SWT 8
D animierte kameraansicht zwischen gezeichneten objekten AWT, Swing, JavaFX & SWT 4
1 Liste mit Objekten Füllen AWT, Swing, JavaFX & SWT 7
M JList mit 2-zeiligen Objekten füllen AWT, Swing, JavaFX & SWT 7
M Verschwinden von gezeichneten Objekten nach Fensterverkleinerung AWT, Swing, JavaFX & SWT 3
B Swing Laden von serialisierten Objekten (invalid type code AC)) AWT, Swing, JavaFX & SWT 3
C Swing Drag and Drop mit Objekten in einem Fenster. AWT, Swing, JavaFX & SWT 9
M PropertyChangeListener - JTable bei neuen Objekten updaten? AWT, Swing, JavaFX & SWT 3
M JTable Sortierung - -zeilenweise mit Objekten verknüpfen AWT, Swing, JavaFX & SWT 4
X JTable mit verschiedenen Objekten füllen AWT, Swing, JavaFX & SWT 14
S AWT Pong - Probleme mit übergreifenden Objekten && Graphics2D AWT, Swing, JavaFX & SWT 3
S Spielfeld mit unförmigen Objekten anklickbar machen? AWT, Swing, JavaFX & SWT 4
T Sichtbarmachen von Objekten auf mehreren JPanels AWT, Swing, JavaFX & SWT 2
W setEnabled in Container Objekten (JScrollPane) AWT, Swing, JavaFX & SWT 5
Q Dynamische Zahl und Positionierung von Objekten AWT, Swing, JavaFX & SWT 5
L JPanel mit Objekten selektieren wie unter Windows / Ubuntu AWT, Swing, JavaFX & SWT 4
T Swing KeyListener mit mehreren Objekten AWT, Swing, JavaFX & SWT 2
P JTable:Sortierung nach der Zeit/Spalte mit Calendar-Objekten AWT, Swing, JavaFX & SWT 2
M Probleme beim Hinzufügen von Objekten zu getContentPane() AWT, Swing, JavaFX & SWT 2
T Drag&Drop mit Objekten! Grundsätzlich. AWT, Swing, JavaFX & SWT 3
C Positionieren von Objekten AWT, Swing, JavaFX & SWT 11
T Gleichzeitiges Steuern von 2 Objekten über Tastatur AWT, Swing, JavaFX & SWT 8
I Größe von Swing-Objekten ändern AWT, Swing, JavaFX & SWT 13
A Attribute von Objekten in JTable-Zeilen anzeigen AWT, Swing, JavaFX & SWT 2
S JTree mit eigenen Objekten füllen AWT, Swing, JavaFX & SWT 4
S Problemen mit Canvas-Objekten im GridLayout AWT, Swing, JavaFX & SWT 8
N JPanels von Objekten AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben