Ich traf letztens auf einen sehr spezielles Java Problem, bei dem es dann zu Problemen bei der Serialisierung von Objekten kommt.
Ziel sollte es sein eine innere Klasse zu serialisieren während die äußere Klasse eine grafische Oberfläche und mehrere Ereignishandler beinhaltet und den JFileChooser verwendet. Dies schlägt fehl.

Hier der stark vereinfachte, aber trotzdem komplett lauffähige Aufbau eines solchen fehlerhaften Programms: (Video unten)

import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import javax.swing.JFileChooser;
import javax.swing.JFrame;

public class GraphEditorGerüst extends JFrame implements MouseListener {
	
	ArrayList<Kreis> kreise = new ArrayList<Kreis>(); // globale Kreisvariable

	public GraphEditorGerüst(){
		super("GraphEditor");
		setSize(150, 100);
		addMouseListener(this);
	}
	
	public class Kreis implements Serializable {
		// innere, zu serialisierende, Klasse
		public static final long serialVersionUID = 3L;
		public int x, y, dx, dy, id, idcounter = 0;
		public Color c = Color.BLACK;	
		public Kreis(int x, int y, int dx, int dy, Color c) {
			this.x = x;
			this.y = y;
			this.dx = dx;
			this.dy = dy;
			this.c = c;
			this.id = ++idcounter;
		}
	}
	
	// Ereignishandler mouseClicked
	public void mouseClicked(MouseEvent me){
		// ein Dummykreis erstellen, der nachher geschrieben wird
		kreise.add(new Kreis(0,0,0,0,Color.BLACK));
		// neues JFileChooser Objekt
		JFileChooser fc = new JFileChooser();
		// JFileChooser Dialog anzeigen und Rückgabewert speichern
		int fcreturn = fc.showDialog(this, "Speichern");
		// wenn auf "Speichern" geklickt wurde
		if (fcreturn == JFileChooser.APPROVE_OPTION) {
			// ausgewählte Datei in ein File Objekt speichern
			File savefile = fc.getSelectedFile();
			try {
				FileOutputStream fos = new FileOutputStream(savefile);
				ObjectOutputStream oos = new ObjectOutputStream(fos);
				for (Kreis k : kreise) {
					// hier tritt der Fehler auf
					oos.writeObject(k);
				}
				oos.close();
				fos.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			catch (IOException e) {
				e.printStackTrace();
			}	
		}
	}	
	
	public static void main(String[] args){
		// Erzeugen eines Objektes von GraphEditorGerüst
		GraphEditorGerüst test = new GraphEditorGerüst();
		test.setVisible(true);
	}


	@Override
	public void mouseEntered(MouseEvent e) {}
	@Override
	public void mouseExited(MouseEvent e) {}
	@Override
	public void mousePressed(MouseEvent e) {}
	@Override
	public void mouseReleased(MouseEvent e) {}

}

Sieht an sich eigentlich unproblematisch aus.
Die innere Klasse soll serialisiert werden, hat das Interface implementiert und nutzt definitiv nur serialisierbare Datentypen und Elemente. Die äußere Klasse kümmert sich um die GUI und einige Ereignishandler. Einer dieser Handler enthält den JFileChooser zum Auswählen einer Datei, in die ein ObjectOutputStream nun die serialisierte innere Klasse schreiben soll. Es kommt beim Speichern, genauer gesagt bei der Ausführung von oos.writeObject, zu folgendem Fehler:

java.io.NotSerializableException: 
javax.swing.plaf.metal.MetalFileChooserUI

alertnativ auch auf

javax.swing.plaf.basic.BasicFileChooserUI$AcceptAllFileFilter

mit folgender Stack Trace:

Code anzeigenDen Code könnt ihr bequem mit den Links/Rechts Pfeiltasten horizontal bewegen.

java.io.NotSerializableException: javax.swing.plaf.metal.MetalFileChooserUI
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeObject(Unknown Source)
	at javax.swing.event.EventListenerList.writeObject(Unknown Source)
	at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
	at java.io.ObjectOutputStream.defaultWriteObject(Unknown Source)
	at javax.swing.JComponent.writeObject(Unknown Source)
	at sun.reflect.GeneratedMethodAccessor10.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
	at java.io.ObjectOutputStream.defaultWriteObject(Unknown Source)
	at java.awt.Window.writeObject(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeObject(Unknown Source)
	at java.awt.Window.writeObject(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeObject(Unknown Source)
	at java.util.ArrayList.writeObject(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
	at java.io.ObjectOutputStream.writeObject(Unknown Source)
	at GraphEditor.actionPerformed(GraphEditor.java:191)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.AbstractButton.doClick(Unknown Source)
	at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
	at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.awt.EventQueue.access$000(Unknown Source)
	at java.awt.EventQueue$3.run(Unknown Source)
	at java.awt.EventQueue$3.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
	at java.awt.EventQueue$4.run(Unknown Source)
	at java.awt.EventQueue$4.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Video des Beispielcodes oben:

Hier die Problemanalyse:

Das Serialisieren von nicht-statischen inneren Klassen, deren äußere Klasse Ereignisempfänger ist, ist unter gewissen Umständen nicht möglich. Es wird versucht nicht nur die innere, sondern auch die äußere Klasse zu serialisieren, da die innere Klasse nicht-statisch ist. Wenn diese äußere Klasse ereignisverarbeitende Methoden verwendet, die nicht serialisierbare Objekte (z.B. JFileChooser in ActionPerformed()) enthält, so schlägt die Serialisierung der äußeren Klasse mit der Fehlermeldung „java.io.NotSerializableException“ auf dem nicht serialisierbaren Objekt „javax.swing.plaf.metal.MetalFileChooserUI“ (im Falle des JFileChooser) fehl.

Es ergeben sich 5 Lösungsmöglichkeiten:
1.) Die innere Klasse mit dem static Modifier versehen.
2.) Kein JFileChooser verwenden.
3.) Keine ereignisverarbeitenden Methoden in der Klasse verwenden, die das zu serialisierende Objekt – oder eine innere Klasse mit diesem Objekt – enthält.
4.) Auslagern der inneren, zu serialisierenden, Klasse.
5.) Auslagern aller Ereignisempfänger und Auslagern der inneren, zu serialisierenden, Klasse.

