Javafx Stylesheets all'interno del pacchetto Osgi
Domanda
Ho inserito "stili.css" nella radice del mio pacchetto, e ora cerca di capire come collegarlo nel codice.Il problema è che @ .getstylesheets (). ADD (_) prende una stringa e non URL, quindi tutti gli approcci che conosco stanno fallendo qui:
Prendi 1:
scene.getStylesheets().add("styles.css");
.
→
Nov 15, 2013 2:04:47 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
WARNING: Resource "styles.css" not found.
.
Prendi 2:
scene.getStylesheets().add(this.getClass().getResource("styles.css").toExternalForm());
.
→
NullPointerException
.
Take 3:
scene.getStylesheets().add(this.getClass().getClassLoader().getResource("styles.css").toExternalForm());
.
→
Nov 15, 2013 2:27:31 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
INFO: Could not load stylesheet: bundle://5.0:1/styles.css
.
Take 4:
scene.getStylesheets().add(myBundle.getEntry("styles.css").toExternalForm());
.
→
Nov 15, 2013 1:31:35 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
INFO: Could not load stylesheet: bundle://5.0:0/styles.css
.
Sto usando Felix-4.2.1 , Java-8 (Build 1.8.0-EA-B115) , JavaFX-8 (8.0.0-EA-B115) .
Soluzione
I Recentemente ho corso nello stesso errore / problemi del poster originale di questa domanda e sono riuscito a risolverlo senza apportare modifiche al CSS / FXML o estraendolo in un file temp. Lo sto postando qui perché non ho trovato una buona risposta online:
Nel mio caso la configurazione è stata:
Bundle0:
- .
- Someview.fxml con un percorso relativo Riferimento a un file CSS
- Somestyle.css con riferimenti relativi per percorso a immagini
- someimage.png
- resourcelooader.java (restituisce oggetti URL da file CSS e FXML)
Bundle1:
- .
- File JavaFX di base per caricare FXML con un caricatore FXML da Bundle0.
Il problema:
Tutte le immagini di riferimento CSS e CSS sembrano essere ignorate dal FXML, anche se ho impostato il cardLoader sul caricatore FXML. Ha funzionato solo se ho usato un percorso di file assoluto per il CSS e le immagini referenziate nel CSS. Questo non è quello che voglio.
La soluzione:
Ci sono 2 bug / problemi di progettazione in JAVAFX che vietano questa configurazione di lavorare con OSGI.
- .
- Caricamento del CSS da FXML
- Riferimento di immagini da un css
Per correggere il primo problema, è necessario disabilitare il file CSS binario in JAVAFX impostando la proprietà di sistema Binary.css su False. C'è un bug in Javafx (forse è già stato risolto?) Dove Javafx cerca di essere intelligente e cerca di trovare il file BSS, anche se dici CSS. Allega perché gli URL delle risorse OSGI hanno un schema 'bundle: //' dove non si aspetta uno schema. Soluzione:
- .
- -dbinary.css= false
Per fissare il secondo problema, è necessario impostare il cardLoader di contesto del thread sul cardLoader del pacchetto in cui si trovano le immagini CSS e quindi ripristinare il cardLoader di contesto del file thread. Il trucco è quello di farlo ogni volta che il CSS è interpretato da Javafx, che non è sempre quando ti aspetti che sia ...
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
try {
final ClassLoader resourcesClassLoader = Resourceloader.class.getClassLoader();
//needed for css
Thread.currentThread().setContextClassLoader(resourcesClassLoader);
this.primaryStage.show();
} finally {
Thread.currentThread().setContextClassLoader(tccl);
}
.
Sfortunatamente questa è la soluzione migliore con cui potrei trovare. Javafx non è stato realizzato con il caricatore di classe o in caso di iniezione di dipendenza, anche se quasi ogni applicazione aziendale utilizza tali funzionalità in qualche forma. : (
// Modifica Sembra che non sia necessario impostare il cardLoader di contesto del filo per accedere alle immagini dal CSS!
Altri suggerimenti
Il motivo per cui questo non funziona è spiegato qui: javafx jira rt-14177 . Poiché non è possibile utilizzare la "formazione esterna" di un ressource, l'ho copiato in un file temp leggendo direttamente il flusso di ingresso.
InputStream inputStream = MainApp.class.getResourceAsStream("/styles/styles.css");
File tempStyleSheetDest = File.createTempFile("javafx_stylesheet", "");
tempStyleSheetDest.deleteOnExit();
Files.copy(inputStream, tempStyleSheetDest.toPath(), StandardCopyOption.REPLACE_EXISTING);
scene.getStylesheets().add(tempStyleSheetDest.toURI().toString());
.
- .
- Assicurati di utilizzare il ClassLoader di una classe che ha accesso al pacchetto contenente il file CSS
- Se stai usando un percorso relativo, assicurati che CSS sia localizzato rispetto a quella confezione di classe
Ecco un esempio di come ho caricato un file CSS in drombller fx ( drombler fx è una piattaforma client ricca modulare per JAVAFX basata su OSGI e MAVEN(Pom-First) ):
qui: la classe Stylesheets è nello stesso pacchetto del file CSS.
Gettclass (). GetClassLoader (). Getresource (). Toexternalform ()?