Avatar billede mummikiks Nybegynder
19. november 2005 - 00:43 Der er 10 kommentarer og
1 løsning

Serialisering af grafiske komponenter

Hej Experter

Jeg har lavet en grafisk GUI, hvorpå jeg kan trække nogle labels rund. De labels som kan trækkes rundt er implemteret i nogle objekter, som indeholde koordinatsæt etc. Mit mål er at kunne lukke programmet ned, hvorefter objekterne(labelene) vil have samme placering, når programmet igen startes.

For at opnå ovenstående mål, har jeg implemteret følgende klasse:
package GUI;
import java.io.*;
public class Serialisering {
public static void gem(Object obj, String filnavn) throws IOException
{
    FileOutputStream datastrøm = new FileOutputStream(filnavn);
    ObjectOutputStream objektstrøm = new ObjectOutputStream(datastrøm);
    objektstrøm.writeObject(obj);
    objektstrøm.close();
}

public static Object hent(String filnavn) throws Exception
{
    FileInputStream datastrøm = new FileInputStream(filnavn);
    ObjectInputStream objektstrøm = new ObjectInputStream(datastrøm);
    Object obj = objektstrøm.readObject();
    objektstrøm.close();
    return obj;
}
}


Jeg har så videre implementeret to funktioner i min applikation.


public static void load() throws Exception
    {
            try {
            ArrayList<Device> l;
            l = (ArrayList<Device>) Serialisering.hent("data.ser");
            System.out.println("Læst: "+l);
                               
           
        } catch (Exception e) {
            System.out.println("Ingen fil at loade");
            e.printStackTrace();
        }
                   
    }
   
    public static void save(Device device) throws Exception
    {
        try {
            l.add(device);
            System.out.println("Gem");
            Serialisering.gem(l,"data.ser");
           
        }
       
        catch (Exception e){
            l = new ArrayList();
            l.add(device);
            Serialisering.gem(l,"data.ser");
            System.out.println("Kunne ikke gemme");
        }
       
    }

Den gemmer findt objektet i en fil, og henter den også fint. Problemet ligger bare i at jeg igen skal have tilføjet objektet til min JPanel.

Nedenstående er output når filen loades:

Læst: [GUI.Device[,0,50,86x50,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=8388608,maximumSize=,minimumSize=,preferredSize=,defaultIcon=file:/C:/Dokumenter/Uni/Eclipse/Source_GUI/GUI/images/device.jpg,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=Device: 2,verticalAlignment=CENTER,verticalTextPosition=CENTER], GUI.Device[,0,50,86x50,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=8388608,maximumSize=,minimumSize=,preferredSize=,defaultIcon=file:/C:/Dokumenter/Uni/Eclipse/Source_GUI/GUI/images/device.jpg,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=Device: 2,verticalAlignment=CENTER,verticalTextPosition=CENTER]]


Mit spørgsmål går så på hvordan jeg kan placere ovenstående objekt på min GUI igen ved opstart.

Glæder mig til at høre fra jer...
Avatar billede mikkelbm Nybegynder
19. november 2005 - 10:56 #1
Du har jo faktisk lavet arbejdet :)

I stedet for at udskrive dine objekter tilføjer du dem vel bare til dit panel?

Nu ved jeg ikke lige hvilken type objekt dine devices er, men lad os sige de nedarver fra JPanel. Så løber du bare den arraylist igennem og tilføjer dem til et panel:

ArrayList<Device> l;
l = (ArrayList<Device>) Serialisering.hent("data.ser");
System.out.println("Læst: "+l);

for (Device device : l)
  ditPanel.add (device);


