JList setSelectedvalue zerstört Liste

Jetzt aber brauch ich wirklich Hilfe, hab ein ganz komisches Problem

Ich hab die oben genannte Methode benutzt, um in meiner Liste das gerade abgespielte zu markieren, so und das klappt jetzt nicht.
Parameter waren die variable, die das Lied enthält sowie true.

Wenn ich dann aber starte, markiert er zwar das momentane Lied, aber macht die Liste total kaputt.

Hier maln Screen, wenn die Zeile auskommentiert ist:
http://puu.sh/4bDcs.png

Wenn ich sie nun jedoch wieder reinmache, schauts so aus:
http://puu.sh/4bDia.png
Man sieht an der Seite schon an der Scrollbar, warum da soviel Platz ist, wenn ich nun mit der Maus das nächste Lied anklicke, nach ewigem runterscrollen, oder er einfach aufs nächste Lied geht, schauts so aus:
http://puu.sh/4bDo5.png
Das ist bei insgesamt 4 Liedern, zwischendrin sind immer mal wieder welche zusammen, (http://puu.sh/4bDyz.png) bzw einige sind sogar garnicht mehr visuell wiederauffindbar, auch wenn sie abgespielt werden und auch angezeigt werden (oben bei momentanes Lied und unten die Länge). (Gerade läuft zum Beispiel eines, das ich nicht in der Liste finde…)

Hat jemand ne Idee, warum das so ist? Ich hab mal völlig keine Ahnung und logisch erklären lässt sich das mir auch nicht…

*** Edit ***

Warum kann ich nicht mehr bearbeiten?^^
Egal, hier mal die CodeZeile oben:
MusikPlayer.getINSTANCE().getMusikDateienListe().setSelectedValue(audioFile, true);

Wenn ich es über den Index mache mit dieses Zeile:
MusikPlayer.getINSTANCE().getMusikDateienListe().setSelectedIndex(MusikPlayer.getINSTANCE().getListModel().indexOf(audioFile));

schauts so aus:
http://puu.sh/4bHrW.png

Alsi hier ist alles gut, bis auf das letzte Lied, das wieder so verbuggt ist und eines zwischendrin, das nur halb zu sehen ist. Das war meine letzte Vermutung, das ganze iwie zu lösen…

PS: get MusikDateinenListe() gibt die Liste zurück und getListModel() das dazugehörige Model, falls wer fragen sollte.

Edit2: Aha, bearbeiten konnte ich nicht, aber nach nem Doppelpost wird automatisch editiert und ich kann wieder? Muss man nicht verstehen^^

*** Edit ***

So, aber ich hab ne andere Methode geschrieben, für nen „nächstes Lied“ Button. Da schauts so aus:

                    index = musikDateienListe.getSelectedIndex() + 1;
                    musikDateienListe.setSelectedIndex(index);
                    File file = (File) listModel.get(index);
                    Musik.getINSTANCE().setCanceled(false);
                    ListThread.getINSTANCE().setAudioFile(file);
                    ListThread.getINSTANCE().init();```
Und da ist die Liste korrekt und sobald ich auf ein Lied Doppelklicke, wird es auch abgespielt. Drück ich jetzt auf den Button spielt er das nächste Lied ab UND markiert dementsprechend das nächste.... Wenn ich dann aber sowas mache:
```public void setCurrentSongSelected(File audioFile) {
        index = listModel.indexOf(audioFile);
        musikDateienListe.setSelectedIndex(index);
    }```
bzw. So, wenn es von der Liste ausgewählt wurde, ist der Parameter true, sonst false:

``` public void setCurrentSongSelected(boolean list) {
        if (list) {
            index = musikDateienListe.getSelectedIndex();
            System.out.println(index);
            musikDateienListe.setSelectedIndex(index);
        } else {
            musikDateienListe.setSelectedIndex(0);
        }
    }```
Wenn ich dann von außen mit
```MusikPlayer.getINSTANCE().setCurrentSongSelected(false);``` Darauf zugreife, zerhackts mir wieder die Liste, ich bin echt ratlos Leute...

Was Du das so treibst hab ich nur zur Hälfte verstanden. Ich hatte noch nie Probleme mit JList bzw. deren setSelectedValue und da es bei Dir in einem Fall zu funktionieren scheint und in anderen Fällen wiederum nicht, liegt der Fehler höchstwahrscheinlich in Deinem Code. Verwendest Du selbstgeschriebene CellRenderer zur Darstellung der Listeneinträge? Hängen da irgendwelche ListSelectionListener oder ähnliches an der JList, die evtl. die List oder deren Model manipulieren? Ohne ein KSKB kann man da wohl nicht viel dazu sagen.

Im normal fall würd ich mal raten vl das setSelectedIndex oder das setSelectedValue in den EDT zu packen mit SwingUtilities.invokeLater

da passieren manchmal ganz seltsame sachen

Das mit dem EDT ist ein heißer Kandidat, wenn da schon „ListThread“ vorkommt…

Ansonsten könnten solche Fehler auch auftreten, wenn man AWT-Components (List, Panel…) verwendet, statt der Swing-Components (JList, JPanel…).

Und… nebenbei… versuch’ mal, den Code so umzuschreiben, dass nirgendwo mehr ‚getINSTANCE‘ vorkommt. (Da wird man um Nachdenken kaum drumrumkommen, aber das könnte man als Berufsrisiko bezeichnen :wink: )

Nein keine eigener CellRenderer, das einzige was an der Liste für ein Listener dranhängt, ist ein MouseListener, der einen Doppelklick registrieren soll

Und das mit dem in invokeLater reinpacken kann garnicht funzen, da die Liste beim start ja noch leer ist :slight_smile: Habs trz mal reingepackt, aber es zerhackts mir trz wenn ich dann nochmal von außen drauf zugreife. Ach und ListThread ist ne Klasse, in der ein neuer eigener Thread startet, in dem alles läuft, also ist das nicht weiter schlimm.

Und ich benutze schon die JList, also die aus Swing.

Und das mit getINSTANCE hab ich eingebaut, damit in jeder Klasse nurnoch 1 Methode und eine variable static ist, was mir im anderen Thread geraten wurde, da ich jedesmal auf selbe Zugreifen will. da wo nicht umbedingt auf etwas bestehendes zugegriffen werden soll, da hab ich überall ein new drin.

aber nochmal @_Michael : Was stimmt den an dem Code nicht? Wenn ich aus der Klasse, in der die GUI ist es so mache:

                    musikDateienListe.setSelectedIndex(index);```
Dann funzt es. Wenn ich aber eine Methode mache
```public void setCurrentSongSelected(boolean list) {
        if (list) {
            index = musikDateienListe.getSelectedIndex();
            System.out.println(index);
            musikDateienListe.setSelectedIndex(index);
        } else {
            musikDateienListe.setSelectedIndex(0);
        }
    }```
Und ich false übergebe mit
```MusikPlayer.getINSTANCE().setCurrentSongSelected(false);```
Dann zerhackts die Liste, das ist das was ich nicht verstehe

*** Edit ***

Neue Erkenntnis:

Wenn ichs mit false übergeb und starte, ist die Liste zerhackt. Schließe ich das Fenster und mache ohne irgendwas am Code zu verändern das Fenster neu auf, dann gehts, dann wieder nicht, dann wieder... Es wechselt also ab zwischen geht und geht nicht. Kann mir bitte das mal jemand erklären? Das gleiche wenn ich die AudioFile übergebe. Mir kommt das sehr mysteriös vor :P

[QUOTE=Schesam]
Und das mit dem in invokeLater reinpacken kann garnicht funzen, da die Liste beim start ja noch leer ist :slight_smile: Habs trz mal reingepackt, aber es zerhackts mir trz wenn ich dann nochmal von außen drauf zugreife. Ach und ListThread ist ne Klasse, in der ein neuer eigener Thread startet, in dem alles läuft, also ist das nicht weiter schlimm.[/QUOTE]

Doch, das ist eventuell (!) schlimm, und „invokeLater“ heißt nicht so viel wie „nach dem Mittagessen“, sondern „so bald wie möglich, aber bitteschön auf dem richtigen Thread“ :wink:

Swing ist single-threaded. ALLES, was das Aussehen einer Swing-Component verändert (oder vom Zustand einer Swing-Component abhängt) muss vom Event-Dispatch-Thread gemacht werden. Gib’ mal bei allen Stellen, wo z.B. setSelectedIndex aufgerufen wird, sowas aus wie
System.out.println(Thread.currentThread());
und schau’ was da so erscheint… (bisher ist das immernoch nur eine Vermutung, aber die einzig plausible, im Moment, für mich…)

Hab mal direkt in die Methode setCurrentSongSelected reingeschrieben, sowie an die im Moment einzige von außen zugreifbare Stelle.

Der erste, nachdem ich dann die setCUrrentSongSelected methode aufgerufen habe, kommt als Thread “Thread[Thread-3,6,main]” 2x raus (einmal von aufruf und einmal in der Methode direkt) Und das jedes mal wenn der Song zum nächsten wechselt. Wenn ich die setCurrent Methode in die invokeLater noch reinpacke mit false, dann kommt direkt am Anfang noch “Thread[AWT-EventQueue-0,6,main]” derhier.

Wenn ich noch getName() dranhänge gibt er bei ersten “AWT-EventQueue-0” und beim anderen dann “Thread-3”. Wo der Thread herkommt, frag mich nich, als ich mal debuggt hab um zu schauen, ob alle Threads korrekte namen haben, hab ich den nich auffinden können

Ich hatte auf eine … durchschaubarere Antwort gehofft, aber vielleicht liegt’s auch an mir oder der Uhrzeit. Jedenfalls sollten die setSelectedIndex nur vom AWT-EventEueue gemacht werden, unabhängig davon, ob das die Ursache für ein Problem ist.

Also in die Methode drumherum ein invokeLater? Aber hilft es zu wissen, dass wenn die Liste zerhackt ist und ich einen weiteren Ordner hinzufüge, das die Liste dann wieder normal ist?
Also ich füge nen Ordner hinzu --> zerhackt
Füge noch einen hinzu --> Liste wieder ok

Edit: das invokeLater in die Methode hat geholfen, nach 3 Versuchen 0 kaputte Listen.

Kannst du mir erklären warum ein äußerer Thread die Liste so zerhackt?

Bei den Details kann man in die Tiefe gehen, Uhrzeitbedingt nur kurz: Wenn mehrere Threads auf der Liste etwas verändern, ist undefiniert, in welchem Zustand sich die Liste gerade befindet. Nicht nur bei Swing und JList, auch wenn zwei Threads z.B. “gleichzeitig” sowas machen wie
Thread1: someArrayList.add(“x”);
Thread2: someArrayList.add(“x”); // genau im gleichen Moment
dann weiß man nicht, ob da nun 1 oder 2 Elemente in der Liste sind. Stichworte: Threads, Concurrency, Race Conditions, Swing Single Thread rule, EIN schnelles Ergebnis: http://www.cab.u-szeged.hu/WWW/java/tutorial/ui/swing/threads.html