Swing MutableComboBoxModel | Implementierung

Status
Nicht offen für weitere Antworten.

Dit_

Bekanntes Mitglied
Hallo

ich bräuchte Hilfe bei der Implementierung von MutableComboBoxModel .

ich habe bis jetzt immer so gemacht.
Java:
JComboBox box = new JComboBox();
box.setModel(new DefaultComboBoxModel(new String[]{"user_a","user_b","user_c"}));
usw.

jetzt aber soll folgendes passieren. Der Benutzer kann die Einträge hinzufügen bzw Löschen. Mein ComboBox soll die Daten nicht aus einem String nehmen sondern aus Registry. und zwar ich habe einen Knoten (zB User) in der Registry angelegt. Jeder Unterordner in dem Knoten entspricht einem Eintrag in dem ComboBox. (preferences.node("/User").childrenNames();)

Code:
Beispiel:
Prefs/User/user_a/
Prefs/User/user_b/
usw.
ComboBox hat 2 Einträge: user_a und user_b.

Hier im Forum hat man mir gesagt ich soll MutableComboBoxModel implementieren
so dass das Model das Hinzufügen und Löschen von Einträgen überwacht und ComboBox automatisch aktualisiert. So vermeide ich das hier:
Java:
//... hier wird Eintrag "user_c" geloescht...
//und dann neues Model gesetzt
box.setModel(new DefaultComboBoxModel(new String[]{"user_a","user_b"}));

Wie es ausieht ich muss dann später ganz normal JComboBox Objekt erstellen und dann als Model mein MutableComboBoxModel uebergeben.
-------------------

Also jetzt stehe ich aber auf dem Schlauch, denn wie soll ich MutableComboBoxModel implementieren? soweit bin ich gekommen, weiss nicht mehr weiter...

Java:
public class AuswahlBox extends AbstractListModel implements MutableComboBoxModel {
	
	/**
	 * Dies ist eine Referenz auf die ComboBox, die dieses Model verwendet.
	 */
	private JComboBox comboBox = null;
	
	
	/**
	 * Dies ist die Liste aller registrierter ListDataListenerS.
	 */
    private ArrayList<ListDataListener> listDataListeners = null;

    /**
     * Dies ist die Liste aller enthaltener Daten.
     */
    private ArrayList<String> daten = null;

    /**
     * Dieser Index speichert bezeichnet das gerade angezeigte Element.
     */
    private int auswahl = 0;

    
    
    public AuswahlBox() {
    	Register reg = new Register();
    	String[] server = reg.gebeKinder();
    	for(String x : server){
    		this.daten.add(x);
    	}
	}
	
    
    
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	
	
	@Override
	public void addElement(Object x) {
		
	}

	@Override
	public void insertElementAt(Object arg0, int arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void removeElement(Object arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void removeElementAt(int arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Object getSelectedItem() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setSelectedItem(Object arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Object getElementAt(int arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return 0;
	}
	
}

Kann jemand Paar Tipps geben ?
Danke schon mal :)
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Solange du die Frage nicht präzisierst: Die Methoden implementieren (Elemente in die List hinzufügen/entfernen, und jeweils mit fire*** die entsprechenden Events werfen....)
 

Dit_

Bekanntes Mitglied
ist es richtig dass ich hier ein JComboBox Objekt verwende? Wenn ja dann kann ich eigentlich ganz normal alle methoden implementieren und dann später mit getMethode ComboBox Objekt übergeben. :shock:
 

hdi

Top Contributor
Erstmal: Es ist kein gutes Design dass das Model seine View kennt. Also die Referenz auf die ComboBox sollte aus dem Model raus.

Ansonsten musst du dich halt im Model auf deine Daten beziehen, ich nehme mal an das ist die ArrayList<String> daten.

zB dann:
Java:
@Override
    public void insertElementAt(Object data, int i) {
             daten.add(i,data);
    }

Du musst dir halt in der API die beschreibung zu den Methoden durchlesen, und sie dann sinnig implementieren. Sinnig heißt: Du arbeitest intern im Model auf deiner ArrayList<String>.

Also noch ein Bsp:
Java:
  @Override
    public void removeElement(Object obj) {
        daten.remove(obj);
    }

usw

Und nochmal, zur Sicherheit:
ist es richtig dass ich hier ein JComboBox Objekt verwende?
Nein! Das Model setzt du einfach per setModel(new MyModel()) auf deine ComboBox, und zwar dort, wo du sie erstellst. Dem Model sollte es egal sein welche ComboBox(en) dieses Model verwendet.
 
Zuletzt bearbeitet:

Dit_

Bekanntes Mitglied
Ich hoffe das ist soweit stilistisch in Ordnung (abgesehen von deutschen Bezeichner... die umbenannt werden sobald die Klasse fertig ist :) )

Java:
public class AuswahlBoxModell extends AbstractListModel implements MutableComboBoxModel {
	

    /**
     * Dies ist die Liste aller enthaltener Daten.
     */
    private ArrayList<String> daten = null;

    /**
     * Dieser Index speichert bezeichnet das gerade angezeigte Element.
     */
    private int auswahl = 0;

    
    
    public AuswahlBox() {
    	holeDaten();
	}
	
    private void holeDaten(){
    	Register reg = new Register();
    	String[] server = reg.gebeServerNamen();//macht folgendes: "return pref.node(HAUPT_PFAD).childrenNames();"
    	daten = new ArrayList<String>();
    	for(String x : server){
    		this.daten.add(x);
    	}
    	
    	setSelectedItem(reg.gebeDefaultServer());
    }
	
    
	@Override
	public void addElement(Object x) {
		daten.add((String)x);
	}

	@Override
	public void insertElementAt(Object x, int index) {
		daten.add(index, (String)x);
	}

	@Override
	public void removeElement(Object x) {
		daten.remove(x);
	}

	@Override
	public void removeElementAt(int index) {
		daten.remove(index);
	}

	@Override
	public Object getSelectedItem() {
		return daten.get(auswahl);
	}

	@Override
	public void setSelectedItem(Object x) {
		//in den meinsten Faellen, daten.size() max 3.
		for (int i = 0; i< daten.size(); i++){
			if (daten.get(i).equals(x)){
				auswahl = i;
			}
		}
	}

	@Override
	public Object getElementAt(int index) {
		return daten.get(index);
	}

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

in meiner HauptGui Klasse mache ich dann folgendes:

Java:
//lade serverAuswahlBox
			{
				serverAuswahlBox = new JComboBox(new AuswahlBoxModell());
				//Listener hier???
				serverAuswahlBox.addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent arg0) {
						
					}
				});
			}