Ovenstående tilføjer dem direkte til panelet. Det kan være du har lavet en speciel add-metode, hvor du laver nogle flere ting, når et device bliver tilføjet, så kalder du bare den i stedet for.
Avatar billede mummikiks Nybegynder
20. november 2005 - 00:10 #2
Det virker faktisk ok med ovenstående kode.. Problemet er bare at at det objekt er et objekt jeg har defineret. Hele klassen som objektet er oprettet af kan ses i nedenstående tekst. Det er en klasse, som laver et objekt der kan flyttes rundt på et panel. Når man højreklikker kommer der nogle menuer.

Når jeg tilføjer objektet med ovenstående kode, kan jeg ikke længere trække det rundt eller højreklikke på det. Er der nogle ting som den ikke har gemt i mit array? og hvordan får jeg mulighed for at gemme alle detaljer. Jeg har nemlig brug for at vide hvilken fil den referere til (se nedenstående klasse) etc. Håber der nogle der kan hjælpe mig.


package GUI;
import java.awt.FlowLayout;
import java.awt.Font;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseListener;

import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.ButtonGroup;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.ImageIcon;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSeparator;
import java.util.Calendar;
import java.awt.*;
import java.io.File;
import java.io.Serializable;

public class Device extends JLabel implements ActionListener, ItemListener, Serializable{
public JPopupMenu popup;
public JMenuItem lightType;
public JMenuItem switchType;
public JMenuItem customType;
public JMenuItem heat;
public JMenuItem Add;
public JMenuItem Rename;
public JRadioButtonMenuItem Light;
public JMenuItem Remove;
public JMenuItem Lock;
public JMenuItem Unlock;
public JMenuItem StartTime;
public JMenuItem StopTime;
public JMenuItem Relations;
public JMenuItem Script;
public JMenuItem SetHeat;
public JSeparator Separator;
public JMenuItem Compile;
public JMenuItem Upload;
public JMenuItem save;    //Stub til save....skal fjernes
public JMenuItem load;    //Stub til load...skal fjernes
public JMenu type;
public File file;
public String startTime;
public String stopTime;
public String heatTemperature;
public int labelX;
public int labelY;

public int xforskydning;
public int yforskydning;

public int pressed_x;
public int pressed_y;

public int dragged_x;
public int dragged_y;

public int labelSizeX;
public int labelSizeY;
public Font labelFont;
public boolean moveable;
private java.awt.Point labelPos, mouseP ;
private double  oldPosX, oldPosY,
                mouseFirstX, mouseFirstY,
                mouseNowX, mouseNowY;
Gui owner;



    public Device(Gui owner, String text2){
          this.owner = owner;
        this.createPopupMenu();
   
        moveable = false;
          labelFont = new Font(null, Font.PLAIN, 22);
        labelX = 152;
        labelY = 84;
        labelSizeX = 100;
        labelSizeY = 100;
        heatTemperature = "20";
        stopTime = owner.clock();
        startTime = stopTime;
        setFont(getFont());
        this.setText(text2);
       
        this.setIcon(new ImageIcon(getClass().getClassLoader().getResource("GUI/images/device.jpg")));
       
        this.setLayout(new FlowLayout());
       
        this.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent evt) {
                  Rectangle r = getBounds();
                    labelX = (int)r.getX();
                    labelY = (int)r.getY();
            }
           
