Ładowanie zasobów: bezradność, złość, halucynacje

2

Stworzyłam sobie projekt JavaFX z Mavenem i mam problem z załadowaniem obrazka (i zasobów ogólnie). Oto struktura plików jaką sobie utowrzyłam:

screenshot-20220309195355.png

A to sposób w jaki odwołuję się do zasobu:

Image myImage = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/img/domek.jpg")));

A w rezultacie dostaję null - kompletnie nie rozumiem dlaczego! Przecież główną scenę ładuję w podobny sposób i nie ma takich problemów:

FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("/fxml/application.fxml"));

W czym rzecz?

2

@calineczka: ja w moim WinampEE korzystam z Guavy i mam:

  private static final Image EMPTY_CD_IMAGE = new Image(getResource("images/empty_cd.jpg").toString());

images to katalog w resourcas (czyli resources/images/empty_cd.jpg)
U mnie działa, getResource pochodzi z tej klasy

0

@scibi_92: Nope, jak ładuję w taki sposób, też dostaję nullptr.

0

@calineczka: czyli Guavą próbowałaś? Bez "/" na początku Stringa, dostajesz null string? Coś mi tu nie pasuje, Guava mówi że jak nie ma zasobu to powinna rzucić IllegalArgumentException

0

@scibi_92: Próbowałam tego: new Image(getResource("/img/domek.jpg").toString()); i tego new Image(getResource("img/domek.jpg").toString());
Bez '/' na początku nie mam żadnych szans na wczytanie czegokolwiek, przerabiałam to przez 2 godziny wczoraj. Nie mam pojęcia co to jest WimampEE (Winamp?) i Guava (jakaś biblioteka od google?) - chcę to zrobić na czystej JavieFX i Mavenie. Jeżeli się tego nie da zrobić bez zewnętrznych bibliotek, to oznacza że JavaFX jest skrajnie upośledzona i nieużywalna (co zaskakujące, bo korzystałam z AvaloniaUI i myślałam, ze gorzej już nie będzie...). ;/

0

ta metoda z guavy odwołuje się bezpośrednio do classloaderów

/**
 * Returns a {@code URL} pointing to {@code resourceName} if the resource is found using the
 * {@linkplain Thread#getContextClassLoader() context class loader}. In simple environments, the
 * context class loader will find resources from the class path. In environments where different
 * threads can have different class loaders, for example app servers, the context class loader
 * will typically have been set to an appropriate loader for the current thread.
 *
 * <p>In the unusual case where the context class loader is null, the class loader that loaded
 * this class ({@code Resources}) will be used instead.
 *
 * @throws IllegalArgumentException if the resource is not found
 */
@CanIgnoreReturnValue // being used to check if a resource exists
// TODO(cgdecker): maybe add a better way to check if a resource exists
// e.g. Optional<URL> tryGetResource or boolean resourceExists
public static URL getResource(String resourceName) {
  ClassLoader loader =
      MoreObjects.firstNonNull(
          Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader());
  URL url = loader.getResource(resourceName);
  checkArgument(url != null, "resource %s not found.", resourceName);
  return url;
}
1

Pomiń wiodący / i dodaj katalog resources do classpatha. Dalej null?

0

@calineczka:

Jeżeli się tego nie da zrobić bez zewnętrznych bibliotek, to oznacza że JavaFX jest skrajnie upośledzona i nieużywalna

wczytywanie zasobów z resourców to nie jest domena JavaFX.
Anyway, bez Guavy u mnie tez działa:

private static final Image EMPTY_CD_IMAGE = new Image(AlbumCoverController.class.getResource("/images/empty_cd.jpg").toString());

Z jakiego IDE korzystasz?

0

Znając życie problem leży w tym że fxml leży w katalogu /resouces/settings.fxml a this.getClass() ma ścieżkę zasobów w jakimś com/company/myapp bo pobierając getClass() odnosisz się do katalogu zasobów klasy a nie głównego katalogu resources.

IMHO Jak ma się kontroler w com.company.app to fxml powinno się trzymać w jakimś resources/com/company/app

0

https://mkyong.com/java/java-read-a-file-from-resources-folder/

W skrócie, może trzeba użyć classLoadera, tak jak w guavie, u Wibowita:

ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("/img/domek.jpg"));

Osobiście nie sprawdzałem.

1

Masz w ogóle te pliki w katalogu target/?

0

@scibi_92: Ah klasyka informatyków wszelkiej maści, "U mnie działa" :| IDE to IntelliJ IDEA 2021.3.3

@yarel: HA! Działa (wstępnie), ale jak usunę wiodącego / to się wysypuje - tak jak wspominałam, wczoraj straciłam 2 godziny na szukaniu dlaczego ta durnota nie chce mi załadować fxmla :|
W każdym razie, dziękuję ślicznie!

EDIT: Pytanie dlaczego - skoro ponoć katalogu resources/ nie było w classpath - udawało mi się wgrywać FXMLe znajdujące się w resources/fxml/...? 0_o

0

EDIT: Pytanie dlaczego - skoro ponoć katalogu resources/ nie było w classpath - udawało mi się wgrywać FXMLe znajdujące się w resources/fxml/...? 0_o

A ktoż to może wiedzieć. Zawsze możesz uruchomić debugger i zobaczyć jak wygląda wyszukiwanie resource i który classloader za to odpowiada.

Skąd wiadomo, że się udawało? Może FXMLLoader dostał nulla i go przęłknął? I jak się udawało, w IDE czy uruchamiając via maven?

1 użytkowników online, w tym zalogowanych: 0, gości: 1