# List Listener



## musterrrmax (28. Aug 2018)

Hallo!
Vielleicht kann mir hier jemand helfen, wieso mein ActionListener nicht funktioniert. Er wird irgendwie gar nicht ausgeführt. Danke schon mal im Voraus 

```
private class MeinListSelectioner implements ListSelectionListener {
  @Override
  public void valueChanged(ListSelectionEvent e) {
   String s = oberfläche.getSelectedValue2();
   ListSelectionModel lsm = (ListSelectionModel) e.getSource();
   int firstIndex = e.getFirstIndex();
   int lastIndex = e.getLastIndex();
   if (lsm.isSelectionEmpty()) {

   } else {
    int minIndex = lsm.getMinSelectionIndex();
    int maxIndex = lsm.getMaxSelectionIndex();
    for (int i = minIndex; i <= maxIndex; i++) {
     if (lsm.isSelectedIndex(i)) {
      try {
       Runtime.getRuntime().exec("explorer.exe /select, C:\\EDD-Files" + s);
      } catch (IOException e1) {
       e1.printStackTrace();
      }
     }
    }
   }
```


----------



## Flown (28. Aug 2018)

Vielleicht nicht zur ListBox hinzugefügt?


----------



## mihe7 (28. Aug 2018)

Abgesehen davon solltest Du prüfen, ob der Wert noch geändert wird, d. h. am Anfang

```
if (e.getValueIsAdjusting()) {
    return;
}
```
einfügen.


----------



## musterrrmax (28. Aug 2018)

Flown hat gesagt.:


> Vielleicht nicht zur ListBox hinzugefügt?


Wie adde ich die Methode zu der JList?


----------



## Flown (28. Aug 2018)

https://docs.oracle.com/javase/10/d...ener(javax.swing.event.ListSelectionListener)


----------



## musterrrmax (28. Aug 2018)

Flown hat gesagt.:


> https://docs.oracle.com/javase/10/d...ener(javax.swing.event.ListSelectionListener)


Ich hab das so schon probiert

```
ausgabe.addListSelectionListener(new ListSelectionListener());
```
aber es funktioniert nicht


----------



## Flown (28. Aug 2018)

Wow. Wie wärs mit:

```
ausgabe.addListSelectionListener(new MeinListSelectioner());
```
?


----------



## musterrrmax (28. Aug 2018)

Flown hat gesagt.:


> Wow. Wie wärs mit:
> 
> ```
> ausgabe.addListSelectionListener(new MeinListSelectioner());
> ...


Schön wärs's. Die MeinListSelectioner() ist eine innere Klasse und in einem anderen Package


----------



## Flown (28. Aug 2018)

Dann verfügbar machen


----------



## mihe7 (28. Aug 2018)

Wenn Du MeinListSelectioner verwenden willst, *musst* Du eine Instanz davon erzeugen. D. h. Du musst schon dafür sorgen, dass dies auch möglich ist. (Nachtrag: möglich = Zugriff auf die Instanz)


----------



## musterrrmax (28. Aug 2018)

mihe7 hat gesagt.:


> Wenn Du MeinListSelectioner verwenden willst, *musst* Du eine Instanz davon erzeugen. D. h. Du musst schon dafür sorgen, dass dies auch möglich ist. (Nachtrag: möglich = Zugriff auf die Instanz)


Das ist mir schon klar, dass ich auf eine private Methode außerhalb der Klasse nicht zugreifen kann. Aber es reicht nicht, sie auf public zu setzen. Was müsste ich umändern?


----------



## mihe7 (28. Aug 2018)

musterrrmax hat gesagt.:


> Was müsste ich umändern?


Vermutlich Dein Design.


----------



## thet1983 (28. Aug 2018)

musterrrmax hat gesagt.:


> ListSelectionModel lsm = (ListSelectionModel) e.getSource();



du verwendest eine JList, warum solltest du hier das SelectionModel bekommen?
An dieser Stelle sollte eine Exception fliegen.

sollte doch zuerst eine JList sein oder?

```
JList<?> list = (JList<?>) e.getSource();
ListSelectionModel lsm = list.getListSelectionModel();
```


----------



## Robat (28. Aug 2018)

thet1983 hat gesagt.:


> du verwendest eine JList, warum solltest du hier das SelectionModel bekommen?
> An dieser Stelle sollte eine Exception fliegen.


Nein `getSource()` liefert in dem Moment das SelectionModel.



musterrrmax hat gesagt.:


> Das ist mir schon klar, dass ich auf eine private Methode außerhalb der Klasse nicht zugreifen kann. Aber es reicht nicht, sie auf public zu setzen.


Es geht auch nicht darum die Methode auf public zu setzen, sondern die innere Klasse, sodass du Zugriff auf diese Klasse bekommst


----------



## thet1983 (28. Aug 2018)

Wenn ich das nachbaue mit einer JList<String>

```
class MyListener implements ListSelectionListener {