            public void mousePressed(MouseEvent evt) {
                pressed_x = evt.getX();
                pressed_y = evt.getY();

                 
                  xforskydning = (labelX - evt.getX());
                  yforskydning = (labelY - evt.getY());
            }
            public void mouseExited(MouseEvent evt) {}
            public void mouseEntered(MouseEvent evt) {}
            public void mouseClicked(MouseEvent evt) {}
        });

        this.addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseMoved(MouseEvent evt) {}
            public void mouseDragged(MouseEvent evt) {
                drag(evt);
            }
        });
     
    }
 

  public void createPopupMenu(){
     
     
      popup = new JPopupMenu();
       
      Add = new JMenuItem("Add");
      Add.addActionListener(this);
      popup.add(Add);
         
      type = new JMenu("Type");
      type.setMnemonic(KeyEvent.VK_S);

      lightType = new JRadioButtonMenuItem("Light");
      lightType.addActionListener(this);
      type.add(lightType);

      switchType = new JRadioButtonMenuItem("Switch");
      switchType.addActionListener(this);
      type.add(switchType);
     
      heat = new JRadioButtonMenuItem("Heat");
      heat.addActionListener(this);
      type.add(heat);
     
      customType = new JRadioButtonMenuItem("Custom");
      customType.addActionListener(this);
      type.add(customType);
     
      ButtonGroup group = new ButtonGroup();
      group.add(lightType);
      group.add(switchType);
      group.add(heat);
      group.add(customType);
      popup.add(type);     
     
      Rename = new JMenuItem("Rename");
      Rename.addActionListener(this);
      popup.add(Rename);
     
      Remove = new JMenuItem("Remove");
      Remove.addActionListener(this);
      popup.add(Remove);
     
      Lock = new JMenuItem("Lock");
      Lock.addActionListener(this);
      popup.add(Lock);
     
      Unlock = new JMenuItem("Unlock");
      Unlock.addActionListener(this);
      popup.add(Unlock);
     
      StartTime = new JMenuItem("Start Time..");
      StartTime.addActionListener(this);
      popup.add(StartTime);
     
      StopTime = new JMenuItem("Stop Time..");
      StopTime.addActionListener(this);
      popup.add(StopTime);
     
      SetHeat = new JMenuItem("Set Heat..");
      SetHeat.addActionListener(this);
      popup.add(SetHeat);
           
      Relations = new JMenuItem("Relations");
      Relations.addActionListener(this);
      popup.add(Relations);
     
      Script = new JMenuItem("Make Script..");
      Script.addActionListener(this);
      popup.add(Script);
     
      Separator = new JSeparator();
      popup.add(Separator);
     
      Compile = new JMenuItem("Compile");
      Compile.addActionListener(this);
      popup.add(Compile);
 
      Upload = new JMenuItem("Upload");
      Upload.addActionListener(this);
      popup.add(Upload);
     
      save = new JMenuItem("Save");
      save.addActionListener(this);
      popup.add(save);
     
      load = new JMenuItem("Load");
      load.addActionListener(this);
      popup.add(load);
     
      MouseListener popupListener = new PopupListener();
      this.addMouseListener(popupListener);
  }
 
  private void drag(MouseEvent evt){
        if (moveable == true) {
   
        mouseP = evt.getPoint();
        labelPos = getLocation();

        mouseNowX = mouseP.getX();
        mouseNowY = mouseP.getY();

        oldPosX = labelPos.getX();
        oldPosY = labelPos.getY();

        setLocation((int)((oldPosX + mouseNowX) - mouseFirstX - pressed_x),
            (int)((oldPosY + mouseNowY) - mouseFirstY - pressed_y) );
        }
       
        else
        {
           
        }
    }

