# ClassCastException



## Goldfish (10. Okt 2012)

hey, ich machs ganz kurz. 

ich habe folgende Zeile


```
...
JPanel p = new JPanel();
...
```

in seltenen nicht reproduzierbaren Fällen, bekomm ich mit Verweis auf diese Zeile folgende Exception.
Wäre super, wenn jemand ne Ahnung hat, was das auslöst. Es macht mich wahnsinnig und ich hab keinen Anhaltspunkt...


```
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.awt.Font
	at javax.swing.plaf.nimbus.NimbusStyle.getFontForState(NimbusStyle.java:573)
	at javax.swing.plaf.synth.SynthStyle.installDefaults(SynthStyle.java:933)
	at javax.swing.plaf.nimbus.NimbusStyle.installDefaults(NimbusStyle.java:231)
	at javax.swing.plaf.synth.SynthStyle.installDefaults(SynthStyle.java:916)
	at javax.swing.plaf.synth.SynthLookAndFeel.updateStyle(SynthLookAndFeel.java:265)
	at javax.swing.plaf.synth.SynthPanelUI.updateStyle(SynthPanelUI.java:117)
	at javax.swing.plaf.synth.SynthPanelUI.installDefaults(SynthPanelUI.java:100)
	at javax.swing.plaf.basic.BasicPanelUI.installUI(BasicPanelUI.java:56)
	at javax.swing.plaf.synth.SynthPanelUI.installUI(SynthPanelUI.java:62)
	at javax.swing.JComponent.setUI(JComponent.java:664)
	at javax.swing.JPanel.setUI(JPanel.java:153)
	at javax.swing.JPanel.updateUI(JPanel.java:126)
	at javax.swing.JPanel.<init>(JPanel.java:86)
	at javax.swing.JPanel.<init>(JPanel.java:109)
	at javax.swing.JPanel.<init>(JPanel.java:117)
	at Gui.MoviePanelBig.getAudio(MoviePanelBig.java:460) <---- die oben angegebene Zeile
	at Gui.MoviePanelBig.getAudio(MoviePanelBig.java:433)
	at Gui.MoviePanelBig.getMiddlePart(MoviePanelBig.java:233)
	at Gui.MoviePanelBig.setRightPart(MoviePanelBig.java:217)
	at Gui.MoviePanelBig.<init>(MoviePanelBig.java:89)
	at Gui.Gui.getBigMovieFrame(Gui.java:313)
	at Gui.MoviePanelSmall.mousePressed(MoviePanelSmall.java:299)
	at java.awt.Component.processMouseEvent(Component.java:6502)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
	at java.awt.Component.processEvent(Component.java:6270)
	at java.awt.Container.processEvent(Container.java:2229)
	at java.awt.Component.dispatchEventImpl(Component.java:4861)
	at java.awt.Container.dispatchEventImpl(Container.java:2287)
	at java.awt.Component.dispatchEvent(Component.java:4687)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4489)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
	at java.awt.Container.dispatchEventImpl(Container.java:2273)
	at java.awt.Window.dispatchEventImpl(Window.java:2719)
	at java.awt.Component.dispatchEvent(Component.java:4687)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:703)
	at java.awt.EventQueue.access$000(EventQueue.java:102)
	at java.awt.EventQueue$3.run(EventQueue.java:662)
	at java.awt.EventQueue$3.run(EventQueue.java:660)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
	at java.awt.EventQueue$4.run(EventQueue.java:676)
	at java.awt.EventQueue$4.run(EventQueue.java:674)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:673)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)
```


----------



## Fant (10. Okt 2012)

Und was passiert z.B. in Zeile

89, 217, 233 und 433?



> at Gui.MoviePanelBig.getAudio(MoviePanelBig.java:460) <---- die oben angegebene Zeile
> at Gui.MoviePanelBig.getAudio(MoviePanelBig.java:433)
> at Gui.MoviePanelBig.getMiddlePart(MoviePanelBig.java:233)
> at Gui.MoviePanelBig.setRightPart(MoviePanelBig.java:217)
> at Gui.MoviePanelBig.<init>(MoviePanelBig.java:89)