        @Override
        public void valueChanged(ListSelectionEvent e) {
            if (e.getValueIsAdjusting())
                return;

            try{
                // FEHLER
                ListSelectionModel m = (ListSelectionModel)e.getSource();
            } catch (Exception e2) {
                System.err.println("Hier laufe ich in die: " + e2.getClass().getName());
            }


            JList<String> target = (JList<String>) e.getSource();
            ListSelectionModel m = target.getSelectionModel();
            String selected = target.getSelectedValue();
            System.out.println("Auswahl: " + selected);
        }
    }
```

dann laufe ich in eine ClassCastException


----------



## mihe7 (28. Aug 2018)

https://docs.oracle.com/javase/tutorial/uiswing/events/listselectionlistener.html


----------



## Flown (28. Aug 2018)

Bitte mal auf die Tabelle darunter achten unter getSource: https://docs.oracle.com/javase/tutorial/uiswing/events/listselectionlistener.html#listselectionevent



> Return the object that fired the event. If you register a list selection listener on a list directly, then the source for each event is the list. Otherwise, the source is the selection model.


----------



## musterrrmax (28. Aug 2018)

Robat hat gesagt.:


> Nein `getSource()` liefert in dem Moment das SelectionModel.
> 
> 
> Es geht auch nicht darum die Methode auf public zu setzen, sondern die innere Klasse, sodass du Zugriff auf diese Klasse bekommst


Kannst du mir konkret sagen, wie ich das umsetzen kann? Ich hatte mit inneren Klassen noch nicht viel am Hut und habe es so gelernt. Das Problem hatte ich noch nie


----------



## mihe7 (28. Aug 2018)

musterrrmax hat gesagt.:


> Kannst du mir konkret sagen, wie ich das umsetzen kann?


`public class ...`
Um ein Objekt von einer nicht-statischen, inneren Klasse zu erstellen, musst Du über ein Objekt der äußeren Klasse gehen, z. B.

```
public class A {
    public class B implements ListSelectionListener {...}
}

A a = new A();
ListSelectionListener listener = a.new B();
```

Stell doch mal Deinen Code hier rein, dann kann man sich den Spaß mal ansehen.


----------



## musterrrmax (28. Aug 2018)

mihe7 hat gesagt.:


> `public class ...`
> Um ein Objekt von einer nicht-statischen, inneren Klasse zu erstellen, musst Du über ein Objekt der äußeren Klasse gehen, z. B.
> 
> ```
> ...


Also ich habe eine Controller Klasse, mit dem ActionListener

```
public class Controller implements ActionListener {
    //konstruktor
    @Override
    public void actionPerformed(ActionEvent e) {
         // anderer Code
   }
 
private class MeinListSelectioner implements ListSelectionListener {
  @Override
  public void valueChanged(ListSelectionEvent e) {
   String s = oberfläche.getSelectedValue2();
   ListSelectionModel lsm = (ListSelectionModel) e.getSource();
   int firstIndex = e.getFirstIndex();
   int lastIndex = e.getLastIndex();
   if (lsm.isSelectionEmpty()) {
  
   } else {
    int minIndex = lsm.getMinSelectionIndex();
    int maxIndex = lsm.getMaxSelectionIndex();
    for (int i = minIndex; i <= maxIndex; i++) {
     if (lsm.isSelectedIndex(i)) {
      try {
       Runtime.getRuntime().exec("explorer.exe /select, C:\\EDD-Files" + s);
      } catch (IOException e1) {
       e1.printStackTrace();
      }
     }
    }
   }
  }
 }
```
Und dann noch eine Panel Klasse, in der ich eine JList<String> eben mit diesem ActionListener versehen möchte