public void itemStateChanged(ItemEvent arg0) {}


   
public void actionPerformed(ActionEvent e) {
    String command = e.getActionCommand();

    if (command.equals("Add")) {
          owner.addDeviceToHouse(this);
        this.validate();
       
          }
   
    else if (command.equals("Rename")) {
        String returnValue = JOptionPane.showInputDialog("Rename", this.getText());
        if (returnValue == null){
        this.setText(getText());
        }
                   
        else{
        this.setText(returnValue);
        }
         
        }
   
    else if (command.equals("Light")) {
        Relations.setVisible(false);
        Script.setVisible(false);
        StartTime.setVisible(false);
        StopTime.setVisible(false);
        SetHeat.setVisible(false);
        Compile.setVisible(true);
        Separator.setVisible(true);
        Upload.setVisible(true);
          this.setIcon(new ImageIcon(getClass().getClassLoader().getResource("GUI/images/light.jpg")));
        this.validate();
    }
   
    else if (command.equals("Switch")) {
        StartTime.setVisible(true);
        StopTime.setVisible(true);
        Relations.setVisible(true);
        Script.setVisible(false);
        SetHeat.setVisible(false);
        Compile.setVisible(true);
        Separator.setVisible(true);
        Upload.setVisible(true);
          this.setIcon(new ImageIcon(getClass().getClassLoader().getResource("GUI/images/switch.jpg")));
        this.validate();
    }
   
    else if (command.equals("Heat")) {
        StartTime.setVisible(true);
        StopTime.setVisible(true);
        Relations.setVisible(false);
        Script.setVisible(false);
        SetHeat.setVisible(true);
        Compile.setVisible(true);
        Separator.setVisible(true);
        Upload.setVisible(true);
          this.setIcon(new ImageIcon(getClass().getClassLoader().getResource("GUI/images/heat.jpg")));
        this.validate();
    }

    else if (command.equals("Custom")) {
        Relations.setVisible(false);
        StartTime.setVisible(false);
        StopTime.setVisible(false);
        Script.setVisible(true);
        SetHeat.setVisible(false);
        Compile.setVisible(true);
        Separator.setVisible(true);
        Upload.setVisible(true);
          this.setIcon(new ImageIcon(getClass().getClassLoader().getResource("GUI/images/device_online.jpg")));
        this.validate();
    }
   
    else if (command.equals("Remove")) {
        owner.removeDevice(this);
        this.validate();
    }
   
    else if (command.equals("Lock")) {
          moveable = false;
          this.Lock.setVisible(false);
          this.Unlock.setVisible(true);
    }
   
    else if (command.equals("Unlock")) {
          moveable = true;
          this.Lock.setVisible(true);
          this.Unlock.setVisible(false);
    }
   
    else if (command.equals("Start Time..")) {
        startTime = JOptionPane.showInputDialog("Start Time [dd:mm:yyyy:tt:mm]",startTime);
    }
   
    else if (command.equals("Stop Time..")) {
        stopTime = JOptionPane.showInputDialog("Stop Time [dd:mm:yyyy:tt:mm]",stopTime);
          }
   
    else if (command.equals("Set Heat..")) {
        heatTemperature = JOptionPane.showInputDialog("Set Heat in degrees", heatTemperature);
          }
   
    else if (command.equals("Relations")) {
        RelationTable relations = new RelationTable(this);
       
    }
   
    else if (command.equals("Make Script..")) {
        scriptEditor editor = new scriptEditor(this);
        editor.setVisible(true);
    }
   
    else if (command.equals("Compile")) {
        String msg = owner.compile(file);
        JOptionPane.showMessageDialog(this, "Device " + this.getText() + " returned with the error " + msg);
    }
   
    else if (command.equals("Upload")) {
        System.out.println("Upload mangler at blive implementeret");
    }
    else if (command.equals("Save")) {
        System.out.println("Save");
       
        try {
            owner.save(this);
        } catch (Exception e1) {
            System.out.println("Fejl isave fra direkte i devicen");
        }
                           
       
    }
    else if (command.equals("Load")) {
        System.out.println("Load");
       
        try {
            owner.load();
        } catch (Exception e1) {
            System.out.println("Fejl i load direkte i devicen");
        }
    }
   
}

class PopupListener extends MouseAdapter {
    public void mousePressed(final MouseEvent e) {
      maybeShowPopup(e);
    }

    public void mouseReleased(final MouseEvent e) {
      maybeShowPopup(e);
    }

    private void maybeShowPopup(final MouseEvent e) {
      if (e.isPopupTrigger()) {
        popup.show(e.getComponent(), e.getX(), e.getY());
      }
    }
}
}
Avatar billede mikkelbm Nybegynder
20. november 2005 - 17:31 #3
Jeg er lidt i tvivl om dine listeners bliver tilføjet rigtigt, når du indlæser et serialiseret objekt. Kan du prøve at lave en init metode, som du kalder på hvert objekt, når det loades?

Noget a la:

public void init ()
{
  // Tilmeld alle dine listeners her
}
Avatar billede mummikiks Nybegynder
20. november 2005 - 19:30 #4
Jeg har lige iplemented Serializable på den nederste popuklasse, hvilket medførte at jeg nuk na højreklikke og der kommer en menu op. Nu mangler jeg bare min mouselistner. Skal man have lavet den om således at den kommer på samme form som min popuplistener? Glæder mig til et godt forslag...
Avatar billede mummikiks Nybegynder
22. november 2005 - 08:48 #5
Ingen forslag til hvordan jeg kan få serialiseret min sidste listener? Kunne man egentlig ikke bare oprette et nyt objekt af device og lade attributerne fra serialiseringen nedarve fra Device objektet. Den har jo serialiseret alle de unikke ting for objektet
Avatar billede mikkelbm Nybegynder
22. november 2005 - 09:01 #6
Hvis den eneste information du gemmer mere eller mindre bare er koordinaterne, ville jeg lave et lille wrapperobjekt der gemte disse indstillinger. Det er sjældent det er nødvendigt at serialisere et grafisk objekt, for det bliver jo faktisk bare tegnet ud fra nogle oplysninger.

Så jo, hvis det er det du mener med at oprette et nyt objekt, så er det helt klart at foretrække.

Så kan du jo bare lave en constructor-overload som tager disse oplysninger med.
Avatar billede mummikiks Nybegynder
22. november 2005 - 11:15 #7
Hej Mikkel...kan du ikke give et lille eksempel til min loadfunktion.

ArrayList<Device> l;
l = (ArrayList<Device>) Serialisering.hent("data.ser");
System.out.println("Læst: "+l);

for (Device device : l)
  Device device = new device();
  ditPanel.add (device);

og så skal jeg hente ind og overrule min konstruktør..hvordan skriver jeg det?
Avatar billede mikkelbm Nybegynder
22. november 2005 - 11:29 #8
Det jeg ville gøre var at lave en wrapperklasse der indeholder de informationer du skal bruge for at lave en Device. Man kan sige at samme informationer skal kunne gemmes i en database eller en kommasepareret tekstfil for den sags skyld.

Noget a la:

public class DeviceWrapper
{
  private int width, height, x, y;
 
  public DeviceWrapper (int width, int height, int x, int y)
  {
      this.width = width;
      // osv...
  }

  // Her laver du så get og set metoder
}

I din Device ville jeg så lave en constructor der tager sådan en DeviceWrapper med og sætter position og størrelse på din Device.

Når du så vil gemme dine Devices gemmer du i virkeligheden DeviceWrappers og det er så også dem du henter ind igen. På den måde undgår du at skulle serialisere nogle grafiske objekter, som kan give nogle sjove resultater engang imellem.

Jeg har ikke tid til at lave et komplet eksempel nu, men skriv lige hvis ikke du forstår, så kigger jeg på det i aften.
Avatar billede mummikiks Nybegynder
22. november 2005 - 22:37 #9
Hmm kan godt se logikken i det, men der er jo mange ting der skal gemmes. Alle mine menuer..om de er "visible" eller ej. Så min Wrapper klasse, vil næsten blive lige så stor. Kan man ikk oprette et nyt objekt og tage min attributer fra serialiseringen og tilføje dem til objektet? Tror godt jeg kunne tænke mig et lille eksempel
Avatar billede mummikiks Nybegynder
24. november 2005 - 23:44 #10
Hej Mikkel

Jeg har lejet med tingene og det virker nu. JEg lavede som du beskrev i ovenstående indlæg og vil derfor gerne give dit pointene..Smid et svar
Avatar billede mikkelbm Nybegynder
25. november 2005 - 00:15 #11
Det var godt du fik det til at virke. Jeg har ikke haft tid til at kigge på det.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester