Abspeichern eines kompletten JPanels

Nachtfalke

Aktives Mitglied
Hallo zusammen,

ich habe in meiner Anwendung ein JPanel auf dem diverse Objekte platziert sind. Nun würde ich gerne das gesamte JPanel beim Beenden der Anwendung abspeichern, um es beim nächsten Start wieder laden und anzeigen zu können. Dummerweise sind bei den enthaltenen Objekten solche dabei, die sich nicht serialisieren lassen. Gibt es noch eine andere Möglichkeit, das Problem zu lösen?
 

André Uhres

Top Contributor
Hallo Nachtfalke,

bei MVC Objekten müssen wir lediglich das Model abspeichern. Ist es nicht serialisierbar, kann es in der Regel durch Erweiterung serialisierbar gemacht werden.

Gruß.
André
 

GUI-Programmer

Top Contributor
Wenn du jetzt dennoch noch vorhast die ganzenKomponenten abzuspeichern, musst du halt die get(Component comp, int index) aufrufen und die entsprechenden Komponenten abspeichern, sowie die Getter die das JPanel bespreichen - eine mühsame und meiner und wahrscheinlich auch André Uhres Meinung nach sinnlose und unnötige Aufgabe.
 
G

Gast2

Gast
Was sind MVC-Objekte? Und wie speichere ich das Model?

Mach mal langsam. MVC ist ein Design Pattern. Klassen die nach diesem Design Pattern konzipiert werden, bze die Objekte dieser Klassen, könnte man MVC Objekte nennen. Finde ich aber ehrlich gesagt blödsinn.

Die Objekte die du dann hast wären Models Controller Klassen (Meistens durch Frameworks ersetzt) und die GUI Klassen.

Les dir mal was dazu durch und mach mal ein paar einfache Übungen zum Thema. Wenn das läuft kannst du übers speichern nachdenken. Vorher nit. Man lernt ja auch erst laufen und dann sprinten.
 

GUI-Programmer

Top Contributor
Les dir mal was dazu durch und mach mal ein paar einfache Übungen zum Thema.

Wie etwa meine Art mit MVC umzugehen: In MVC Ein JFrame, mehrere JPanels
Wobei du dann halt die Speichermechanismen im Model implementieren musst. D.h. du musst alle Werte abspeichern, z.B. bei wenigen Werten per Properties (z.B. über XML), und diese bei jeden Programmstart aus diesen Properties laden und dem Werten entsprechend deine GUI, also deine Panels mit Komponenten aufbauen.
 
C

Camino

Gast
Was sind MVC-Objekte? Und wie speichere ich das Model?
Bei MVC hast du eine Trennung von Model (enthält die Daten) und View (Ansicht, GUI). Normalerweise baut sich die View nach den Daten des Models auf, bzw. aktualisert sich, wenn sich die Daten im Model geändert haben. Deshalb brauchst du wahrscheinlich nur diese Daten zu speichern und beim Neustart diese wieder einzulesen und die View zu aktualisieren.
 

André Uhres

Top Contributor
Was sind MVC-Objekte? Und wie speichere ich das Model?

Die Swing GUI Komponenten sind z.B. in der Regel nach dem MVC Prinzip aufgebaut. JTable hat ein TableModel und eine TableUI. Aus der Sicht der MVC-Struktur implementiert TableModel das "Model", TableUI die "View" und JTable den "Controller" (mit "MVC-Objekt" meine ich die ganze Komponente).

Man kann z.B. mit "XMLEncoder" eine JTable speichern und mit XMLDecoder wieder laden, indem man in Wirklichkeit nur das Model speichert und ladet.

Gruß,
André
 

Schandro

Top Contributor
Bin auch GUI-Programmers Meinung, überleg dir lieber was du wirklich abspeichern musst und mach das in deinem eigenen Format in XML o.Ä., ist denke ich sehr viel sinnvoller und du lernst dadurch auch mehr als einfach alle Components zu serialisieren
 

André Uhres

Top Contributor
Bin auch GUI-Programmers Meinung, überleg dir lieber was du wirklich abspeichern musst
Das MVC-Konzept setzt ja gerade diese Überlegung voraus.

und mach das in deinem eigenen Format in XML o.Ä., ist denke ich sehr viel sinnvoller und du lernst dadurch auch mehr

Die Entwicklung eines sinnvollen Models ist im vorliegenden Fall wohl wichtiger als die Art des Abspeicherns, denn die gespeicherten Daten dienen ja nur der Wiederherstellung der GUI, wenn ich Nachtfalke richtig verstanden habe.

Gruß,
André
 

Schandro

Top Contributor
Die Entwicklung eines sinnvollen Models ist im vorliegenden Fall wohl wichtiger als die Art des Abspeicherns, denn die gespeicherten Daten dienen ja nur der Wiederherstellung der GUI, wenn ich Nachtfalke richtig verstanden habe.
Eine sinnvolles Model ist wohl die Grundlage für ein eigenes abspeichern anstatt alles von serialize machen zu lassen ;)
 

André Uhres

Top Contributor
Eine sinnvolles Model ist wohl die Grundlage für ein eigenes abspeichern anstatt alles von serialize machen zu lassen ;)

Ein sinnvolles Model ist die Grundlage sowohl für ein eigenes Abspeichern als auch für ein sinnvolles Serialisieren. Ein eigenes Abspeichern bringt aber nach aktueller Sachlage für die Anwendung keinen Vorteil ;).

Gruß,
André
 

Nachtfalke

Aktives Mitglied
Wie etwa meine Art mit MVC umzugehen: In MVC Ein JFrame, mehrere JPanels
Wobei du dann halt die Speichermechanismen im Model implementieren musst. D.h. du musst alle Werte abspeichern, z.B. bei wenigen Werten per Properties (z.B. über XML), und diese bei jeden Programmstart aus diesen Properties laden und dem Werten entsprechend deine GUI, also deine Panels mit Komponenten aufbauen.

Jetzt habe ich verstanden was ihr meint. Ich hatte mir schon gedacht, daß ich um eigene Speichermechanismen nicht herumkomme, aber ich hatte gehofft, daß es etwas ähnlich einfaches gibt wie die Serialisierung.
 

Nachtfalke