Die erste Lösung geht wohl am schnellsten und hilft in den meisten Fällen ohne weitere Probleme zu generieren. Die zwei nächsten Lösungen schränken die Möglichkeiten ein. Die vierte Lösung ist am einfachsten umzusetzen; nur die innere, zu serialisierende, Klasse wird in eine eigene Class Datei ausgelagert und entsprechend verwendet. Die fünfte Lösung lagert zusätzlich noch alle Ereignishandler aus (was sowieso nicht schlecht ist, da es zur logischen Trennung und Übersichtlichkeit beiträgt), kann aber, je nach Größe des Projekts, relativ aufwändig werden.

Hier der Code eines komplett lauffähigen Programms, bei der die zu serialisierende Klasse ausgelagert wurde:

GraphEditor.java:

Code anzeigenDen Code könnt ihr bequem mit den Links/Rechts Pfeiltasten horizontal bewegen.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class GraphEditor extends JFrame implements MouseListener, MouseMotionListener, ActionListener {
	
	//Globale Variablen
	JTextField txt = new JTextField(10);
	JPanel panel1 = new JPanel();
	
	//Globale Variablen
	Kreis gezogenerKreis = null; //Kreis-Objekt zum Zwischenspeichern des bewegten Kreises
	
	//Kreisdurschnitt
	final int dX = 16, dY = 16;
	
	//Erstkonfiguration und Koordinatenkorrekturen
	int korrekturX = 0, korrekturY = 0;
	int korrekturX1 = 0, korrekturY1 = 0, korrekturX2 = 0, korrekturY2 = 0, configclickcounter = 1;
	boolean configured = false;
	
	//ArrayList zum Aufnehmen der Kreis-Objekte
	ArrayList<Kreis> kreise = new ArrayList<Kreis>(); 

	//Konstruktor der Klasse GraphEditor
	public GraphEditor(){
		
		//Aufruf des Konstruktors der Oberklasse
		super("GraphEditor");
		
		//Schließen des Fensters 
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		
		//Menüleiste
		JMenuBar mbar = new JMenuBar();
		this.setJMenuBar(mbar);
		
		//Menü
		JMenu mGraph = new JMenu("Graph");
		JMenu mVertex = new JMenu("Vertex");
		
		//Menüelemente
		JMenuItem mGraphOpen = new JMenuItem("open");
		JMenuItem mGraphNew = new JMenuItem("new");
		JMenuItem mGraphSave = new JMenuItem("save");
		JMenuItem mVertexInsert	= new JMenuItem("insert");
		JMenuItem mVertexMove = new JMenuItem("move");
		JMenuItem mVertexDelete = new JMenuItem("delete");
		JMenuItem mVertexNone = new JMenuItem("none");
		
		//Hinzufügen der Elemente zur Menüleiste
		mGraph.add(mGraphNew);
		mGraph.add(mGraphOpen);
		mGraph.add(mGraphSave);
		mVertex.add(mVertexInsert);
		mVertex.add(mVertexMove);
		mVertex.add(mVertexDelete);
		mVertex.add(mVertexNone);		
		mbar.add(mGraph);
		mbar.add(mVertex);
		
		//Haupt-Panel
		this.setLayout(new BorderLayout());
		panel1.setBackground(Color.white);
		this.add(panel1, BorderLayout.CENTER);
		panel1.addMouseListener(this);
		panel1.addMouseMotionListener(this);
		
		//unteres Panel für Label und Textfeld
		JPanel panel2 = new JPanel();
		this.add(panel2, BorderLayout.SOUTH);
		
		//Label
		JLabel label = new JLabel("Selected Action", JLabel.RIGHT);
		panel2.setLayout(new GridLayout(1,2,5,0));
		panel2.add(label);
		
		//Panel für Textfeld
		JPanel panel3 = new JPanel();
		panel3.setLayout(new FlowLayout(3));
		panel2.add(panel3);
		
		//Textfeld
		txt.setText("none");
		txt.setDisabledTextColor(Color.black);
		txt.setEnabled(false);
		panel3.add(txt);
		
		//ActionListener
		mVertex.addActionListener(this); // vertex:
		mVertexInsert.addActionListener(this);
		mVertexDelete.addActionListener(this);
		mVertexMove.addActionListener(this);
		mVertexNone.addActionListener(this);
		mGraph.addActionListener(this); // graph:
		mGraphNew.addActionListener(this);
		mGraphOpen.addActionListener(this);
		mGraphSave.addActionListener(this);
		
		//ActionCommands
		mVertex.setActionCommand("vertex"); // vertex:
		mVertexInsert.setActionCommand("insert");
		mVertexDelete.setActionCommand("delete");
		mVertexMove.setActionCommand("move");
		mVertexNone.setActionCommand("none");
		mGraph.setActionCommand("graph"); // graph:
		mGraphNew.setActionCommand("new");
		mGraphOpen.setActionCommand("open");
		mGraphSave.setActionCommand("save");
	}
	
	//Überschriebene Paint-Methode zum Zeichnen der Kreise
	public void paint(Graphics g) {
		super.paint(g);
		for (Kreis k: kreise) {
			g.setColor(k.c);
			g.fillOval(k.x - k.dx/2 + korrekturX, k.y - k.dy/2 + korrekturY, k.dx, k.dy);
		}
	}
	
	//ActionEvent
	public void actionPerformed(ActionEvent ae){
		//Zwischenspeichern
		String action = ae.getActionCommand();
		
		//werden unabhängig von der Erstkonfiguration immer ausgeführt
		if(action == "delete"){
			txt.setText("Vertex: delete");
		}
		if(action == "move"){
			txt.setText("Vertex: move");
		}
		if(action == "none"){
			txt.setText("none");
		}
		//wenn insert zum ersten Mal ausgewählt wird: Infofenster anzeigen
		if (configured == false && action == "insert") {
			int wahl = JOptionPane.showConfirmDialog(this, "" +
					"Bei der ersten Verwendung des Programms muss eine Konfiguration erfolgen. \n" +
					"Bitte klicken Sie an eine Stelle mittig im Zeichenbereich und danach\n " +
					"exakt in den weißen Punkt in der Mitte des gezeichneten Kreises!", 
					"Konfiguration nötig!", JOptionPane.OK_CANCEL_OPTION);
			if (wahl == JOptionPane.OK_OPTION) {
				txt.setText("Vertex: insert");
			}
		}
		//wenn Erstkonfiguration schon abgeschlossen ist
		else if (configured == true) {
			if(action == "insert"){
				txt.setText("Vertex: insert");	
			}
		}
		
		//Löschen der Kreise aus der Liste 
		if(action == "new") {
			kreise.clear();
			repaint();
		}
		
		//Speichern der gezeichneten Kreise
		if(action == "save") {
			JFileChooser fc = new JFileChooser();
			int fcreturn = fc.showDialog(this, "Speichern");
			if (fcreturn == JFileChooser.APPROVE_OPTION) {
	            File savefile = fc.getSelectedFile();
				try {
					FileOutputStream fos = new FileOutputStream(savefile);
					ObjectOutputStream oos = new ObjectOutputStream(fos);
					for (Kreis k : kreise) {
						oos.writeObject(k);
					}
					oos.close();
					fos.close();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}
				catch (IOException e) {
					e.printStackTrace();
				}	
			}
		}
		
		//Öffnen einer bereits gespeicherten Datei mit Punkten
		if(action == "open") {
			kreise.clear();
			JFileChooser fc = new JFileChooser();
			int fcreturn = fc.showDialog(this, "Öffnen");
			if (fcreturn == JFileChooser.APPROVE_OPTION) {
	            File openfile = fc.getSelectedFile();
	            fc = null;
	            FileInputStream fis;
	            ObjectInputStream ois;
				try {
					fis = new FileInputStream(openfile);
					ois = new ObjectInputStream(fis);
					try {
						while (true) {
						kreise.add((Kreis) ois.readObject());
						repaint();
						}
					}
					catch (EOFException e) {
						System.out.println("Dateiende erreicht");
						ois.close();
						fis.close();
					}
				}
				catch (IOException e) {
					e.printStackTrace();
				} 
				catch (ClassNotFoundException e) {
					e.printStackTrace();
				}	
	        }
		}
		repaint();
	}
	
	//MouseEvents
	public void mouseClicked(MouseEvent me){
		repaint();
		int cursorX = me.getX();
		int cursorY = me.getY();
		//Erstkonfiguration der Koordinatenkorrektur starten, wenn noch nicht erfolgt
		if (configured == false) {
			//erster Klick der Erstkonfiguration, Textfeld mit "Vertex: insert" nur, wenn der Benutzer im Dialog "OK" geklickt hat
			if (configclickcounter == 1 && txt.getText().equals("Vertex: insert")) {
				//erstes Koordinatenpaar lesen
				korrekturX1 = me.getX();
				korrekturY1 = me.getY();
				configclickcounter++;
				/* Kreis mit den unkonfigurierten Standardkoordinaten zeichnen; 				
				 * dieser wird links oberhalb des Klickpunktes erscheinen, je nach Betriebssystem(/-version)
				 * und Windows-Design unterschiedlich!
				 * Ein kleiner weißer Kreis symbolisiert die Mitte, die angeklickt werden muss. */		 
				kreise.add(new Kreis(cursorX, cursorY, dX, dY));
				kreise.add(new Kreis(cursorX, cursorY, 2, 2, Color.WHITE));
			//zweiter Klick der Erstkonfiguration
			} else if (configclickcounter == 2 && txt.getText().equals("Vertex: insert")) {
				//Konfigurationskreise löschen
				kreise.clear();
				repaint();
				//zweites Koordinatenpaar lesen
				korrekturX2 = me.getX();
				korrekturY2 = me.getY();
				//Korrekturen errechnen
				korrekturX = korrekturX1 - korrekturX2;
				korrekturY = korrekturY1 - korrekturY2;
				//Konfiguration beenden, Infodialog anzeigen
				configured = true;
				JOptionPane.showConfirmDialog(this, "" +
						"Die Konfiguration ist abgeschlossen. \n" +
						"Koordinatenkorrektur für X: " + korrekturX + " | Y: " + korrekturY, 
						"Konfiguration abgschlossen!", JOptionPane.OK_CANCEL_OPTION);
			}
		}		
		//Erstkonfiguration beendet
		else if (configured == true){
			if(txt.getText().equals("Vertex: insert")){
				kreise.add(new Kreis(cursorX, cursorY, dX, dY));
			}
		}
		if(txt.getText().equals("Vertex: delete")){
			for(Kreis k : kreise){
				if(cursorX <= (k.x + dX/2.0) && cursorX >= (k.x - dX/2.0) && cursorY <= (k.y + dY/2.0) && cursorY >= (k.y - dY/2.0)){
					kreise.remove(k);
					break;
				} 
			}
		}
	}	
	
	public void mousePressed(MouseEvent me){
		if(txt.getText().equals("Vertex: move")){
			int cursorX = me.getX();
			int cursorY = me.getY();
			for(Kreis k : kreise){
				if(cursorX <= (k.x + dX/2.0) && cursorX >= (k.x - dX/2.0) && cursorY <= (k.y + dY/2.0) && cursorY >= (k.y - dY/2.0)){
					gezogenerKreis = k;					
				} 
			}
		}
	}
	public void mouseEntered(MouseEvent arg0){}
	public void mouseExited(MouseEvent arg0){}
	public void mouseReleased(MouseEvent arg0){
		gezogenerKreis = null;
	}

	//MouseMotionEvents
	public void mouseDragged(MouseEvent me) {
		if(txt.getText().equals("Vertex: move")){
			if(gezogenerKreis != null) {	
				gezogenerKreis.x = me.getX();
				gezogenerKreis.y = me.getY();	
				repaint();
			}
		}
	}
	public void mouseMoved(MouseEvent e){}
	
	//Main-Methode		
	public static void main(String[] args){
		
		//GraphEditor-Objekt
		GraphEditor ui = new GraphEditor();
		
		//Setzen der Größe und Sichtbarkeit des GraphEditor-Objekts
		ui.setSize(550, 350);
		ui.setVisible(true);
		
	}

}