deine zitierte Zeile ist so vollkommen aus dem Kontext gerissen zunächst mal natürlich nicht falsch. 

Ich glaub kaum, dass dir irgendwer helfen kann, wenn du nicht mehr dazu passenden Code postest ._.


----------



## Spacerat (10. Okt 2012)

Die Zeile ist sehr wahrscheinlich nicht mal der Auslöser, sondern das Nimbus L&F. Versuch's mal mit 'nem Standard L&F.
Bist im übrigen nichr der erste, der beim Nimbus 'ne unerklärliche CCE bekommt.


----------



## Goldfish (10. Okt 2012)

Also was die anderen Zeilen angeht, sind die ähnlich nichts sagend. Im Prinzip ist das ein Verlauf, der bis zu der Klasse zurückführt, wo die Methodenaufrufe beginnen. Und das beste ist, dass ich in dieser Klasse dann nicht einen einzigen Boolean bzw. Font von meiner Seite aus verwende. Über den gesamten Pfad nicht, der da angezeigt wird.

Aber angesichts dessen, was Spacerat sagt, scheint Nimbus entweder nen fiesen Bug zu haben, oder irgendwas von den Infos, wie mit dem Nimbusstyle umgegangen werden muss, ist nicht wirklich bekannt. Denn wie ich hinzu noch anmerken will, bekomme ich immer wieder eine derartige Exception und wie sich herausgestellt hat, auch immer Verweise auf andere Codeteile, wenn ich denn überhaupt mal Verweise auf meine Codeteile bekomme. manchmal gibt es nichtmal das und die Fehlerquelle scheint einzig und allein im Nimbus zu sein...

Ich will den Nimbus eigentlich nur ungern weglegen, da dies so ziemlich der einzige ist bei java, der mir wirklich gefällt...


----------



## xehpuk (11. Okt 2012)

ClassCastExceptions in Swing deuten immer darauf hin, dass man auf Swing-Komponenten außerhalb des EDT zugreift.


----------



## Goldfish (11. Okt 2012)

okay, das war definitiv hilfreich, aber folgendes.

das MainPanel, das ich verwende besteht aus einem JScrollPane, welches ein JPanel trägt, in welchem weitere diverse JPanels angelegt sind, auf welches ich regelmäßig zugreifen muss.
Mittels
System.out.println( javax.swing.SwingUtilities.isEventDispatchThread());
hab ich nachgesehen, und mir wird angegeben, dass sich das gute JScrollPane Objekt nicht im EDT befindet.
Was kann ich dagegen tun, dass ich hier Probleme mit Thread Zugriffen bekomme? Irgendwie muss man das doch safe machen können. Soll ich die entsprechenden Funktionen einfach auf synchronized setzen und damit ist es getan?


----------



## Spacerat (11. Okt 2012)

Also ich lese aus dem Stacktrace ganz konkret, dass die Exception im EDT nach einem simplen "new JPanel()" fliegt, was für mich in soweit unvorstellbar wäre. Die Instanzierung einer Komponente sollte eigentlich zu keiner Zeit eine solche werfen. Desegen erscheint mir ja auch besagter Nimbus so verdächtig, deswegen hätte ich erst mal ausprobiert, ob es evtl. mit dem Standard L&F funktioniert.


----------



## xehpuk (11. Okt 2012)

Spacerat hat gesagt.:


> Also ich lese aus dem Stacktrace ganz konkret, dass die Exception im EDT nach einem simplen "new JPanel()" fliegt, was für mich in soweit unvorstellbar wäre. Die Instanzierung einer Komponente sollte eigentlich zu keiner Zeit eine solche werfen. Desegen erscheint mir ja auch besagter Nimbus so verdächtig, deswegen hätte ich erst mal ausprobiert, ob es evtl. mit dem Standard L&F funktioniert.