Aktives Mitglied
Ich habe es jetzt doch nochmal mit Serialisierung versucht, indem ich zunächst mal feststellen wollte, welche der Komponenten nicht serialisierbar sind. Das erste Problem trat bei einer JTable auf. Tante Google hat mir dann verraten, daß JTables im Gesamten nicht serialisierbar sind. Ist auch logisch, da das Speichern der GUI keinen Sinn machen würde. Daraufhin habe ich versucht, nur das Model der Table zu serialisieren. Das funktioniert aber auch nicht. Kann das an meinem Model liegen?

Java:
public class StatTableModel extends DefaultTableModel implements Serializable {

  private final Integer STEP = 5;
  public FormatData[][] cellFormat = new FormatData[10][10];

  private FormatData[][] resizeArray(FormatData[][] array, Integer cols, Integer rows) {
    FormatData[][] help = new FormatData[array.length + cols][array[0].length + rows];
    for (int i = 0; i < array.length + cols; i++) {
      for (int j = 0; j < array[0].length + rows; j++) {
        help[i][j] = new FormatData();
      }
    }
    System.arraycopy(array, 0, help, 0, array.length);
    return help;
  }

  @Override
  public void addColumn(Object colName, Object[] data) {
    super.addColumn(colName, data);
    if (getColumnCount() >= cellFormat[0].length) {
      cellFormat = resizeArray(cellFormat, 0, STEP);
    }
  }

  @Override
  public void addRow(Vector data) {
    super.addRow(data);
    if (getRowCount() >= cellFormat.length) {
      cellFormat = resizeArray(cellFormat, STEP, 0);
    }
  }

  public StatTableModel() {
    super();
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        cellFormat[i][j] = new FormatData();
      }
    }
  }
}

Die Klasse FormatData implementiert Serializable.
 

bERt0r

Top Contributor
Ja kann es, weil in deinem Model EventListener gespeichert werden, die meines Wissens nach nicht serializable sind. Kann mich aber auch täuschen. Am einfachsten ist es, du überschreibst einfach folgende Methoden:
Java:
private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;
 private void readObjectNoData() 
     throws ObjectStreamException;
Das heisst, du kümmerst dich manuell darum, welche Daten auf den outputstream geschrieben werden bzw. gelesen werden.
Discover the secrets of the Java Serialization API
 

André Uhres

Top Contributor
Daraufhin habe ich versucht, nur das Model der Table zu serialisieren. Das funktioniert aber auch nicht.

Du musst nur noch die fehlenden Getter/Setter zum StatTableModel hinzufügen:
Java:
public Vector getColumnIdentifiers() {
    return columnIdentifiers;
}
public void setDataVector(Vector dataVector) {
    this.dataVector = dataVector;
}
Danach funktioniert es ohne Weiteres mit XMLEncoder/XMLDecoder:
Java:
XMLEncoder o = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(filename)));
o.writeObject(table.getModel());
o.close();
...
XMLDecoder d = new XMLDecoder(new BufferedInputStream(new FileInputStream(filename)));
table.setModel((TableModel) d.readObject());
d.close();

Gruß,
André
 
Zuletzt bearbeitet:
B

bygones

Gast
hab ich was verpasst ?!

warum musst du deine kompletten Swing elemente serialisieren und nicht einfach die Daten die die Elemente anzeigen ?!
 
G

Gast2

Gast
Die Daten liegen im Tablemodel und das ist aufgrund des Bugs nicht serialisierbar.

Da ist auch dein Denkfehler. Du brauchst ein Model (ein eigenes) in dem du die für DICH relevanten Daten ablegst. Deine GUI (respektive das JTable) stellt diese Daten für dich dar! WIE der JTable das widerum macht ist vollkommen egal. Das ist in diesem Fall zwar auch ein Model, jedoch nicht dein eigenes Program Model!

Erstelle dir also eine eigene Model Klasse in der du die Daten vorhälst. Deine GUI verbindet sich mit dem Model und fragt die Daten ab. (Stichwort MVC). Der JTable muss dann natürlich deine Model Daten so übersetzen, dass sie in sein eigenes Model passen. Das JTable Model gehört aber dennoch zur GUI und somit zum VIEW im MVC.

Dein Model kannst du dann speichern wie immer du es für nötig hälst. Datenhaltung wäre dann von der Anzeigelogik getrennt.

Stell dir nur mal vor du wechselt aus irgendeinem Grund die GUI Bibliothek. Dein Backbone (Daten) bleibt dann gleich. Nur die Darstellung verändert sich.
 

André Uhres

Top Contributor
Hallo Nachtfalke,

wenn Du die Klasse "SizeSequence" abspeichern willst, musst Du sie kopieren und anpassen.

Alternativ kannst Du vielleicht die Zeilenhöhe aus anderen Daten ableiten oder in die Zeilendaten als zusätzliche Eigenschaft einfügen, die nur benutzt wird, um die Höhe der betreffenden Zeile einzustellen.

Gruß,
André
 

Nachtfalke

Aktives Mitglied
Hallo Nachtfalke,

wenn Du die Klasse "SizeSequence" abspeichern willst, musst Du sie kopieren und anpassen.

Alternativ kannst Du vielleicht die Zeilenhöhe aus anderen Daten ableiten oder in die Zeilendaten als zusätzliche Eigenschaft einfügen, die nur benutzt wird, um die Höhe der betreffenden Zeile einzustellen.

Gruß,
André

Genauso hatte ich mir das gedacht. Inzwischen funktioniert die Serialisierung einwandfrei. Mittels dieser Methode:

Java:
public void saveStatistics() {
    
    int i;
    
    try
    {
      FileOutputStream file = new FileOutputStream("statistik.ser");
      ObjectOutputStream o = new ObjectOutputStream( file );
      System.out.println("Writing objects to disk ...");

      o.writeObject(statistikPanel);
      o.close();
    }
    catch ( IOException e ) { System.err.println( e ); }
  }

speichere ich das entsprechende Panel. Mittels dieser Methode:
Java:
public JScrollPane loadStatistics() {
    
    JScrollPane newPanel = new JScrollPane();
    try
    {
      System.out.println("Reading objects ...");
      FileInputStream file = new FileInputStream("statistik.ser");
      ObjectInputStream o = new ObjectInputStream(file);
      newPanel = (JScrollPane) o.readObject();
      o.close();
    }
    catch ( IOException e ) { 
      System.err.println( e ); 
    }
    catch ( ClassNotFoundException e ) { 
      System.err.println( e ); 
    }
    return newPanel; 
  }

möchte ich es zurückholen, die ich mit

Java:
meinPanel = loadStatistics();