Kreis.java:

Code anzeigenDen Code könnt ihr bequem mit den Links/Rechts Pfeiltasten horizontal bewegen.

import java.awt.Color;
import java.io.Serializable;

public class Kreis implements Serializable {
	//Innere Kreis-Klasse
	public static final long serialVersionUID = 3L;
	public int x, y, dx, dy, id;
	public Color c = Color.BLACK;	
	int counter = 0;
	// 2 verschieden überladene Konstruktoren ermöglichen die freie Farbwahl für jeden einzelnen Kreis
	public Kreis(int x, int y, int dx, int dy, Color c) {
		this.x = x;
		this.y = y;
		this.dx = dx;
		this.dy = dy;
		this.c = c;
		this.id = ++counter;
	}
	public Kreis(int x, int y, int dx, int dy) {
		this.x = x;
		this.y = y;
		this.dx = dx;
		this.dy = dy;
	}
	@Override
	public String toString() {
		return "x:"+ x + " y:" + y + " dx:" + dx + " dy:" + dy + " color:" + c.toString()+ "\n";

	}
}

Ich bin ein Freund von persönlichen Fotos auf gedruckten Leinwänden. Demnach horchte ich immer auf, wenn es Gutscheine für Leinwände gibt. Picanova, PosterXXL, meinfoto, alle vom selben Schlag, machen das mittlerweile sehr professionell und zuverlässig; mindestens 10 Leinwände habe ich dort schon gekauft.


Nun also von mir der Tipp: 29,90€ bezahlt, Leinwände im Wert von 100€ bestellt!

Zum Gutschein


Bei einem Format von 40x30cm könnt ihr da 4 Leinwände kaufen; das sind also nicht einmal 7,50€ pro Leinwand!
Die Leinwände werden bei Picanova mit lösemittelfreien Farben auf die Holzrahmen gespannt und werden somit fertig verschickt; nur noch das Aufhängen kostet Arbeit.

Viel Spaß damit.

Kurz zur Einleitung, weil das mein erster Post zu diesem Thema ist:
Monkeyrunner ist ein Tool des Android SDK, welches als Schnittstelle zu dem angeschlossenen Android Smartphone fungiert. Es bietet eine, mit Python Scripten angesprochene, Fernsteuerung des Geräts mit einigen Features. So lassen sich lange Interaktionsfolgen automatisiert verscripten und „unbemannt“ ausführen.

Also, Screen Lock & Unlock mit Monkeyrunner:

# simulierter Druck auf den Power Knopf -> Screen aus
device.press("POWER", MonkeyDevice.DOWN_AND_UP)

# eigene Methode zum Aufwecken des Bildschirms
# nochmal ein Druck auf POWER funktioniert nicht
device.wake()

# 1 Sekunde warten
MonkeyRunner.sleep(1)

# Ziehen des Entsperr-Rings (vom unteren Rand in die Mitte (HTC One X))
device.drag((354, 1191), (324, 525), 1, 10)

# entsperrt!

Der Sperrbildschirm ist in diesem Beispiel nur mit dem üblichen Entsperr-Ring von HTC versehen, kein Muster oder PIN.
Die einzige Hürde ist also das Festlegen der Koordinaten beim Entsperren. Dazu später noch ein weiteres Tutorial.

English Version

A short introduction first because this is the first post on this topic:

Monkeyrunner is a tool which provides an interface between your computer and the connected Android smartphone. It is controlled by Python scripts and is capable of serving as a Android device remote control with functions like sending various inputs, running apps, taking and saving screenshots from the device. This way you can automatize complex interactions and inputs and run them unattended.

How to lock & unlock the Android device with Monkeyrunner:

# simulate a POWER button press -> turn off the screen
device.press("POWER", MonkeyDevice.DOWN_AND_UP)

# monkeyrunner method to unlock the screen
# POWER button press doesn't work to turn on
device.wake()

# wait a second
MonkeyRunner.sleep(1)

# drag the unlock-ring (from bottom to center (HTC One X))
device.drag((354, 1191), (324, 525), 1, 10)

# unlocked!

This example shows that the lock screen is just secured by the HTC unlock-ring, which must simply be dragged from the bottom to the center. No lock pattern or PIN here (which is much easier to solve with monkeyrunner).
So there’s just one small thing to consider: defining the coordinates of your unlock … thingy’s start end end position. Doing so depends on the device and Android version your using. There will be a tutorial here about that very soon.

via

Der Ordner C:\Windows\Installer beinhaltet oftmals mehrere Gigabyte an Daten verteilt in vielen kryptischen Ordnern und viele .msi/.msp Dateien.
Es macht den Eindruck als könnte man den Ordner löschen, als seien das nur überflüssige Überbleibsel von ehemaligen Installationen; „weg damit“, oder so. So falsch ist das nicht, der Ordner enthält tatsächlich Daten von ehemaligen Installationen, diese sind aber nicht überflüssig sondern werden jedes Mal benötigt, wenn man installierte Programme ändern, reparieren oder deinstallieren möchte.
Der Ordner sollte nicht gelöscht werden, das wird so ziemlich überall im Netz empfohlen.
Das habe ich natürlich erst zu spät recherchiert, der Ordner ist auf meinem PC weg.

Es heißt, dass nach dem Löschen des Programms die meisten installierten Anwendungen nicht mehr verändert, repariert oder deinstalliert werden können.
Ich selber stelle seit dem vorerst nur fest, dass dadurch viele Icons verschwunden sind. Startmenü, Softwareauflistung, Explorer, überall fehlen die richtigen Icons.

So richtig tragisch ist das erstmal nicht, schön ist es aber auch nicht.
Testweise habe ich 3 Deinstallationen von Programmen, deren Icon in der Softwareauflistung gelöscht wurde, vorgenommen. Alle Deinstallationen verliefen ohne Probleme. Größere Schäden am System konnte ich glücklicherweise noch nicht ausmachen.
Ich empfehle die Löschung trotzdem nicht. 😉

Ich brauche die UNIX Shell auf meinem Windows System. Und es war erstaunlich einfach.

Cygwin heißt die sich praktisch von selbst installierende Software, die das komplette Linux Look & Feel mitbringt. Zusätzlich ermöglicht es der Installer auf einfachsten Wege hunderte Linux Pakete gleich mitzuinstallieren.

Nach der Installation liegt auf dem Desktop (wenn nicht während der Installation deaktiviert) eine Verknüpfung zum Cygwin Terminal, welcher einer Linux Umgebung nachempfunden ist. Von dort kann man wie auch im Linux Terminal Befehle absetzen, Programme starten, ausführen usw.

Es wird auch direkt eine Linux-ähnliche Ordnerstruktur erstellt und eingegebene Pfade entsprachend übersetzt, sodass auch das Dateisystem Linux-like anmutet:

MS-DOS style path detected: p:/Cygwin/home/Hannes/prog.sh
Preferred POSIX equivalent is: /home/Hannes/prog.sh

Die Ausgaben des Cygwin Terminals entsprechend nicht 1:1 den Ausgaben von Linux Distributionen, man sollte den dort entwickelten Code also nicht ohne Weiteres in Linuxumgebungen übernehmen.
Aber für erste Tests (und die 2 Linux Bash Vorlesungen meines Studiums) reicht es.

[Video zur Bloggerchallenge – wird von Adblockern geblockt! Also bitte kurz deaktivieren.]


[Video zur Bloggerchallenge – wird von Adblockern geblockt! Also bitte kurz deaktivieren.]

Der alljährliche nationale IT-Gipfel steht vor der Tür. Seit 2006 findet jedes Jahr dieser IT-Gipfel statt, bei dem sich Politiker und Wirtschaftsvertreter zusammensetzen um Konzepte zu entwickeln mit denen Deutschland als IT-Standort gefestigt werden kann.
Dieses Jahr gilt das Motto „digitalisieren_ vernetzen_ gründen“. Am 13. November 2012 wird es im ThyssenKrupp Quartier in Essen unter Anderem um folgende Themen gehen:

  • Arbeitsgruppe 1 – „Digitale Wirtschaft in Deutschland“
  • Arbeitsgruppe 2 – „Digitale Infrastrukturen als Enabler für innovative Anwendungen“
  • Arbeitsgruppe 3 – „Innovative IT-Angebote des Staates“
  • Arbeitsgruppe 4 – „Vertrauen, Datenschutz und Sicherheit im Internet“
  • Arbeitsgruppe 5 – „Verantwortung und Schutz in der vernetzten Gesellschaft“
  • Arbeitsgruppe 6 – „Bildung und Forschung für die digitale Zukunft“
  • Arbeitsgruppe Regionalthema – „NRW gestaltet IKT – Industriell. Integriert. Innovativ.“
  • Arbeitsgruppe Sonderthema – „eHealth/Gesundheitstelematik“

Ein Blog informiert vorab und bei Youtube kann man sich einzelne Clips aus den letzten Jahren ansehen, Rösler und Seehofer beim letzten Gipfel 2011 zum Beispiel.

Dort bei diesem Event dabei zu sein ist nun eigentlich Politikern und nur den größten Unternehmen der Wirtschaft vorenthalten. In den Berichterstattungen fällt dieses einheitliche Bild auch schnell auf, das Publikum ist sorgfältig ausgewählt:

In den einzelnen Arbeitsgruppen sind die Firmen und Politiker gelistet, die dort vertreten sein werden, alles mit Rang und Namen.

Umso spannender ist es doch, dass dieses Jahr 10 deutsche Blogger vor Ort sein werden um persönlich von dem Event zu berichten, zu bloggen um genau zu sein!
Die sogenannte Bloggerchallenge, die dieses Jahr unter dem Motto „Vom Start-up zur Global Brand!?“ steht, ermöglicht es nicht nur vor, während und nach dem Event offiziell zu berichten sondern für einen dieser Blogger heißt es dann auch: ab ins Silicon Valley! Für ganze 5 Tage wird der/die Gewinner/in dort in Kalifornien von dem German Silicon Valley Accelerator -Programm berichten können.

Klingt das verlockend? Dann werft einen Blick auf die Bloggerchallenge Seite.

Der Prozess SeachIndexer.exe ist ein Prozess des „Windows Suche“ Dienstes. Dieser Dienst sorgt dafür, dass Ordner, Dateien, Dateieigenschaften und Dateiinhalte für die Windows Suche vorbereitet und optimiert. Ob man das braucht muss jeder selber entscheiden. Ich nutze die Windows Suche weder im Explorer noch in anderen Microsoft Programmen, der Prozess ist also eher lästig.

Indizierung beenden

Start -> (Systemsteuerung ->) Indizierungsoptionen -> Erweitert -> [Neu Erstellen]

Damit wird die bisherige Indizierungsdatenbank gelöscht. Anschließend:

Start -> Ausführen -> Services.msc -> "Windows Search" -> Eigenschaften -> [Beenden]

um den Dienst zu beenden und dann Starttyp auf „Deaktiviert“ stellen.
Damit sollten der Dienst und der Prozess lahm liegen.

Nur Startmenü indizieren

Eine sinnvolle Alternative zum Beenden, vorgeschlagen vom Leser Klemens, ist das Reduzieren der Indizierungsorte auf das Startmenü.
Geht dazu in die Indizierungsoptionen, klickt auf „Ändern“ und entfernt dort alle Orte bis auf das Startmenü.
So wird der Indizierungsdienst nicht mehr viel ackern und ihr könnt im Startmenü trotzdem all eure Programme über die Suchleiste finden.
Das Bild zeigt die Einstellungen der Indizierungsoptionen in denen nur das Startmenü als Indizierungsort ausgewählt wurde um die Auslastung durch die Windows Suche zu minimieren