java.awt.EventQueue & Look and Feel - Probleme (Swing threading rules?)

Klein0r

Erfahrenes Mitglied
Hallo zusammen,

ich wollte gerade eine Anwendung von mir mit nem anderen Look & Feel darstellen. Mache sowas zum ersten mal (mit einem Look & Feel was ich selbst einbinde) ;)

Also ich nutze: https://substance.dev.java.net/ (5.0 stable)

Einbinden wollte ich das L&F mit (Start.java):
Java:
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(new SubstanceBusinessBlackSteelLookAndFeel());
            JFrame.setDefaultLookAndFeelDecorated(true);
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
        
        new GUI();
    }

Leider bekomme ich so um die 100 Exceptions... (Auszug)
Code:
org.jvnet.substance.api.UiThreadingViolationException: Component creation must be done on Event Dispatch Thread
	at org.jvnet.substance.utils.SubstanceCoreUtilities.testComponentCreationThreadingViolation(SubstanceCoreUtilities.java:2312)
	at org.jvnet.substance.SubstancePanelUI.createUI(SubstancePanelUI.java:57)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at sun.reflect.misc.Trampoline.invoke(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
	at javax.swing.UIDefaults.getUI(Unknown Source)
	at javax.swing.UIManager.getUI(Unknown Source)
	at javax.swing.JPanel.updateUI(Unknown Source)
	at javax.swing.JPanel.<init>(Unknown Source)
	at javax.swing.JPanel.<init>(Unknown Source)
	at javax.swing.JPanel.<init>(Unknown Source)
	at javax.swing.JRootPane.createGlassPane(Unknown Source)
	at javax.swing.JRootPane.<init>(Unknown Source)
	at javax.swing.JFrame.createRootPane(Unknown Source)
	at javax.swing.JFrame.frameInit(Unknown Source)
	at javax.swing.JFrame.<init>(Unknown Source)
	at org.chessoe.gui.GUI.<init>(GUI.java:107)
	at org.chessoe.gui.Start.main(Start.java:34)
UIDefaults.getUI() failed: createUI() failed for javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=] java.lang.reflect.InvocationTargetException
java.lang.Error
	at javax.swing.UIDefaults.getUIError(Unknown Source)
	at javax.swing.MultiUIDefaults.getUIError(Unknown Source)
	at javax.swing.UIDefaults.getUI(Unknown Source)
	at javax.swing.UIManager.getUI(Unknown Source)
	at javax.swing.JPanel.updateUI(Unknown Source)
	at javax.swing.JPanel.<init>(Unknown Source)
	at javax.swing.JPanel.<init>(Unknown Source)
	at javax.swing.JPanel.<init>(Unknown Source)
	at javax.swing.JRootPane.createGlassPane(Unknown Source)
	at javax.swing.JRootPane.<init>(Unknown Source)
	at javax.swing.JFrame.createRootPane(Unknown Source)
	at javax.swing.JFrame.frameInit(Unknown Source)
	at javax.swing.JFrame.<init>(Unknown Source)
	at org.chessoe.gui.GUI.<init>(GUI.java:107)
	at org.chessoe.gui.Start.main(Start.java:34)

Zeile 107 aus der GUI.java setzt (im Standardkonstruktor) nur mit setTitle() den JFrame-Titel. Eigentlich sehr unspektakulär...

Jetzt habe ich schon ne ganze Weile Google bemüht und hab folgende Lösung gefunden (Start.java):
Java:
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(new SubstanceBusinessBlackSteelLookAndFeel());
                    JFrame.setDefaultLookAndFeelDecorated(true);
                } catch (UnsupportedLookAndFeelException e) {
                    e.printStackTrace();
                }
                
                new GUI();
            }
        });

Das ganze funktioniert schonmal soweit, dass meine Anwendung startet und nicht direkt mit 100 Exceptions stirbt - allerdings finde ich das eine sehr unschöne Lösung. Ich verstehe zwar überhaupt nicht was diese EventQueue ist, noch weiß ich warum das so gemacht werden muss.... Aber ich erkenne wohl das das ein Haufen Pfusch ist ;)
Und meine Anwendung stürzt immernoch ab, wenn ich aus einem dritten Thread ein JOptionPane öffne. Das kann ich aber unmöglich weg lassen!
Sonst läuft das ganze stabil ;)

Nach weiteren Google-Suchen habe ich dann jemanden mit dem selben Problem gefunden. Dazu meinte dann jemand:
The JTable is created on the thread you created in the constructor of your main class. It is a violation of Swing threading rules.
(Link: http://markmail.org/message/oioj4pgwqfe7pl5r#query:+page:1+mid:culzucst6nsza2zs+state:results )

Raff ich nicht - was genau meint der mit Swing threading rules Nie davon gehört...

Sollte man seine Oberfläche normalerweise in einem anderen Thread zeichnen als die Logik abläuft? Oder wie darf ich mir das vorstellen?
So wie ich das verstehe soll die Oberfläche nur in einem seperaten Thread gezeichnet werden.

Um das Problem zu lösen will ich meine Anwendung nun konform gestalten. Aber ich habe keine Ahnung wie ich da ansetzen soll - daher dieser Thread ;)

Bitte gebt mir ein paar hilfreiche Links oder Comments.
Evt hat sich ja zufällig von euch ja auch schon jemand mit Substance auseinander gesetzt.

lg
 
Zuletzt bearbeitet:
Zurück