aufrufe, aber nach dem Laden wird das Panel nicht mit den Objekten gefüllt :(. Irgendwo muss wohl noch ein Fehler sein. Aber den werde ich auch noch finden.
 
G

Gast2

Gast
Und dein letzter Post beweist wie einfach man Empfehlungen ignorieren kann ...

Anstatt es richtig zu machen wurschtelst du dich damit durch doch die GUI selber zu speichern.

Viel Glück und Adios!
 

bERt0r

Top Contributor
Der bug den du gepostet hast ist von 2003...
So (De)Serialisiert man ein TableModel:
Java:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;


public class Serialize2 extends JFrame {

	private JPanel contentPane;
	private JTable table;
	private File tempFile;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Serialize2 frame = new Serialize2();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Serialize2() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);
		
		table = new JTable();
		table.setRowHeight(30);
		table.setModel(new DefaultTableModel(
	            new Object[][] {
	                {"Sepp",new Integer(1)},
	                { "Fritz", 2},
	                { "Karl", 3},
	                { "Georg",4},
	                { "Franz", 5},
	            },
	            new String[] {
	                "Name", "Bewertung"
	            }
	        ) {
	            /**
	             * 
	             */
	            private static final long serialVersionUID = 1L;
	            Class[] columnTypes = new Class[] {
	                Object.class, String.class
	            };
	            public Class getColumnClass(int columnIndex) {
	                return columnTypes[columnIndex];
	            }
	            private void writeObject(ObjectOutputStream out) throws IOException
	            {
	                out.writeObject(this.columnIdentifiers);
	                out.writeObject(columnTypes);
	                out.writeObject(this.dataVector);
	            }
	            
	            private void readObject(ObjectInputStream in) throws IOException
	            {
	            	
	                try{
	                    Object o=in.readObject();
	                    if(o instanceof Vector)
	                    {
	                        this.columnIdentifiers=(Vector<?>)o;
	                    }
	                    o=in.readObject();
	                    if(o instanceof Class[])
	                    {
	                        this.columnTypes=(Class[])o;
	                    }
	                    o=in.readObject();
	                    if(o instanceof Vector)
	                    {
	                        this.dataVector=(Vector<?>)o;
	                    }
	                }catch(ClassNotFoundException e)
	                {
	                    e.printStackTrace();
	                }
	 
	            }
	        });
		contentPane.add(table, BorderLayout.CENTER);
		
		JPanel panel = new JPanel();
		contentPane.add(panel, BorderLayout.SOUTH);
		
		JButton btnSerialize = new JButton("Serialize");
		btnSerialize.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) 
			{
				try {
					tempFile=File.createTempFile("Table", "tmp");
					ObjectOutputStream o=new ObjectOutputStream(new FileOutputStream(tempFile));
					table.removeEditor();
					o.writeObject(table.getModel());
					o.close();
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
		panel.add(btnSerialize);
		
		JButton btnDeserialize = new JButton("Deserialize");
		btnDeserialize.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				if(tempFile==null)
				{
					JOptionPane.showMessageDialog((Component) e.getSource(), "Fehler","Erst serialisieren!",JOptionPane.ERROR_MESSAGE);
				}
				else
				{
				try {
					ObjectInputStream in=new ObjectInputStream(new FileInputStream(tempFile));
					TableModel tm=(TableModel)in.readObject();
					table.setModel(tm);
					table.revalidate();
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (ClassNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				}
			}
		});
		panel.add(btnDeserialize);
	}

}
 

André Uhres

Top Contributor
Genauso hatte ich mir das gedacht.

Welche von den drei Alternativen hattest Du dir denn gedacht?

Inzwischen funktioniert die Serialisierung einwandfrei.

Und woher willst Du das wissen, wenn Du die Komponente nicht laden kannst?

Irgendwo muss wohl noch ein Fehler sein. Aber den werde ich auch noch finden.

Dann viel Glück. Falls es doch nicht funktionieren sollte: es wurden Dir ja schon eine ganze Menge Ideen vorgeschlagen, die Du dann noch ausprobieren kannst ;).

Gruß,
André
 

André Uhres

Top Contributor
Das Speichern läuft ohne Fehlermeldung durch und die geschriebene Datei hat eine Größe von ca. 5,5 MB. Die Wahrscheinlichkeit, daß das Schreiben einwandfrei funktioniert hat ist damit ziemlich hoch, denke ich.

Leider kannst Du nicht sehen, was er schreibt, da es eine binäre Datei ist. Somit kannst Du nicht wissen, ob alle relevanten Daten gespeichert werden. Zudem wird die binäre Variante (im Gegensatz zu XMLEncoder) für langfristiges Speichern nicht empfohlen, weil verschiedene Java-Versionen unterschiedliche Dateien erzeugen können, die mitunter nicht kompatibel sind. In dem Fall könnte Dein Programm nicht mehr lauffähig sein, wenn eine neue Java-Version installiert wird.

Gruß,
André
 

hdi

Top Contributor
Sag mal, was genau willst du eigentlich speichern bzw laden? Du redest hier von irgendwelchen Panel-Objekten. Was soll das sein? Werd mal konkret, dann können wir dir auch sagen wie du das am besten angehen solltest. Ich befürchte du vermischt hier zwei Sachen:

1) Willst du die eigentlichen Daten speichern, die angezeigt werden, d.h. der Inhalt der Table (=Business Model)

2) Oder willst du sowas wie Spalten-Anordnung, Tabellen-Selektion oder irgendwelche eingestellten Farben usw speichern?

Oder beides?
 

Nachtfalke

Aktives Mitglied
Sag mal, was genau willst du eigentlich speichern bzw laden? Du redest hier von irgendwelchen Panel-Objekten. Was soll das sein? Werd mal konkret, dann können wir dir auch sagen wie du das am besten angehen solltest. Ich befürchte du vermischt hier zwei Sachen:

1) Willst du die eigentlichen Daten speichern, die angezeigt werden, d.h. der Inhalt der Table (=Business Model)

2) Oder willst du sowas wie Spalten-Anordnung, Tabellen-Selektion oder irgendwelche eingestellten Farben usw speichern?

Oder beides?

beides.
 

André Uhres

Top Contributor
2) Oder willst du sowas wie Spalten-Anordnung ... speichern?

Die Spalten-Anordnung (und Spalten-Breiten) könnte man noch unter 1) aufzählen, weil JTable ein TableColumnModel hat, das man problemlos speichern kann.

Er will aber auch noch die Zeilenhöhe speichern. Das wurde bereits besprochen.

Er scheint aber noch nicht so richtig auf die jeweiligen Vorschläge einzugehen und reagiert oft kurz angebunden, selten konkret. Er will wahrscheinlich erst mal seine eigenen Ideen soweit verwirklichen, bis er selbst sieht, dass es so nicht funktionieren kann. Jedem Tierchen, sein Pläsierchen :D.

Gruß,
André
 

hdi

Top Contributor
Gut, wie du die eigentlichen Tabellen-Inhalte abspeichern kannst hat dir kappesf ja schon gesagt: Die Daten sollten nicht unmittelbarer Bestandteil der Table sein, sondern separat in deiner Anwendung vorhanden sein, und lediglich über ein TableModel auf die Tabelle gemappt werden. Deine Daten sollten also nicht direkt ins TableModel eingefügt oder daraus gelöscht werden. Diese Business-Daten kannst du dann erstmal völlig unabhängig von der Tabelle abspeichern. Das Laden ist dann auch unproblematisch, weil bei korrekter MVC-Implementierung der Table mitbekommt wenn neue Business-Daten da sind und diese "automtaisch anzeigt." Für das Speichern dieser Daten würd ich jetzt aber nicht unbedingt Serialisierung vornehmen. Schreib dir einfach ne eigene Methode zum speichern und laden deiner Daten.

Was nun den Zustand der GUI angeht: Was genau serialisierst du, und was meinst du mit "das Panel wird nicht mit Objekten gefüllt". Welches Panel? Ist das ein JPanel? Und was sind die Objekte?
 

André Uhres

Top Contributor
Die Daten sollten nicht unmittelbarer Bestandteil der Table sein, sondern separat in deiner Anwendung vorhanden sein

Das wurde in der Tat schon gesagt, jedoch ist das TableModel bereits separat und eine wirkliche Notwendigkeit für die vorgeschlagene Daten-Verdoppelung sehe ich nicht. MVC kann auch in einer Anwendung auf mehreren Ebenen agieren und außerdem muss man MVC auch nicht immer allzu stur befolgen, sondern auch danach schauen, was praktikabel ist.

Gruß,
André
 

hdi

Top Contributor
Achso er verwendet also eine eigene Datenstruktur für seine Daten, die halt gleich schon TableModel implementiert? Klar, DefaultTableModel ist so gesehen auch separat, aber naja.. Man bleibt halt an den/einen Table gekettet. Warum du von Daten-Verdopplung sprichst versteh ich aber nicht. Es verdoppelt sich doch nix nur weil ein TableModel dazukommt.
 

hdi

Top Contributor
Ich verstehe nicht, wieso man an den/einen Table gekettet bleibt, wenn das Model separat ist.
Aber das ist es ja nicht?! Soweit ich das jetzt verstanden hab hat der TO seine Daten direkt in einem TableModel. D.h. als direkten Bestandteil dieser View. TableModel heißt ja nur "Model", aber es aus Sicht von MVC gehört es nicht zum M, sondern zum V. Ein TableModel ist nun mal auf einen JTable ausgelegt, und nicht beispielsweise auf eine JList oder eine komplett UI-unabhängige Datenstruktur. Er ist einen Table gekettet, und kann zB nicht mal eben auf eine List umsteigen, denn JList kann mit einem TableModel nix anfangen. Er muss das TableModel also durch ein ListModel ersetzen. Dann wiederum ist sein TableModel futsch, also wenn die Table als zweite Komponente hinzukommen soll, gibt's wieder ein PRoblem.

Aber irgendwie müssen wir aneinander vorbeireden, denn mir ist klar dass du ganz genau weißt was ein Table- oder ListModel ist ;)
 

bERt0r

Top Contributor
Wie Andre schon sagte kommt das eben auf die Anwendung drauf an und man muss man nicht immer stur MVC befolgen. Wenn er seine Daten noch in einer List braucht, spricht nichts dagegen dass das TableModel auch noch das ListModel Interface implementiert.
Wenn du deine Daten z.B aus einer Datenbank ziehst, wirst du natürlich auch noch eine andere MVC Schicht haben. Sind die Daten aber sticknormale Properties oder sowas, was ausm File eingelesen wird und nur in der Table angezeigt wird, so wies hier anscheinend der Fall ist sehe ich den Nutzen von noch einer MVC Schicht nicht.
 

hdi

Top Contributor
Wenn er seine Daten noch in einer List braucht, spricht nichts dagegen dass das TableModel auch noch das ListModel Interface implementiert.
Nur dass es dabei nicht bleibt. Denn wenn das TableModel die Daten ändert kriegt die List nix davon mit, und andersrum. Du darfst also im TableModel auch noch Events für die List feuern, und umgekehrt. Ich meine, es geht natürlich. Aber ich würd das generell nicht machen, egal wie primitiv die Anwendung ist. Man braucht ja nur eine einzige kleine weitere Klasse und nen Listener, und schon ist das sauber getrennt, und GUI und Core sind synchronisiert, egal wo oder wie die Daten verändert werden. Wenn zB irgendein Thread im Hintergrund etwas tun soll wenn neue Daten hinzukommen oder welche gelöscht werden, dann müsstest du diese Thread ja auch direkt in deine TableModel-ListModel-Implementierung reinklatschen. Und das ist dann der Punkt wo Model und View komplett durcheinander geraten.
 

bERt0r

Top Contributor
Events feuern musst du doch sowieso, oder setzt du dann bei jeder Änderung deines Datenmodells ein neues TableModel rein? Ich versteh jetzt nicht ganz was du meinst, vielleicht reden wir auch aneinander vorbei.
Schau wie schön einfach das funktioniert:
Java:
package TableListModel;

import java.util.List;
import java.util.Vector;

import javax.swing.ListModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;

public class TableListModel extends DefaultTableModel implements ListModel
{
	List<ListDataListener> listenerList=new Vector<ListDataListener>();

	public TableListModel(Object[][] objects, String[] strings) {
		super(objects,strings);
	}

	@Override
	public void addListDataListener(ListDataListener l) 
	{
		listenerList.add(l);
	}

	@Override
	public Object getElementAt(int i) {
		return this.getDataVector().get(i);
	}

	@Override
	public int getSize() {
		return this.getDataVector().size();
	}

