2012-07-16 1 views
1

Ok mon problème est simple: je fais l'application de la peinture, et je voudrais offrir une sorte de fonctionnalité « défaire ». J'ai lu sur les gestionnaires d'annulation et ainsi de suite, mais cette approche semble être difficile à comprendre pour moi alors j'ai décidé de concevoir le mien. Mon idée est simple: puisque je dessine sur JPanel je vais juste sauvegarder son contenu actuel juste avant que toute opération de dessin soit faite. Et le bouton Annuler va juste restaurer le précédent.Saving JPanel comme l'image (non sous forme de fichier, mais comme une variable)

Le problème est: Je suis incapable de « restaurer » l'image enregistrée et placez-le sur le JPanel. Je suis tamponné depuis que j'ai déjà mis en place "sauvegarder" l'image actuelle sur disque dur et aussi "ouvrir" l'image arbitraire du disque dur. Les deux fonctionnent parfaitement bien.

Malheureusement essayant exactement de la même approche pour mon système « défaire » ne fonctionne pas.

Regardez le code: (pour simplifier, i manuellement "Enregistrer l'image actuelle -> à des fins de test)

public class PictureEdit { //class for saving the current JPanel drawing for undo 
    public BufferedImage saveBI; 
    public Graphics2D saveG2D; 
} 

public void actionPerformed(ActionEvent e) { //action for "UNDO" button, not working 
    //drawingField - instance of JPanel 
    //pe - instance of PictureEdit class 
    drawingField.setBufferedImg(drawingField.pe.saveBI); 
    drawingField.updateArea(drawingField.getBufferedImg());    
} 

public void actionPerformed(ActionEvent e) { //action for manual "save" (for undo) 
    drawingField.pe.saveBI=drawingField.getBufferedImg(); 
    drawingField.pe.saveG2D=(Graphics2D)drawingField.getBufferedImg().getGraphics(); 

} 

maintenant l'exemple de ma solution de travail, mais en rapport avec les fichiers de Woking sur le disque dur:

public void actionPerformed(ActionEvent e){ //Opening file from harddrive - works fine 
    JFileChooser jfc = new JFileChooser(); 
    int selection = jfc.showOpenDialog(PaintUndo.this); 
    if (selection == JFileChooser.APPROVE_OPTION){     
     try { 
      drawingField.setBufferedImg(ImageIO.read(jfc.getSelectedFile())); 
      drawingField.updateArea(drawingField.getBufferedImg()); 

     } catch (IOException ex) { 
      Logger.getLogger(PaintUndo.class.getName()).log(Level.SEVERE, null, ex); 
      JOptionPane.showMessageDialog(PaintUndo.this, "Could not open file"); 
     } 
    }     
} 


public void actionPerformed(ActionEvent e) { //Saving to harddrive - works fine 
    int n = JOptionPane.showConfirmDialog(PaintUndo.this, "Are you sure you want to save?", "Saving image...", JOptionPane.OK_CANCEL_OPTION); 
    if (n == JOptionPane.YES_OPTION){ 
     JFileChooser jfc = new JFileChooser(); 
     int nn = jfc.showSaveDialog(PaintUndo.this); 
     if (nn == JFileChooser.APPROVE_OPTION){      
      File saveFile = new File(jfc.getSelectedFile()+".bmp"); 
      try { 
       ImageIO.write(drawingField.getBufferedImg(), "bmp", saveFile); 
      } catch (IOException ex) { 
       Logger.getLogger(PaintUndo.class.getName()).log(Level.SEVERE, null, ex); 
       JOptionPane.showMessageDialog(PaintUndo.this, "Error while saving file"); 
      }      
     } 
    } 
} 

Juste au cas où quelqu'un est curieux: updateArea fonction (membre de la classe JPanel étendue qui représente mentionné drawingField):

public void updateArea(BufferedImage img){ //it is just resizing the current picture (if necessary) and then assigns the new Graphics. 
    area.height=img.getHeight(); 
    area.width=img.getWidth(); 
    this.setPreferredSize(area); 
    g2d = (Graphics2D)this.getGraphics(); 
} 

Fondamentalement, la procédure est exactement la même, et travailler avec des fichiers est ok alors je ne peux pas sauvegarder et de restaurer l'image quand je suis sur les variables d'exploitation ... Qu'est-ce qui pourrait être mal? des idées? Quand j'utilise Undo/boutons UndoSave, absolument rien ne change dans mes JPanel (drawingField)

Toute aide appréciée

+0

fonctionnalité Annuler dépend de la façon dont vous dessinez. Dessinez-vous des formes simples? Ou dessiner des pixels arbitraires? – Mohayemin

+2

1) Publier une [SSCCE] (http://sscce.org) au lieu de l'affichage des morceaux sur lesquels nous devons faire des suppositions sauvages 2) Alors que votre approche est originale, il sera tout à fait mémoire coûteuse et sur chaque action , vous devrez repeindre un nouveau BufferedImage qui n'est pas si bon marché. –

+0

Eh bien oui, je dessine des formes simples comme point, ligne, rectangle, ovale. En dehors de cela, je suis en train de tourner/retourner l'image. Concernant SSCCE: http://pastebin.com/0QY4uwHG (j'ai minimisé le code au strict minimum pour le rendre exécutable -> dessin exclu des ovales/rectangles et retournement/rotation). En ce qui concerne mon approche, eh bien, je ne pense pas que «UndoManager» est «moins cher» en termes de mémoire - mais je me trompe peut-être ici. Néanmoins, essayer de comprendre le non-gou- verneur me semble un peu douloureux, alors j'ai décidé d'y aller seul. UndoManager est-il si bon et optimisé pour qu'il soit plus rapide que la mienne? –

Répondre

3

Dans le code que vous avez montré, vous copiez votre référence à l'image, mais les deux références font encore en même objet image - si vous effectuez une action qui ne réaffecte pas la référence (=), il sera reflété dans les deux références! Afin de sauvegarder une ancienne version de l'image, vous devez copier l'objet réel, pas seulement la référence.

Je ne recommande en utilisant l'approche de Java de gestion undo mis en place, mais si vous voulez continuer avec votre propre, ce sont des méthodes que vous devriez regarder:

//BufferedImage image; 
Raster raster = image.getData(); // save 
image.setData(raster); // restore 
+0

ok cela fonctionne comme il se doit, mais je vais essayer d'implémenter UndoManager en quelque sorte. Merci pour votre aide. –

Questions connexes