Beim Aufruf eines Swing-Komponenten-Konstruktors passiert mehr, als man zuerst annehmen würde. Selbst wenn es mit einem anderen LaF funktionierte, wäre dies nur reines Glück. Da also lieber nichts dem Zufall überlassen.



Goldfish hat gesagt.:


> Mittels
> System.out.println( javax.swing.SwingUtilities.isEventDispatchThread());
> hab ich nachgesehen, und mir wird angegeben, dass sich das gute JScrollPane Objekt nicht im EDT befindet.


Das kann man so nicht sagen. Ein Objekt befindet sich in keinem speziellen Thread. Lediglich Variableninhalte können von verschiedenen Threads unterschiedlich gesehen werden.
Die Zeile zeigt nur, dass diese Stelle in der Methode nicht im EDT ausgeführt wird.



Goldfish hat gesagt.:


> Was kann ich dagegen tun, dass ich hier Probleme mit Thread Zugriffen bekomme? Irgendwie muss man das doch safe machen können.


Der goldene Code-Schnipsel lautet da immer:

```
SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        // hier auf die JPanels zugreifen
    }
});
```
Wenn du nicht weißt, wie du das am besten einbringen kannst, kannst du ja mal mehr Code zeigen und dann schauen wir weiter.



Goldfish hat gesagt.:


> Soll ich die entsprechenden Funktionen einfach auf synchronized setzen und damit ist es getan?


Das dürfte nichts bringen, weil der EDT dann weiterhin unsynchronisiert läuft.

Zum Schluss wie immer meine Empfehlung: Lesson: Concurrency in Swing (The Java™ Tutorials > Creating a GUI With JFC/Swing)


----------



## Spacerat (11. Okt 2012)

xehpuk hat gesagt.:


> Beim Aufruf eines Swing-Komponenten-Konstruktors passiert mehr, als man zuerst annehmen würde. Selbst wenn es mit einem anderen LaF funktionierte, wäre dies nur reines Glück. Da also lieber nichts dem Zufall überlassen.


Das gilt wohl nicht nur für Swing-Komponent-Konstutoren aber wenn etwas kommt, was man nicht erwartet, schaut man halt in den Quelltext.
In besagter Zeile wird z.B. versucht, ein Font aus einer Liste zu kramen, die möglicherweise erst ausserhalb des EDT initialisiert werden kann.
Auszug NimbusStyle:
[JAVA=564]    /**
     * @inheritDoc
     *
     * Overridden to cause this style to populate itself with data from
     * UIDefaults, if necessary. If a value named "font" is not found in
     * UIDefaults, then the "defaultFont" font in UIDefaults will be returned
     * instead.
     */
    @Override protected Font getFontForState(SynthContext ctx) {
        Font f = (Font)get(ctx, "font");
        if (f == null) f = UIManager.getFont("defaultFont");

        // Account for scale
        // The key "JComponent.sizeVariant" is used to match Apple's LAF
        String scaleKey = (String)ctx.getComponent().getClientProperty(
                "JComponent.sizeVariant");
        if (scaleKey != null){
            if (LARGE_KEY.equals(scaleKey)){
                f = f.deriveFont(Math.round(f.getSize2D()*LARGE_SCALE));
            } else if (SMALL_KEY.equals(scaleKey)){
                f = f.deriveFont(Math.round(f.getSize2D()*SMALL_SCALE));
            } else if (MINI_KEY.equals(scaleKey)){
                f = f.deriveFont(Math.round(f.getSize2D()*MINI_SCALE));
            }
        }
        return f;
    }[/code]Komischerweise ist Nimbus (neben Synth) der einzige Style, der diese "get()"-Methode aus SynthStyle überschreibt bzw. sogar das einzige, das eine eigene XXStyle-Klasse definiert. Da andere Klassen diese StyleKlasse nicht erweitern, muss "getFontForState()" auch nicht überschrieben und daraus folgend auch nichts gecasted werden. Ich bin mir relativ sicher, dass die Exception beim Verwenden eines anderen Styles (und das nicht nur zufällig) ausbleibt. Ob das dann noch etwas mit dem EDT oder Concurrency zu tun hat, wage ich mal zu bezweifeln.
1. ein uninitialisierter Font (null) wird abgefangen.
2. Boolean statt Font entspricht keiner Konvention, schon gar nicht als "uninitialisiert"-Signal.

Ergo: Ob nun EDT oder nicht, ein Boolean hat an dieser Stelle zu keiner Zeit etwas zu suchen.


----------



## Goldfish (11. Okt 2012)

Also was Code angeht, da hätte ich bspw. folgendes, wo ich annehme, dass dies vermutlich ebenfalls für eine der Exceptions verantwortlich ist.
Ich hab auch schon wieder ganz andere ClassCastExceptions bekommen. Die wechseln sich richtig gut ab.

Auf jeden Fall erstmal folgendes. Mit der Klasse hatte ich bereits einmal ein Problem und hatte sie schon gepostet gehabt, dieser konnte jedoch behoben werden ^^

Bei dieser Klasse handelt es sich um mein MainPanel. Ich hab versucht das ganze so zu halten, dass es sich selbst verwalten kann, da ich nicht ständig von außen drauf zugreifen wollte.
Die Stelle wo hier Daten ins Panel hinzugefügt bzw. gelöscht werden, werd ich versuchen gleich ganz deutlich zu markieren ^^


```
public class MainPanel extends JScrollPane{
    
    private SmallMoviePanelContainer movieContainer;
    
    public MainPanel(GridLayout lay){
        super();
        movieContainer = new SmallMoviePanelContainer(this);
        this.getViewport().add(movieContainer);
        
        this.setOpaque(false);
        this.getViewport().setOpaque(false);
        this.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        this.getVerticalScrollBar().setUnitIncrement(20);
    }
    
    public int getMovieCount(){
        return movieContainer.getComponentCount();
    }
      
    private static
    class SmallMoviePanelContainer extends JPanel implements PropertyChangeListener
                                                             //,ComponentListener
    {
        
        private int openPage = 0;
        private JScrollPane scroll;
        
        public SmallMoviePanelContainer(JScrollPane scroll){
            super();
            this.scroll = scroll;
            this.setLayout(new GridLayout(0,2));
            this.setOpaque(false);
            MainComponents.addMovieListener(this);
            this.addComponentListener(this);
        }
                
        @Override
        public void propertyChange(PropertyChangeEvent evt) {            
            switch (evt.getPropertyName()) {                
                case "added":
                    addMovie((Movie)evt.getNewValue(), (int)evt.getOldValue());
                    break;
                case "removed":
                    removeMovie((Movie)evt.getNewValue(), (int)evt.getOldValue());
                    break;
                case "newList":                    
                    fillPanel( (ArrayList<Movie>)evt.getNewValue(),
                               (int)evt.getOldValue());
                    break;
            }
        }
        
        private void addMovie(final Movie m, final int index){
            int page = index % MainComponents.SHOWN_MOVIES;
            int currentPage = StaticGuiComponents.getCurrentPage();
            if(currentPage == page || this.getComponentCount() < MainComponents.SHOWN_MOVIES){
                MoviePanelSmall mps = new MoviePanelSmall(m);
                if(this.getComponentCount() == MainComponents.SHOWN_MOVIES){
                    this.remove(this.getComponentCount()-1);
                    if(index != -1){
                        this.add(mps, index % MainComponents.SHOWN_MOVIES);
                    }else{
                        this.add(mps); //<--------------------------------------------------------------
                    }
                    MainComponents.showComponents();
                }else{
                    this.add(mps,index);//<------------------------------------------------------------
                }         
                int position = mps.getLocation().y;
                scroll.getVerticalScrollBar().setValue(position);
            }                
        }
        
        private void removeMovie(final Movie m, final int index){
            int removeIndex = index % MainComponents.SHOWN_MOVIES;
            this.remove(removeIndex); //<-----------------------------------------------------------
            
            int checkIndex = MainComponents.SHOWN_MOVIES - removeIndex;
            if(index-1+checkIndex < MainComponents.getMovieCount()){
                MoviePanelSmall mps = new MoviePanelSmall(
                                  MainComponents.getMovie(index+checkIndex-1));
                this.add(mps);//<---------------------------------------------------------------------
            }    
            MainComponents.showComponents();
        }
        
        private void fillPanel(final ArrayList<Movie> movies,
                               final int page){
            this.removeAll();
            Thread t = new Thread(){
              @Override
              public void run(){                  
                  for(int y = page*MainComponents.SHOWN_MOVIES; 
                                 y < (page*MainComponents.SHOWN_MOVIES)+
                                           MainComponents.SHOWN_MOVIES && 
                                 y < MainComponents.getMovieCount(); y++)
                  {
                      Movie m = movies.get(y);
                      addMovie(m,y);
                      MainComponents.showComponents();
                  }               
              }
            };
            t.start();                                            
        }
    } 
}
```

Also ich bin nicht sicher, aber kann hier ein entsprechendes Problem auftauchen?
mein MainPanel an sich ist in einem JTabbedPane untergebracht und hin und wieder werden auch ClassCastExceptions geworfen, wenn ich ein neues Objekt zum TabbedPane hinzufüge.

Das hier ist meine letzte Exception, die ich bekommen habe, als ich vorhin einen Tab hinzugefügt habe.

Die eine referenzierte Zeile hier aus meiner eigenen Klasse ist folgende:
super.paintComponent(g);


```
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.plaf.FontUIResource cannot be cast to javax.swing.Painter
	at javax.swing.plaf.nimbus.NimbusStyle.getBackgroundPainter(NimbusStyle.java:708)
	at javax.swing.plaf.nimbus.SynthPainterImpl.paintBackground(SynthPainterImpl.java:99)
	at javax.swing.plaf.nimbus.SynthPainterImpl.paintPanelBackground(SynthPainterImpl.java:957)
	at javax.swing.plaf.synth.SynthPanelUI.update(SynthPanelUI.java:155)
	at javax.swing.JComponent.paintComponent(JComponent.java:778)
	at Gui.Bild.paintComponent(Bild.java:60) <------------------------------------------------
	at javax.swing.JComponent.paint(JComponent.java:1054)
	at javax.swing.JComponent.paintChildren(JComponent.java:887)
	at javax.swing.JComponent.paint(JComponent.java:1063)
	at javax.swing.JComponent.paintChildren(JComponent.java:887)
	at javax.swing.JComponent.paint(JComponent.java:1063)
	at javax.swing.JComponent.paintChildren(JComponent.java:887)
	at javax.swing.JComponent.paint(JComponent.java:1063)
	at javax.swing.JComponent.paintChildren(JComponent.java:887)
	at javax.swing.JComponent.paint(JComponent.java:1063)
	at javax.swing.JComponent.paintChildren(JComponent.java:887)
	at javax.swing.JComponent.paint(JComponent.java:1063)
	at javax.swing.JComponent.paintChildren(JComponent.java:887)
	at javax.swing.JComponent.paint(JComponent.java:1063)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5221)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1482)
	at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1413)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1206)
	at javax.swing.JComponent._paintImmediately(JComponent.java:5169)
	at javax.swing.JComponent.paintImmediately(JComponent.java:4980)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:770)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:728)
	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:677)
	at javax.swing.RepaintManager.access$700(RepaintManager.java:59)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1621)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:701)
	at java.awt.EventQueue.access$000(EventQueue.java:102)
	at java.awt.EventQueue$3.run(EventQueue.java:662)
	at java.awt.EventQueue$3.run(EventQueue.java:660)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:671)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)
```


----------



## Spacerat (11. Okt 2012)

Viel muss man dazu wohl nicht mehr sagen, ausser dass Nimbus einen sehr suspekten Eindruck hinterlässt.
Erneut 'ne CCE und wieder in der Klasse NimbusStyle. Es wäre ratsam, wenn du das Ganze noch mal mit Ocean L&F (und allen anderen von mir aus auch) testest und wenn's dann funktioniert, nach liest, was man bei dem Nimbus L&F, welcher btw. noch relativ neu ist und offensichtlich einige Besonderheiten (Neuerungen) bietet, zu beachten hat.


----------



## xehpuk (12. Okt 2012)

Das wäre mir jetzt zu aufwendig, mich in die ganzen Swing-Interna einzulesen. Das Problem ist in meinen Augen offensichtlich.



Goldfish hat gesagt.:


> Also ich bin nicht sicher, aber kann hier ein entsprechendes Problem auftauchen?


Ja, natürlich. Du startest schließlich in 
	
	
	
	





```
fillPanel()
```
 (grundlos?) einen neuen Thread, mit dem du die Oberfläche stark bearbeitest. Diesen Code mal entfernt, dann siehts so aus:
[JAVA=87]        private void fillPanel(final ArrayList<Movie> movies,
                               final int page){
            this.removeAll();
            for(int y = page*MainComponents.SHOWN_MOVIES;
                           y < (page*MainComponents.SHOWN_MOVIES)+
                                     MainComponents.SHOWN_MOVIES &&
                           y < MainComponents.getMovieCount(); y++)
            {
                Movie m = movies.get(y);
                addMovie(m,y);
                MainComponents.showComponents();
            }
        }[/code]

Wenn es nach dieser Änderung weitere Probleme gibt, musst du mehr Stellen zeigen.


----------



## Goldfish (12. Okt 2012)

Diese Stelle an sich ist leider nicht verhandelbar, da die Anwendung sosnt etwa 30 Sekunden braucht, bis sie gestartet wird, da die Gui an sich sonst erst angezeigt wird, wenn diese Schleife durchgelaufen ist. Und auch vom Start abgesehen, wenn die Funktion wieder ausgelöst wird und kein Thread gestartet wird, ist die GUI für die Dauer der Schleife blockiert. Und das wollte ich halt nicht.

Aber derartige Fehler bekomme ich auch noch, wenn ich an anderen Stellen arbeite. Wie folgende. Diese wird per Mausdoppelklick ausgelöst auf ein internes Panel des MainPanels.

Kurz gesagt, wird hier nur ein neuer tab ins TabbedPane hinzugefügt, welcher zusätzlich einen closeButton enthält. Und unter der Voraussetzung, dass es sich hier um eine bestimmte Klasse handelt (MoviePanelBig), wird zusätzlich noch ein editButton mit hinzugefügt.

Ist im groben alles. Die Funktion befindet sich in einer Klasse, die sich von JTabbedPane ableitet und wie schon erwähnt, hier habe ich auch sehr häufig die Fehlermeldung, ohne dass irgendwo ein Thread gestartet wird.