	@Override
	public void removeListDataListener(ListDataListener l) 
	{
		listenerList.remove(l);
	}
		
	@Override
	public void fireTableChanged(TableModelEvent e)
	{
		super.fireTableChanged(e);
		if(listenerList!=null)
		{
			for(ListDataListener l: listenerList)
			{
				l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, e.getFirstRow(),e.getLastRow()));
			}
		}
	}	
}
 

hdi

Top Contributor
Events feuern musst du doch sowieso, oder setzt du dann bei jeder Änderung deines Datenmodells ein neues TableModel rein?
Nein, natürlich nicht. Aber ich feuer das Event über einen UI-unabhängigen BusinessData-Listener und reagiere in den einzelnen UI-Komponenten separat. So ist jede Komponente nur für sich verantwortlich, und ich muss mich nicht darum kümmern das Ganze jetzt von dort jeweils an irgendwelche Instanzen weiterzuleiten die mich eigentlich gar nix angehen.

Schau wie schön einfach das funktioniert:
Ja, so schön einfach funktioniert eine Read-Only List, die darüber hinaus die Einschränkung hat dass sie genau die Daten anzeigen muss die auch die Table anzeigt. Was passiert, wenn du diese beiden Views unabhängig voneinander steuern willst? So ist der nämlich in 99% der Fälle, wenn man die selben Daten in zwei verschiedenen Views hat. Wenn du die Daten nicht in der Table sondern in der List bearbeiten willst? Genau, das selbe Spiel nochmal andersrum implementieren, und in der fireListDataChanged() über deine TableDataListener drüberlaufen. Ist halt alles doppelt gemoppelt. Und das steigt exponentiell. Hast du 3 Views, hast du in JEDEM der Models den Aufwand ALLE 3 zu benachrichtigen. Und das Problem, dass UI-unabhängige Instanzen da jetzt gar nicht reinpassen hast du wohl unter den Tisch gekehrt ;)

Sorry, aber dieses Beispiel ist jetzt schon so eingeschränkt und mit nicht gewollten Abhängigkeiten verknüpft dass ich bei meiner Meinung festhalte. Den Code, den ich für meine externe Model-Klasse und den Listene schreibe, würdest du schon jetzt toppen wenn du die Synchronisation von Table und List auch in die andere Richtung realisieren willst.
 

André Uhres

Top Contributor
Ein TableModel ist nun mal auf einen JTable ausgelegt, und nicht beispielsweise auf eine JList oder eine komplett UI-unabhängige Datenstruktur.

Ob man das TableModel für eine Anwendung nutzt, wenn es passt, oder ein neues Model erfindet (das am Ende das Gleiche macht), dann sehe ich zwischen den beiden Möglichkeiten keinen wesentlichen Unterschied, außer dass vorhandener Code im ersten Fall wiederverwendet wird, was ich dann trotzdem bevorzuge :).

Gruß,
André
 

hdi

Top Contributor
Ob man das TableModel für eine Anwendung nutzt, wenn es passt...
Aber wann passt das schon? Ich meine was ist das für eine Software, wo du deine Core-Daten spezifiziert und in diesem Schritt schon sagst "Alles dreht sich um ne JTable". Denn das ist die Aussage wenn dein Core-Model ein TableModel ist. Das kann doch keine richtige Anwendung sein, außer eine JTable-Demo von Sun.

dann sehe ich zwischen den beiden Möglichkeiten keinen wesentlichen Unterschied, außer dass vorhandener Code im ersten Fall wiederverwendet wird, was ich dann trotzdem bevorzuge
Also ich nehm mir lieber die Zeit für eigenen Code, der dann auch genau passt, statt dass ich etwas hernehme nur weil es halt grad da ist. Ich meine schau mal im Endeffekt ist deine Aussage: "Ich habe keine Lust eine kleine Klasse mit 3-4 Methoden und einer Interface mit 3-4 Methoden zu schreiben, und lege mich aus diesem Grund darauf fest dass mein Programm im Wesentlichen irgendwas mit nem JTable zu tun hat". So wirkt das auf mich..

Naja, aber wie hast du heute schon irgendwo geschrieben: Jedem Tierchen, sein Pläsierchen ;) Und den letzten Satz bitte nicht falsch verstehen. Ich bin mir ziemlich sicher dass du mehr Erfahrung hast als ich und gute Software schreibst, bzw. deine Vorzeige-Software besser ist als meine. Nur ich persönlich sehe hier einfach keinen Pluspunkt, abgesehen eben davon dass du dir etwa 50 Zeilen Code sparst :bahnhof:
 

bERt0r

Top Contributor
Ja, so schön einfach funktioniert eine Read-Only List, die darüber hinaus die Einschränkung hat dass sie genau die Daten anzeigen muss die auch die Table anzeigt. Was passiert, wenn du diese beiden Views unabhängig voneinander steuern willst?
Nun die Standard JList ist nunmal Read only, ich weis jetzt gar nicht auf die schnelle wie man eine JList macht, in der man rumschreiben kann.
Zu zweiterem, ich dachte hier gehts darum die selben Daten in zwei Views anzuzeigen.

Ausserdem müssen sich doch bei deiner Variante alle Models bei deinem Datenmodell dann registrieren, damit die Events gefeuert werden, oder? Und wie funktioniert das, wenn das Tablemodel einen Datensatz ändert? Wo steckt der fire Aufruf an die anderen Models oder verwendest du eh nicht die Default-Model Klassen bzw. überschreibst du ihre Funktionen?
 

hdi

Top Contributor
Nun die Standard JList ist nunmal Read only, ich weis jetzt gar nicht auf die schnelle wie man eine JList macht, in der man rumschreiben kann.
Ja, ok der geht an dich ;) Ich dachte mehr an den "Bereich, in dem die JList liegt", also evtl damit verbundene Buttons usw, und weniger an die JList-Komponente selber.

Zu zweiterem, ich dachte hier gehts darum die selben Daten in zwei Views anzuzeigen.
Es ging mir um das selbe Model, was aber nicht heißt dass exakt die selben Datensätze daraus angezeigt werden in der JList und im JTable. Dein Problem ist wenn zB die JList gefiltert ist. Kann sein dass ein neuer Table Eintrag in der List gar nicht auftauchen darf. Dann ist die Frage was genau du für ein ListDataEvent feuerst wenn sich was in der Table ändert. Auch diese Infos hast du dann in deiner "Gott-Klasse" die immer größer und unübersichtlicher wird.