----------



## Robat (28. Aug 2018)

@mihe7 hat dir doch gezeigt wie es aussehen muss.. mach MeinListSelectioner public ..


----------



## mihe7 (28. Aug 2018)

Und aus welchem Grund ist MeinListSelectioner eine innere Klasse?


----------



## musterrrmax (28. Aug 2018)

Robat hat gesagt.:


> @mihe7 hat dir doch gezeigt wie es aussehen muss.. mach MeinListSelectioner public ..


Genau so habe ich es auch probiert. Dann kommt aber dieser Fehler:

The method MeinListSelectioner(Controller.MeinListSelectioner) is undefined for the type JList<String>


----------



## musterrrmax (28. Aug 2018)

mihe7 hat gesagt.:


> Und aus welchem Grund ist MeinListSelectioner eine innere Klasse?


Ich habs so im Internet nachgelesen :') Lösungsvorschlag?


----------



## mihe7 (28. Aug 2018)

musterrrmax hat gesagt.:


> Lösungsvorschlag?


Pack das Teil in eine eigene Java-Datei.


----------



## musterrrmax (28. Aug 2018)

mihe7 hat gesagt.:


> Pack das Teil in eine eigene Java-Datei.


Das ist zu kompliziert, da ich nach MVC programmiere und alles irgendwie miteinander verknüpft ist


----------



## mihe7 (28. Aug 2018)

musterrrmax hat gesagt.:


> Das ist zu kompliziert, da ich nach MVC programmiere und alles irgendwie miteinander verknüpft ist


Wenn es zu kompliziert ist, dann bestimmt nicht, weil Du MVC anwendest, sondern weil Dein Design nicht gut ist.


----------



## musterrrmax (28. Aug 2018)

mihe7 hat gesagt.:


> Wenn es zu kompliziert ist, dann bestimmt nicht, weil Du MVC anwendest, sondern weil Dein Design nicht gut ist.


Naja schau. Wenn ich die Methode in eine neue Klasse haue, dann hab ich 2 Controller Klassen und kann somit nicht mehr auf die Methoden der Panel Klasse zugreifen weil ich kein zweites PanelObjekt initialisieren kann wie ich es in der Controller Klasse gemacht habe:

```
public class Controller implements ActionListener {
 private Oberfläche oberfläche; // Panel Klasse
 private Frameklasse frame;
 private Model model;

 public Controller() {
  oberfläche = new Oberfläche(this);
  frame = new Frameklasse("Test", oberfläche);
  model = new Model();
 }
}
```


----------



## musterrrmax (28. Aug 2018)

mihe7 hat gesagt.:


> Wenn es zu kompliziert ist, dann bestimmt nicht, weil Du MVC anwendest, sondern weil Dein Design nicht gut ist.


So

```
ausgabe.[U]MeinListSelectioner[/U](controller.new MeinListSelectioner());
```
rufe ich die Methode (inzwischen public auf) aber es kommt bei ausgabe der Fehler:"The method MeinListSelectioner(Controller.MeinListSelectioner) is undefined for the type JList<String>" (ausgabe ist eine Jlist<String>)


----------



## mihe7 (28. Aug 2018)

Mit den Code-Schnipseln kann man leider wenig anfangen. Allgemein: 
a) es gibt kaum einen Grund, die GUI-Klassen zu erweitern
b) Du kannst Objekte übergeben
c) Du kannst den Listener einer JList hinzufügen, dann bekommst Du diese als Quelle des Events.


----------



## mihe7 (28. Aug 2018)

musterrrmax hat gesagt.:


> dann hab ich 2 Controller Klassen


Ja, Du hast ja auch zwei Elemente 


musterrrmax hat gesagt.:


> kann somit nicht mehr auf die Methoden der Panel Klasse


Warum willst Du darauf zugreifen?


musterrrmax hat gesagt.:


> weil ich kein zweites PanelObjekt initialisieren kann


Musst Du auch nicht.


----------



## musterrrmax (28. Aug 2018)