```
private static int tabCount = -1;
    public void addNewTab(String title, JComponent mpb){
        tabCount++; 
        JPanel titlePanel = new JPanel();
        titlePanel.setLayout(new FlowLayout());
        titlePanel.setOpaque(false);
        titlePanel.add(new JLabel(title));

        if(mpb instanceof JScrollPane){
            JScrollPane scroll = (JScrollPane) mpb;
            if(scroll.getViewport().getComponent(0) instanceof MoviePanelBig){
                JButton editButton = new JButton();
                editButton.setIcon(LoadedImages.editButton);
                editButton.setName("editButton - "+tabCount);
                Dimension dim = new Dimension(32,28);
                editButton.setMaximumSize(dim);
                editButton.setPreferredSize(dim);
                editButton.setMinimumSize(dim);

                editButton.setToolTipText("Filmdaten bearbeiten");
                editButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JButton editButton = (JButton) e.getSource();
                        String[] parts = editButton.getName().split(" - ");                            
                        if(parts[0].equals("editButton")){
                            editButton.setIcon(LoadedImages.editButtonBack);
                            editButton.setName("editButtonBack - "+parts[1]);
                            MoviePanelBig mpb = getFromScrollPane((JComponent) 
                                getComponentAt(getTabComponentOnName(parts[1])));
                            mpb.changeEditable();
                        }else{
                            editButton.setIcon(LoadedImages.editButton);
                            editButton.setName("editButton - "+parts[1]);
                            MoviePanelBig mpb = getFromScrollPane((JComponent) 
                                getComponentAt(getTabComponentOnName(parts[1])));
                            mpb.changeEditable();
                        }
                    }
                });
                titlePanel.add(editButton);
            }
        }            

        JButton closeButton = new JButton("x");
        closeButton.setToolTipText("Tab schließen");
        closeButton.setName(tabCount+"");
        closeButton.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                JButton src = (JButton) e.getSource();
                remove(getTabComponentOnName(src.getName()));
            }                
        });
        titlePanel.add(closeButton);
        this.add(mpb,title);
        this.setTabComponentAt(this.getTabCount()-1, titlePanel);
        this.getTabComponentAt(this.getTabCount()-1).setName(tabCount+"");
        this.setSelectedIndex(this.getTabCount()-1);
    }
```


----------



## xehpuk (12. Okt 2012)

Goldfish hat gesagt.:


> Diese Stelle an sich ist leider nicht verhandelbar, da die Anwendung sosnt etwa 30 Sekunden braucht, bis sie gestartet wird, da die Gui an sich sonst erst angezeigt wird, wenn diese Schleife durchgelaufen ist. Und auch vom Start abgesehen, wenn die Funktion wieder ausgelöst wird und kein Thread gestartet wird, ist die GUI für die Dauer der Schleife blockiert.


Was genau dauert an dem Code denn so lang? Was macht 
	
	
	
	





```
MainComponents.showComponents()
```
?
Setze den Code dann in einen [JAPI]SwingWorker[/JAPI]: Worker Threads and SwingWorker (The Java™ Tutorials > Creating a GUI With JFC/Swing > Concurrency in Swing)

So in etwa:

```
private PanelFiller filler;

private void fillPanel(final ArrayList<Movie> movies, final int page) {
	if (filler != null) {
		filler.cancel(true);
	}
	this.removeAll();
	filler = new PanelFiller(movies, page);
	filler.execute();
}

private class PanelFiller extends SwingWorker<Void, Movie> {
	private final List<Movie> movies;
	private final int page;
	private int y;

	private PanelFiller(final List<Movie> movies, final int page) {
		this.movies = movies;
		this.page = page;
	}

	@Override
	protected Void doInBackground() throws Exception {
		final int sm = MainComponents.SHOWN_MOVIES;
		for (int y = page * sm, c = MainComponents.getMovieCount(); y < (page + 1) * sm && y < c; y++) {
			final Movie m = movies.get(y);
			publish(m);
		}
		return null;
	}
	
	@Override
	protected void process(final List<Movie> chunks) {
		for (final Movie m : chunks) {
			addMovie(m, y++);
		}
		MainComponents.showComponents();
	}
}
```



Goldfish hat gesagt.:


> Die Funktion befindet sich in einer Klasse, die sich von JTabbedPane ableitet und wie schon erwähnt, hier habe ich auch sehr häufig die Fehlermeldung, ohne dass irgendwo ein Thread gestartet wird.


Und du bist sicher, dass 
	
	
	
	





```
addNewTab()
```
 immer im EDT ausgeführt wird? Überprüf das mal.


----------



## X5-599 (12. Okt 2012)

Also laut den Stacktraces würde ich auch sagen, dass es am Nimbus liegt. Es wird immer auf eine Map zugegriffen. Und da kommt für den jeweiligen Key ein Value zurück das nicht erwartet wird (also kein Painter bzw. Font sondern Boolean bzw. FontUIResource).

Ich würde es ,wie schon vorgeschlagen wurde, einfach mal mit einem anderen LookAndFeel probieren. Wenn diese Fehler dann ausbleiben, weisst du mit Sicherheit, dass es am Nimbus lag. Bzw, an dem der die Maps packt.


----------



## xehpuk (12. Okt 2012)

Tjoa, handelt sich anscheinend um eine Race-Condition innerhalb des Nimbus-Codes, wenn man eben nicht alles im EDT macht. Dementsprechend kein Fehler von Nimbus, da Threadsicherheit ausdrücklich nicht gegeben ist. Ich finds sogar gut, dass man da Probleme bekommt, weil man nur so daraus lernen kann ("Hat mit anderen LaFs aber bisher auch funktioniert.", "Auf meiner Maschine läuft es aber." etc.).

Hier dann Beispielcode, der den Fehler provoziert:

```
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

public class NimbusTest implements Runnable {
	public static void main(final String... args) {
		Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Wahrscheinlichkeit für Race-Condition erhöhen
		SwingUtilities.invokeLater(new NimbusTest()); // läuft immer ohne Probleme
		new NimbusTest().run(); // sorgt oft für ClassCastExceptions und/oder Darstellungsfehler
	}
	
	private boolean setNimbus() {
		try {
			for (final LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
				if ("Nimbus".equals(info.getName())) {
					UIManager.setLookAndFeel(info.getClassName());
					return true;
				}
			}
		} catch (final Exception e) {}
		return false;
	}

	@Override
	public void run() {
		if (!setNimbus()) {
			return;
		}
		final JFrame f = new JFrame(Thread.currentThread().getName());
		final JPanel cp = new JPanel();
		final JButton[] l = new JButton[20];
		for (int i = 0; i < l.length; i++) {
			l[i] = new JButton();
			cp.add(l[i]);
		}
		f.setContentPane(cp);
		f.setSize(200, 200);
		f.setLocationRelativeTo(null);
		f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		f.setVisible(true);
		for (int i = 0; i < 100; i++) {
			for (int j = 0; j < l.length; j++) {
				new JPanel();
				l[j].setText(String.valueOf(i));
			}
		}
	}
}
```


----------



## Goldfish (12. Okt 2012)

nettes Beispiel ^^ habs ein paar mal ausprobiert und jedes mal entsprechende ClassCastExceptions bekommen.
Also ich hab es jetzt stumpf so gemacht, hab den Fehler aber mittlerweile dennoch wieder einmal bekommen. Daher hab ich so das Gefühl, dass ichs wohl doch noch nicht ganz begriffen hab...
Ich hab zuhause, wenn ich da denn mal wieder auftauchen sollte, noch ein Buch über Java liegen, wo dies bestimmt noch ausführlicher diskutiert wird. Immerhin ist das Buch über 1300 Seiten lang, da kann man das dann ja wohl auch erwarten. Ich hoffe, dass ich dann damit weiter komme.
Denn das hier hat leider noch nicht funktioniert... 


```
public static void createAndShowGUI(){
        DVD_Liste dvd_liste = new DVD_Liste();
    }
  
    public static void main(String[] args) {        
       SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
       });
    }
```


----------



## Goldfish (13. Okt 2012)

super, ich habs endlich begriffen ^^
Ich bin nicht sicher, ob das die feine Art ist, aber ich hab jetzt stumpf um die Felder, in denen ich Elemente ind er Gui hinzufüge oder entferne ein


```
EventQueue.invokeLater(new Runnable() {
                            @Override
                            public void run(){ 
                                ... 
                            }
                        });
```

rumgesetzt und der Fehler scheint auch nicht mehr aufzutauchen. Muss das ncoh weiter beobachten, aber ich denke das war sehr lehrreich ^^
Danke vielmals an alle ^^


----------

