19. november 2005 - 00:43Der 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);
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.
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.
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();
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); }
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 }
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...
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
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.
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.
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
Det var godt du fik det til at virke. Jeg har ikke haft tid til at kigge på det.
Synes godt om
Ny brugerNybegynder
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.