mihe7 hat gesagt.:


> Warum willst Du darauf zugreifen?


Ich muss mir ja das ausgewählte Item aus der Liste holen. Dazu habe ich eine Methode, die das holt. Auf die kann ich dann aber nicht mehr zugreifen, weil keine Verknüpfung zu der Panel Klasse besteht


----------



## musterrrmax (28. Aug 2018)

mihe7 hat gesagt.:


> Musst Du auch nicht.


Was schreibe ich dann in den Konstruktor der 2. Controller Klasse?


----------



## mihe7 (28. Aug 2018)

musterrrmax hat gesagt.:


> Was schreibe ich dann in den Konstruktor der 2. Controller Klasse?


Wie soll ich Dir das sagen? Ich weiß ja nur, dass Du irgendwo eine JList (vermutlich) hast und einen ListSelectionListener hinzufügen willst. Außerdem, dass Du irgendeinen ActionListener hast.

Du könntest z. B.

```
public class MeinListSelectioner implements ListSelectionListener {
    @Override
    public void valueChanged(ListSelectionEvent e) {
        if (e.getValueIsAdjusting()) {
           return;
        }
        JList list = (JList) e.getSource();
        ...
    }
}
```
schreiben und MeinListSelectioner der JList hinzufügen. Das muss nicht die beste Lösung sein, aber ohne genauere Infos kann man Dir halt auch keine genauere Antwort geben.


----------



## musterrrmax (28. Aug 2018)

mihe7 hat gesagt.:


> Wie soll ich Dir das sagen? Ich weiß ja nur, dass Du irgendwo eine JList (vermutlich) hast und einen ListSelectionListener hinzufügen willst. Außerdem, dass Du irgendeinen ActionListener hast.
> 
> Du könntest z. B.
> 
> ...


Okay nochmal von neu, diesmal genaur.
Ich habe eine PanelKlasse, in der ich ein GUI erstelle. Auf dem Panel gibt es einen Button und eine JList<String>. Und in der PanelKlasse hab ich diese Methode

```
public String getSelectedValue2() {
   return ausgabe.getSelectedValue();
}
```
die schaut, welches der Elemente in der JList<String> (ein Attribut) angeklickt wurde. Diese Methode rufe ich in meiner ControllerKlasse mit oberfläche.getSelectedValue2(); auf, indem ich im Konstruktor der PanelKlasse ein Controller Objekt mitgebe

```
public Oberfläche(Controller controller) {
this.controller = controller;
```
und das im Konstruktor der ControllerKlasse mitgebe. Wenn ich aber jetzt die innere Klasse in eine neue Datei haue, hab ich dieses Panel Objekt nicht mehr im Konstrutor der neuen Klasse und kann nicht Panel.getSelectedValue2() machen. Und ich weiß nicht, wie ich diese Klassen miteinander verknüpfe. Und was in der Konstruktor kommt weiß ich auch nicht


----------



## Flown (28. Aug 2018)

musterrrmax hat gesagt.:


> oberfläche.getSelectedValue2()


Ist nicht nach MVC programmiert. Sobald du was anklickst, muss was am Model geändert werden und das Model aktualisiert die UI.


----------



## musterrrmax (28. Aug 2018)

Flown hat gesagt.:


> Ist nicht nach MVC programmiert. Sobald du was anklickst, muss was am Model geändert werden und das Model aktualisiert die UI.


Kann gut sein, dass es nicht das MVC ist, das man so kennt. Ich habe es in der Schule etwas komisch gelernt


----------



## mihe7 (28. Aug 2018)

MVC ist nichts anderes als Eingabe (C), Verarbeitung (M) und Ausgabe (V). Ein Listener übernimmt meist die Rolle des Controllers. Die GUI-Komponenten die Rolle der View und das Model musst Du zur Verfügung stellen. Bei MVC arbeitet man mit mehreren Models, Controllern und Views.



musterrrmax hat gesagt.:


> Wenn ich aber jetzt die innere Klasse in eine neue Datei haue, hab ich dieses Panel Objekt nicht mehr im Konstrutor der neuen Klasse und kann nicht Panel.getSelectedValue2() machen.


Wofür brauchst Du Panel, wenn Du die JList hast?


----------