Wenn das alles stimmt, dann hätte ich noch eine Frage.

sobald der Benutzer in der Box ein Element auswaehlt, wird folgendes passieren.

1. Ein SteuerungsThread wird gestop (dieser steuert die Aktualisierung der GuiOberflächen und das Holen der Datagrampaketen von einem Server)
2. Der in der Box ausgewaehlte server wird als currentServer gesetzt.
Dieser wird an SteuerungsThread uebergeben.
3. Start des SteuerungsThreads.

Frage jetzt
Wo mache ich das alles? Ich brauche natürlich Listener, wo soll dieser sein in meiner HauptGui Klasse, denn nur diese kennt meinen SteuerungsThread oder doch in dem AuswahlBoxModell ?
 

hdi

Top Contributor
Eine kleine Anmerkung zu

Java:
@Override
    public void setSelectedItem(Object x) {
        //in den meinsten Faellen, daten.size() max 3.
        for (int i = 0; i< daten.size(); i++){
            if (daten.get(i).equals(x)){
                auswahl = i;
            }
        }
    }

Falls das Objekt null ist (keine Auswahl), wird dein auswahl-index nicht geändert. Das ist nicht gut. Besser:

Java:
@Override
    public void setSelectedItem(Object x) {
        //in den meinsten Faellen, daten.size() max 3.
        for (int i = 0; i< daten.size(); i++){
            if (daten.get(i).equals(x)){
                auswahl = i;
                break; // <- !
            }
        }
        auswahl = -1; // <- !
    }

Zu den anderen Fragen: Ich würde den ActionListener auf deiner Box tauschen gegen einen ItemChangeListener. Und in seine Methode schreibst du dann halt diesen Vorgang, den du beschrieben hast.

Wichtig: Falls die GUI während dieses Vorgangs nicht blockiert werden soll, musst du das ganze auf einem neuen Thread starten. Falls sie blockiert werden soll, wovon ich ausgehe (damit der User nicht mit einer neuen Selektion dazwischenfunken kann), kannst du den Code direkt in die Listener-Methode schreiben.
Falls das ganze länger dauert wäre es dann aber angebraucht dem User eine Meldung anzuzeigen.
 

hdi

Top Contributor
...Ach und nochwas: Du vergisst die entpsrechenden fire() Methoden zu verwenden.
Das solltest du tun nach einem Update der Daten, also nach add/remove und evtl change.

Kuck dir mal die fire()- Methoden des AbstractListModel an. zB:

Java:
@Override
    public void addElement(Object x) {
        daten.add((String)x);
        this.fireIntervalAdded(x, daten.size()-1,daten.size()-1);
    }
 
U

Unregistriert

Gast
Java:
@Override
    public void setSelectedItem(Object x) {
        //in den meinsten Faellen, daten.size() max 3.
        for (int i = 0; i< daten.size(); i++){
            if (daten.get(i).equals(x)){
                auswahl = i;
                break; // <- !
            }
        }
        auswahl = -1; // <- !
    }
Nur blöd, dass auswahl immer -1 wird mit dieser Methode. Nicht beabsichtigt, oder?
 

Dit_

Bekanntes Mitglied
Ok folgendes Problem, wenn ich in der Box etwas auswähle, kommt immer das gleiche als auswahlobjekt... (siehe Code)


Java:
public class AuswahlBoxModell extends AbstractListModel implements
		MutableComboBoxModel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 4084928491913716688L;

	/**
	 * Dies ist die Liste aller enthaltener Daten.
	 */
	private ArrayList<String> daten = null;

	/**
	 * Dieser Index speichert bezeichnet das gerade angezeigte Element.
	 */
	private int auswahl = 0;

	
	/**************************
	 * Konstruktor
	 *************************/
	public AuswahlBoxModell() {
		holeDaten();
	}

	/**
     * 
     */
	private void holeDaten() {
		Register reg = new Register();
		String[] server = reg.gebeServerNamen();// macht folgendes:
												// "return pref.node(HAUPT_PFAD).childrenNames();"
		daten = new ArrayList<String>();
		for (String x : server) {
			this.daten.add(x);
		}

		setSelectedItem(reg.gebeDefaultServer());
	}

	

	@Override
	public void addElement(Object x) {
		daten.add((String) x);
		fireIntervalAdded(this, daten.size()-1,daten.size()-1);
	}

	@Override
	public void insertElementAt(Object x, int index) {
		daten.add(index, (String) x);
		fireIntervalAdded(this, daten.size()-1,daten.size()-1);
	}

	@Override
	public void removeElement(Object x) {
		daten.remove(x);
		fireIntervalRemoved(this, daten.size()-1,daten.size()-1);
	}

	@Override
	public void removeElementAt(int index) {
		daten.remove(index);
		fireIntervalRemoved(this, daten.size()-1, daten.size()-1);
	}

	
	@Override
	public Object getSelectedItem() {
		return daten.get(auswahl);
	}

	
	
	@Override
	public void setSelectedItem(Object x) {
		System.out.println("SetSelectedItem " + (String) x);   //<-- Kommt immer das gleiche, egal was man auswaehlt
		// in den meinsten Faellen, daten.size() max 3.
		for (int i = 0; i < daten.size(); i++) {
			if (daten.get(i).equals(x)) {
				auswahl = i;
				return;
			}
		}
		auswahl = 0;
	}

	@Override
	public Object getElementAt(int index) {
		return daten.get(index);
	}

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

}

Löschen geht auch nicht :(

so mache ich das in HaupGui Klasse

Java:
...
				modell = new AuswahlBoxModell();
				serverAuswahlBox = new JComboBox(modell);
...
				final JButton loeschen = new JButton(Icons.LOESCHEN);
				loeschen.setToolTipText(ToolTips.SERVER_LOESCHEN);
				loeschen.addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent e) {
						modell.removeElement(serverAuswahlBox.getSelectedItem());
					
					}
				});
was ist denn daran falsch ?
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
S Swing JComboBox mit MutableComboBoxModel ist leer nach addItem AWT, Swing, JavaFX & SWT 4
Dit_ MutableComboBoxModel | Listener fehlt ? AWT, Swing, JavaFX & SWT 6
B JavaFX Verständnisfrage EventHandler<ActionEvent> Implementierung in meiner Klasse AWT, Swing, JavaFX & SWT 2
B Java FX In control.TreeCell-Implementierung Binding erzeugen AWT, Swing, JavaFX & SWT 0
H JTextArea - farbige Zeilen .. bitte um Vorschläge zur Implementierung AWT, Swing, JavaFX & SWT 1
S Swing SwingWorker - richtige Implementierung doInBackground() AWT, Swing, JavaFX & SWT 5
F Problem mit Implementierung von Kollisionsabfrage AWT, Swing, JavaFX & SWT 5
W Java AWT/GUI Implementierung gesucht AWT, Swing, JavaFX & SWT 3
M Implementierung der generalisierten Houghtranformation AWT, Swing, JavaFX & SWT 4
E Implementierung des Windows Rechners? AWT, Swing, JavaFX & SWT 7
N AWT seperate ActionHandler Implementierung AWT, Swing, JavaFX & SWT 2
hdi Swing Gemeinsame JTable-Implementierung AWT, Swing, JavaFX & SWT 23
E AWT Implementierung einer Anweisung in Methode ActionPerformed AWT, Swing, JavaFX & SWT 2
R JTable: Implementierung einer JTable in einer JScrollPane AWT, Swing, JavaFX & SWT 2
cowabunga1984 Implementierung von Graphics2D AWT, Swing, JavaFX & SWT 2
S Implementierung Java Swing HelloWorld - verständnisproblem AWT, Swing, JavaFX & SWT 3
M Implementierung einer Zusammenstellung (AWT) AWT, Swing, JavaFX & SWT 5

Ähnliche Java Themen


Oben