Ausserdem müssen sich doch bei deiner Variante alle Models bei deinem Datenmodell dann registrieren, damit die Events gefeuert werden, oder?
Genau, so mach ich das auch. Wenn ich eine neue View erstelle hab ich einen addListener() aufruf am model, wenn ich eine entferne einen removeListener()-Aufruf. Das geht ziemlich fix. Für den Listener hab ich ja nen abstrakten Datentyp.

Und wie funktioniert das, wenn das Tablemodel einen Datensatz ändert? Wo steckt der fire Aufruf an die anderen Models oder verwendest du eh nicht die Default-Model Klassen bzw. überschreibst du ihre Funktionen?
Die einzelnen Views haben eine Referenz auf das Business-Model, und rufen dort entsprechende manipulative Methoden auf. Das Busniess-Model schickt das Event an alle registrierten Listener. Damit kriegt jede Instanz eine Änderung mit, egal wodurch diese Änderung ausgelöst wurde. Und zwar nicht nur innerhalb der GUI, sondern auch in Bezug auf tieferliegende Instanzen, wie zB irgendwelche Background Threads o.ä. Die Notifikation vom Model gelangt so auch als Callback bei der View die das ganze ausgelöst hat. D.h. ich ruf in meinem TableModel nach einem add() im Model nicht selbst irgendein fire auf mir auf, sondern lass es über ein Callback auslösen. Kann ja sein, dass das adden vom model verweigert wird und sich gar nix tut.

Also so zieh ich all meine GUI-Applikationen auf. ICh kann so sehr leicht neue Views hinzufügen oder welche löschen, und ich muss die dann nur beim Business Model an-/abmelden. Sowohl die einzelnen Views, als auch die gesamte business-Schicht sind vollständig unabhängig voneinander. Im TableModel steht nix von ListModel, im ListModel steht nix von TableModel, und im Business-Model steht nix von beidem, da hab ich nur ganz abstrakte Listener. Was das für GUI-Komponenten sind, und ob das überhaupt Komponenten vom GUI sind, das kann mir egal sein.
 
Zuletzt bearbeitet:

bERt0r

Top Contributor
Die einzelnen Views haben eine Referenz auf das Business-Model
D.h. ich ruf in meinem TableModel nach einem add() im Model nicht selbst irgendein fire auf mir auf, sondern lass es über ein Callback auslösen.
Das heisst du schreibst dir auch jede deiner Views neu oder wie darf ich das verstehen? Irgendwie klingt das doch nach sehr viel mehr Aufwand als eine Instanz dieses Models da oben an 2 Konstruktoren zu übergeben, aber jedem das seine :) Auch wenns den TO sicher nicht mehr interessiert, haben wir zumindest eine super Diskussion aus dem Thread gemacht :D </spam>
 

hdi

Top Contributor
Das heisst du schreibst dir auch jede deiner Views neu oder wie darf ich das verstehen? Irgendwie klingt das doch nach sehr viel mehr Aufwand als eine Instanz dieses Models da oben an 2 Konstruktoren zu übergeben, aber jedem das seine
Du, ob du nun 1 Klasse hast die beide Interfaces implementiert, oder 2 Klassen die jeweils eines davon implementieren ist doch das selbe vom Aufwand her. Ja, okay, ich hab 2 Konstruktoren, du nur einen :eek: ;) Du darfst nicht vergessen dass meine View-Klassen im Gegensatz zu deiner Klasse ja jeweils wirklich nur noch das Mapping auf diese eine View enthalten, das ganze "Core"-Zeug vom Model ist ja in meinem Business-Model, und das hab ich nur einmal. Diese Business-Model Klasse und deren ListenerInterface sind das einzige, was ich mehr an Code hab. Aber durch die saubere Trennung spar ich mir auf Seiten der View wiederum ein paar Zeilen, zB weil ich eben nicht an verschiedensten Stellen mehrere verschiedene fire-Methoden aufrufen muss. Und ich kann eben auch vereinzelt Views löschen, das kannst du nicht so easy. Wirf jetzt mal deine Table über den Haufen: Deine ganze App reagiert nur auf TableDataEvents, die es jetzt nicht mehr gibt.. Also schön alles auf ListDataEvents umwälzen, DAS ist Aufwand :pueh: :D

Auch wenns den TO sicher nicht mehr interessiert, haben wir zumindest eine super Diskussion aus dem Thread gemacht
Na wenigstens etwas ;) In diesem Sinne, gute Nacht!
 

André Uhres

Top Contributor
Aber wann passt das schon?

Daten, die in Tabellenform vorliegen, gibt es ziemlich oft. Die müssen aber nicht immer für JTable gedacht sein. Hier ist z.B. der WindController vom MVC Tutorial aus unseren FAQ, in einer erweiterten Version, für die Windmessungen von vier verschiedenen Orten:
Java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class WindController {

    private Wind wind;

    public WindController() {
        WindViewer viewer = new WindViewer(this);
        wind = new Wind();
        wind.addTableModelListener(viewer);
    }

    public void changeDirection() {
        int row = (int) (Math.random() * 4);
        Direction direction = Direction.values()[(int) (Math.random() * 4)];
        wind.setValueAt(direction, row, 1);
    }

    public void changeSpeed() {
        int row = (int) (Math.random() * 4);
        int speed = (int) (Math.random() * 100);
        wind.setValueAt(speed, row, 2);
    }

    public Wind getWind() {
        return wind;
    }

    public static void main(final String[] args) {
        Runnable gui = new Runnable() {

            @Override
            public void run() {
                new WindController();
            }
        };
        //GUI must start on EventDispatchThread:
        SwingUtilities.invokeLater(gui);
    }
}

class Wind extends DefaultTableModel {

    public Wind() {
        super(0, 3);
        addRow(new Object[]{"Paris", Direction.EAST, 2});
        addRow(new Object[]{"Brüssel", Direction.EAST, 10});
        addRow(new Object[]{"Luxembourg", Direction.NORTH, 8});
        addRow(new Object[]{"Berlin", Direction.WEST, 23});
    }
}

enum Direction {

    NORTH, EAST, SOUTH, WEST
}

class WindViewer extends JFrame implements TableModelListener {

    private WindController controller;
    private JLabel id;
    private JLabel direction;
    private JLabel speed;
    private JPanel buttonPanel;
    private JPanel mainPanel;

    public WindViewer(WindController controller) {
        super("WindViewer");
        this.controller = controller;
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        init();
        setSize(400, 100);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private void init() {
        buttonPanel = new JPanel();
        mainPanel = new JPanel();
        id = new JLabel();
        direction = new JLabel();
        speed = new JLabel();
        mainPanel.add(new JLabel("Id: "));
        mainPanel.add(id);
        mainPanel.add(new JLabel("Direction: "));
        mainPanel.add(direction);
        mainPanel.add(new JLabel("Speed: "));
        mainPanel.add(speed);
        getContentPane().add(mainPanel);

        JButton button = new JButton("Change Direction");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {
                controller.changeDirection();
            }
        });
        buttonPanel.add(button);

        button = new JButton("Change Speed");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {
                controller.changeSpeed();
            }
        });
        buttonPanel.add(button);
        getContentPane().add(buttonPanel, BorderLayout.SOUTH);
    }

    @Override
    public void tableChanged(TableModelEvent e) {
        int row = e.getFirstRow();
        Wind wind = controller.getWind();
        id.setText(wind.getValueAt(row, 0).toString());
        direction.setText(wind.getValueAt(row, 1).toString());
        speed.setText(wind.getValueAt(row, 2).toString());

    }
}
Gruß,
André
 
Zuletzt bearbeitet:

bERt0r

Top Contributor
So schlecht geschlafen, will Klarheit :D
@Hdi, deine JTable Klasse implementiert das TableModel interface oder wie? Und wieso sollte ich irgendwas umimplementieren müssen, nur weil der JTable weg ist kann mein Model immer noch Events werfen. Der JTable hört sie dann halt nicht mehr, die list aber sehr wohl.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
V mehrere bilder als eines abspeichern AWT, Swing, JavaFX & SWT 2
F RTF eines JEditorPanes abspeichern AWT, Swing, JavaFX & SWT 9
L Swing Files abspeichern mit Save as Dialog Fenster AWT, Swing, JavaFX & SWT 5
E AWT Bilder als "Array" abspeichern. AWT, Swing, JavaFX & SWT 4
S Projekt: Meisterschaft - Abspeichern bereits gemachter Schritte AWT, Swing, JavaFX & SWT 2
Y JavaFX Bild speichern und Pfad dazu abspeichern AWT, Swing, JavaFX & SWT 2
P BufferedImage schlechte Qualität beim Abspeichern AWT, Swing, JavaFX & SWT 9
P Komische Zeichen beim Abspeichern von TextFelder AWT, Swing, JavaFX & SWT 2
S Schwarzes Bild beim Abspeichern von JPanel AWT, Swing, JavaFX & SWT 12
S JTree Elemente nach BaumLevel abspeichern AWT, Swing, JavaFX & SWT 2
J Swing Problem - Abspeichern JSplitPane Position AWT, Swing, JavaFX & SWT 5
S Abspeichern aus einem ImageIcon ins korrekte Format AWT, Swing, JavaFX & SWT 2
Y AWT Maus Koordinaten abspeichern in eine Textfile AWT, Swing, JavaFX & SWT 3
H Image abspeichern AWT, Swing, JavaFX & SWT 4
N Frame bzw Grafiks als JPEG abspeichern AWT, Swing, JavaFX & SWT 4
X Swing Inhalt einer JEditorPane in Datei abspeichern AWT, Swing, JavaFX & SWT 5
R Wie kann man beim JTree die UserObjects mit abspeichern ? AWT, Swing, JavaFX & SWT 3
R JPanel mit Bildern als jpg abspeichern AWT, Swing, JavaFX & SWT 9
H Bild abspeichern AWT, Swing, JavaFX & SWT 7
G JLabel als JPG abspeichern AWT, Swing, JavaFX & SWT 9
H Selektionen in einem JTree abspeichern (Navigationshilfe) AWT, Swing, JavaFX & SWT 4
R Tree-Struktur in einer DB abspeichern AWT, Swing, JavaFX & SWT 15
redztripe Graphics2D rotieren und rotiertes Bild abspeichern AWT, Swing, JavaFX & SWT 2
jojoge wie kann ich in eine Benennung eines JButtons eine Variable einbauen? AWT, Swing, JavaFX & SWT 6
L paintComponent in Panel eines Borderlayouts hinzufügen AWT, Swing, JavaFX & SWT 3
I Einbindung eines jpg/png/icons in eine GUI AWT, Swing, JavaFX & SWT 1
Splayfer Umrandung eines AttributedStrings AWT, Swing, JavaFX & SWT 2
Guybrush Threepwood Einfachste Möglichkeit zum Abspielen eines Videos in Swing AWT, Swing, JavaFX & SWT 4
Jose05 NullPointerException bei Beschreiben eines Labels aus einem Array AWT, Swing, JavaFX & SWT 12
Jose05 zugreifen auf ein Objekt eines GridPanes AWT, Swing, JavaFX & SWT 0
melaniemueller Verschiebung eines Fensters über Button AWT, Swing, JavaFX & SWT 27
news2swen automatisches erstellen eines Languagefiles AWT, Swing, JavaFX & SWT 1
B Stylen eines JTextPane funktioniert nicht AWT, Swing, JavaFX & SWT 1
MiMa Schliessen eines FXML Fensters? AWT, Swing, JavaFX & SWT 10
B JavaFX Farbe eines Quadrates in einer separaten Klasse ändern AWT, Swing, JavaFX & SWT 4
L AWT Ändern der Farbe eines BufferedImage mit Farbähnlichkeit AWT, Swing, JavaFX & SWT 5
B veränderte Größe eines Panels im Vorhinein wissen? AWT, Swing, JavaFX & SWT 1
L Komponenten eines Panels werden erst nach Klick darauf angezeigt AWT, Swing, JavaFX & SWT 13
L JavaFX Validierung eines Spinner AWT, Swing, JavaFX & SWT 1
M Builden eines lauffähigen JAR Files AWT, Swing, JavaFX & SWT 3
K Swing Text eines Lables in einer Methode ändern AWT, Swing, JavaFX & SWT 13
M JavaFX rotieren eines Kreises mit konstanter Geschwindigkeit AWT, Swing, JavaFX & SWT 1
K JavaFX Allgemeine Fragen zu dem Aufbau eines Programms hinsichtlich der Klassen AWT, Swing, JavaFX & SWT 1
M JavaFX Auf ein UI Elemement eines anderen Controllers zugreifen AWT, Swing, JavaFX & SWT 0
P Bewegung eines Balkens in eineum JPanel welches als Spielfeld fungiert AWT, Swing, JavaFX & SWT 2
Tronert JavaFX Linienstärke eines Separators ändern? AWT, Swing, JavaFX & SWT 3
N JavaFX Group: Gezieltes entfernen eines Objects (Rectangle) AWT, Swing, JavaFX & SWT 0
J Ziehen eines Buttons im JPanel AWT, Swing, JavaFX & SWT 2
J Drag and Drop eines Buttons AWT, Swing, JavaFX & SWT 0
M NullPointerException bei Übergabe eines RadioButtons AWT, Swing, JavaFX & SWT 11
DaCrazyJavaExpert Swing Extern den Text eines nicht fetsgelegten Buttons bekommen. AWT, Swing, JavaFX & SWT 12
J JavaFX Rectangle innerhalb eines Rectangle oder Panes positionieren? AWT, Swing, JavaFX & SWT 1
C JavaFX Inhalt eines SplitPane's durch Menü-Auswahl ändern? AWT, Swing, JavaFX & SWT 13
J linken Bildausschnitt eines BufferedImage abschneiden AWT, Swing, JavaFX & SWT 4
J bestimmten Bereich eines JPanels drucken AWT, Swing, JavaFX & SWT 2
D LookAndFeel Überschreiben eines UIDelegate AWT, Swing, JavaFX & SWT 0
T Java FX Probleme beim befüllen eines Tableviews AWT, Swing, JavaFX & SWT 5
C Zeichen eines 6 -Eckes AWT, Swing, JavaFX & SWT 1
U JavaFX Wechsel der Scene nach betätigen eines Button AWT, Swing, JavaFX & SWT 2
F Screenshot eines JPanel AWT, Swing, JavaFX & SWT 3
S JavaFX TreeItem: Icon am Ende eines Eintrags anhängen AWT, Swing, JavaFX & SWT 2
D TAB Taste innerhalb eines JSpinner AWT, Swing, JavaFX & SWT 2
R Update eines Labels bei Methodenaufruf einer anderen Klasse AWT, Swing, JavaFX & SWT 9
F Swing Spaltenbreite einer Column eines JTable auslesen AWT, Swing, JavaFX & SWT 5
D Swing Komponenten Anordnung eines Panels in Verbindung eines weiteren Panels AWT, Swing, JavaFX & SWT 9
F Swing Rotation eines Bildes mit beliebigen Koordinaten um den Mittelpunkt AWT, Swing, JavaFX & SWT 3
Cromewell JavaFX Nur bestimmten Teil eines Canvas rendern und anzeigen AWT, Swing, JavaFX & SWT 2
Z Swing Variable eines Objekt aus Hashmap in JList anzeigen AWT, Swing, JavaFX & SWT 1
D Frame beim starten eines anderen Frames schließen AWT, Swing, JavaFX & SWT 2
R Hilfe beim ändern des Hintergrundes eines JFrames AWT, Swing, JavaFX & SWT 9
T Durch klicken eines Buttons Klasse wechseln AWT, Swing, JavaFX & SWT 2
E Swing Copy und Paste eines einzelnen Knoten aus einem JTree AWT, Swing, JavaFX & SWT 1
J Swing Vertikales Zeichnen eines Strings mit Java2D AWT, Swing, JavaFX & SWT 1
7 JavaFX Problem beim Zeichnen eines Dreiecks in einem GUI AWT, Swing, JavaFX & SWT 6
V JavaFX Teile eines Images Transparent machen AWT, Swing, JavaFX & SWT 4
I JavaFX Langes drücken eines Buttons AWT, Swing, JavaFX & SWT 4
B Swing Wie Witdh und Height eines GuiElements bekommen AWT, Swing, JavaFX & SWT 5
L Swing Teile eines JPanel in eigene Klasse auslagern AWT, Swing, JavaFX & SWT 3
M Swing JPanel innerhalb eines Frames verschieben AWT, Swing, JavaFX & SWT 3
J JavaFX Zugriff auf FXML-Variablen eines anderen Controllers AWT, Swing, JavaFX & SWT 2
K Swing Inhalt eines JPanels lesen AWT, Swing, JavaFX & SWT 3
T Nur bestimmte Bereiche eines Fotos bearbeiten AWT, Swing, JavaFX & SWT 0
J Swing Erstellung eines User Interface AWT, Swing, JavaFX & SWT 2
S JavaFX Teil eines Bildes ausschneiden / als neues Bild nutzen AWT, Swing, JavaFX & SWT 8
R Swing Bewegung eines Graphics Objektes innerhalb eines JPanels funktioniert nicht richtig AWT, Swing, JavaFX & SWT 2
O Swing Aufbau eines JFrames AWT, Swing, JavaFX & SWT 2
A JavaFX Hilfe beim Design eines Quiz AWT, Swing, JavaFX & SWT 2
F Instanzierung einer inneren Klasse in Klasse eines anderen Packets AWT, Swing, JavaFX & SWT 3
A befüllen eines JTables mittels Methode AWT, Swing, JavaFX & SWT 10
javampir Swing Wanderung eines JFrames AWT, Swing, JavaFX & SWT 7
J Anfänger GUI Problem bei der Ausführung eines sehr einfachen Programms AWT, Swing, JavaFX & SWT 2
G Swing ComboBox: Auswahl eines Items der Liste durch Eingabe eines Buchstabens AWT, Swing, JavaFX & SWT 3
S Swing Nur den sichtbaren Bereich eines TextPane mit Inhalt darstellem AWT, Swing, JavaFX & SWT 0
I Erstellung eines kleinen Programmes AWT, Swing, JavaFX & SWT 8
H Position eines JLabel in einem JPanel AWT, Swing, JavaFX & SWT 2
J 2D-Grafik Windows Blue-Screen nach anzeigen eines Bildes in Java AWT, Swing, JavaFX & SWT 10
T Swing Einzelne Teile eines Textes färben? AWT, Swing, JavaFX & SWT 10
H Swing Probleme beim erstellen eines neuen Objektes durch einen Button AWT, Swing, JavaFX & SWT 10
HaukeG JavaFX JavaFX Resize und DragAndDrop eines Pane AWT, Swing, JavaFX & SWT 4
D 2D-Grafik Inhalt eines Graphics in anderes Graphics zeichnen.... AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben