Browse Source

the omdbAPI query is now in its own thread

pull/22/head
Jannik 4 years ago
parent
commit
b5256ddaa8
  1. 1
      .gitignore
  2. 78
      src/main/java/kellerkinder/HomeFlix/application/MainWindowController.java
  3. 69
      src/main/java/kellerkinder/HomeFlix/controller/DBController.java
  4. 124
      src/main/java/kellerkinder/HomeFlix/controller/OMDbAPIController.java
  5. 239
      src/main/java/kellerkinder/HomeFlix/controller/apiQuery.java
  6. 2
      src/main/resources/fxml/MainWindow.fxml

1
.gitignore vendored

@ -48,4 +48,5 @@ Temporary Items
config.xml
.directory
target/
apiKeys.json

78
src/main/java/kellerkinder/HomeFlix/application/MainWindowController.java

@ -94,8 +94,8 @@ import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.util.Duration;
import kellerkinder.HomeFlix.controller.DBController;
import kellerkinder.HomeFlix.controller.OMDbAPIController;
import kellerkinder.HomeFlix.controller.UpdateController;
import kellerkinder.HomeFlix.controller.apiQuery;
import kellerkinder.HomeFlix.datatypes.SourceDataType;
import kellerkinder.HomeFlix.datatypes.FilmTabelDataType;
@ -240,6 +240,7 @@ public class MainWindowController {
private String streamUrl;
private String ratingSortType;
private String local;
private String omdbAPIKey;
// text strings
private String errorPlay;
@ -250,7 +251,8 @@ public class MainWindowController {
public double size;
private int last;
private int selected;
private int indexTable;
private int indexList;
private int next;
private ResourceBundle bundle;
@ -272,8 +274,9 @@ public class MainWindowController {
private Properties props = new Properties();
private Main main;
private MainWindowController mainWindowController;
private UpdateController updateController;
private apiQuery ApiQuery;
private OMDbAPIController omdbAPIController;
private DBController dbController;
/**
@ -282,8 +285,9 @@ public class MainWindowController {
*/
void setMain(Main main) {
this.main = main;
mainWindowController = this;
dbController = new DBController(this.main, this);
ApiQuery = new apiQuery(this, dbController, this.main);
omdbAPIController = new OMDbAPIController(this, dbController, this.main);
}
void init() {
@ -310,11 +314,11 @@ public class MainWindowController {
filmsTreeTable.setShowRoot(false);
// write content into cell
columnTitle.setCellValueFactory(cellData -> cellData.getValue().getValue().titleProperty());
columnRating.setCellValueFactory(cellData -> cellData.getValue().getValue().imageProperty());
columnStreamUrl.setCellValueFactory(cellData -> cellData.getValue().getValue().streamUrlProperty());
columnTitle.setCellValueFactory(cellData -> cellData.getValue().getValue().titleProperty());
columnSeason.setCellValueFactory(cellData -> cellData.getValue().getValue().seasonProperty().asObject());
columnEpisode.setCellValueFactory(cellData -> cellData.getValue().getValue().episodeProperty().asObject());
columnRating.setCellValueFactory(cellData -> cellData.getValue().getValue().imageProperty());
// add columns to treeTableViewfilm
filmsTreeTable.getColumns().add(columnStreamUrl);
@ -322,7 +326,7 @@ public class MainWindowController {
filmsTreeTable.getColumns().add(columnRating);
filmsTreeTable.getColumns().add(columnSeason);
filmsTreeTable.getColumns().add(columnEpisode);
filmsTreeTable.getColumns().get(0).setVisible(false); //hide columnStreamUrl (column with file URL, important for opening a file/stream)
filmsTreeTable.getColumns().get(0).setVisible(false); //hide columnStreamUrl (important)
// context menu for treeTableViewfilm
filmsTreeTable.setContextMenu(menu);
@ -421,7 +425,7 @@ public class MainWindowController {
@Override
public void handle(ActionEvent event) {
dbController.like(streamUrl);
dbController.refresh(streamUrl, selected);
dbController.refresh(streamUrl, indexList);
refreshTable();
}
});
@ -430,7 +434,7 @@ public class MainWindowController {
@Override
public void handle(ActionEvent event) {
dbController.dislike(streamUrl);
dbController.refresh(streamUrl, selected);
dbController.refresh(streamUrl, indexList);
refreshTable();
}
});
@ -488,18 +492,25 @@ public class MainWindowController {
filmsTreeTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
@Override
public void changed(ObservableValue<?> observable, Object oldVal, Object newVal) {
// last = selected; //for auto-play
selected = filmsTreeTable.getSelectionModel().getSelectedIndex(); // get selected item
last = selected - 1;
next = selected + 1;
title = columnTitle.getCellData(selected); // get name of selected item
streamUrl = columnStreamUrl.getCellData(selected); // get file path of selected item
if (filmsList.get(selected).getCached() == true) {
indexTable = filmsTreeTable.getSelectionModel().getSelectedIndex(); // get selected item
indexList = filmsList.indexOf(filmsTreeTable.getSelectionModel().getSelectedItem().getValue());
last = indexTable - 1;
next = indexTable + 1;
title = columnTitle.getCellData(indexTable); // get name of selected item
streamUrl = columnStreamUrl.getCellData(indexTable); // get file path of selected item
System.out.println("index table: " + indexTable);
System.out.println("index list: " + indexList);
System.out.println(title);
if (filmsList.get(indexList).getCached()) {
LOGGER.info("loading from cache: " + title);
dbController.readCache(streamUrl);
} else {
ApiQuery.startQuery(title, streamUrl); // start api query
omdbAPIController = new OMDbAPIController(mainWindowController, dbController, main);
Thread omdbAPIThread = new Thread(omdbAPIController);
omdbAPIThread.setName("OMDbAPI");
omdbAPIThread.start();
}
}
});
@ -667,7 +678,7 @@ public class MainWindowController {
// refresh the selected child of the root node
private void refreshTable() {
filmRoot.getChildren().get(selected).setValue(filmsList.get(selected));
filmRoot.getChildren().get(indexTable).setValue(filmsList.get(indexList));
}
/**
@ -936,6 +947,15 @@ public class MainWindowController {
} catch (IOException e) {
LOGGER.error(errorSave, e);
}
// try loading the omdbAPI key
try {
File file = new File(getClass().getClassLoader().getResource("apiKeys.json").getFile());
JsonObject apiKeys = Json.parse(new FileReader(file)).asObject();
omdbAPIKey = apiKeys.getString("omdbAPIKey", "");
} catch (Exception e) {
LOGGER.error("Cloud not load the omdbAPI key. Please contact the developer!", e);
}
}
// if AutoUpdate, then check for updates
@ -976,6 +996,14 @@ public class MainWindowController {
return color;
}
public String getTitle() {
return title;
}
public String getStreamUrl() {
return streamUrl;
}
public void setSize(Double input) {
this.size = input;
}
@ -984,6 +1012,14 @@ public class MainWindowController {
return size;
}
public int getIndexTable() {
return indexTable;
}
public int getIndexList() {
return indexList;
}
public void setAutoUpdate(boolean input) {
this.autoUpdate = input;
}
@ -1008,6 +1044,10 @@ public class MainWindowController {
return local;
}
public String getOmdbAPIKey() {
return omdbAPIKey;
}
public ObservableList<FilmTabelDataType> getFilmsList() {
return filmsList;
}

69
src/main/java/kellerkinder/HomeFlix/controller/DBController.java

@ -215,6 +215,7 @@ public class DBController {
* @param index of the film in LocalFilms list
*/
public void refresh(String streamUrl, int index) {
// FIXME we need to refresh the entry in the table as well, else indexOf for indexList won't work
LOGGER.info("refresh ...");
try {
Statement stmt = connection.createStatement();
@ -446,6 +447,9 @@ public class DBController {
} catch (SQLException e) {
LOGGER.error("Ups! an error occured!", e);
}
// FIXME see fixme at refresh()
// refresh(streamUrl, mainWindowController.getIndexList());
}
/**
@ -475,36 +479,40 @@ public class DBController {
*/
void addCache( String streamUrl, String Title, String Year, String Rated, String Released, String Runtime, String Genre, String Director,
String Writer, String Actors, String Plot, String Language, String Country, String Awards, String Metascore, String imdbRating,
String Type, String imdbVotes, String imdbID, String Poster, String Response) throws SQLException{
PreparedStatement ps = connection.prepareStatement("insert into cache values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
LOGGER.info("adding to cache: " + Title);
ps.setString(1,streamUrl);
ps.setString(2,Title);
ps.setString(3,Year);
ps.setString(4,Rated);
ps.setString(5,Released);
ps.setString(6,Runtime);
ps.setString(7,Genre);
ps.setString(8,Director);
ps.setString(9,Writer);
ps.setString(10,Actors);
ps.setString(11,Plot);
ps.setString(12,Language);
ps.setString(13,Country);
ps.setString(14,Awards);
ps.setString(15,Metascore);
ps.setString(16,imdbRating);
ps.setString(17,imdbVotes);
ps.setString(18,imdbID);
ps.setString(19,Type);
ps.setString(20,Poster);
ps.setString(21,Response);
ps.addBatch();
ps.executeBatch();
connection.commit();
ps.close();
LOGGER.info("done!");
String Type, String imdbVotes, String imdbID, String Poster, String Response) {
try {
PreparedStatement ps = connection.prepareStatement("insert into cache values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
LOGGER.info("adding to cache: " + Title);
ps.setString(1,streamUrl);
ps.setString(2,Title);
ps.setString(3,Year);
ps.setString(4,Rated);
ps.setString(5,Released);
ps.setString(6,Runtime);
ps.setString(7,Genre);
ps.setString(8,Director);
ps.setString(9,Writer);
ps.setString(10,Actors);
ps.setString(11,Plot);
ps.setString(12,Language);
ps.setString(13,Country);
ps.setString(14,Awards);
ps.setString(15,Metascore);
ps.setString(16,imdbRating);
ps.setString(17,imdbVotes);
ps.setString(18,imdbID);
ps.setString(19,Type);
ps.setString(20,Poster);
ps.setString(21,Response);
ps.addBatch();
ps.executeBatch();
connection.commit();
ps.close();
LOGGER.info("done!");
} catch (Exception e) {
LOGGER.error(e);
}
}
/**
@ -567,7 +575,6 @@ public class DBController {
mainWindowController.getPosterImageView().setImage(new Image("resources/icons/close_black_2048x2048.png"));
LOGGER.error(e);
}
mainWindowController.getPosterImageView().setImage(im);
} catch (SQLException e) {
LOGGER.error("Ups! an error occured!", e);

124
src/main/java/kellerkinder/HomeFlix/controller/OMDbAPIController.java

@ -0,0 +1,124 @@
package kellerkinder.HomeFlix.controller;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import javafx.application.Platform;
import kellerkinder.HomeFlix.application.Main;
import kellerkinder.HomeFlix.application.MainWindowController;
public class OMDbAPIController implements Runnable {
private MainWindowController mainWindowController;
private DBController dbController;
private Main main;
private String[] responseString = new String[20];
private String URL = "https://www.omdbapi.com/?apikey=";
private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName());
public OMDbAPIController(MainWindowController mainWindowController, DBController dbController, Main main){
this.mainWindowController = mainWindowController;
this.dbController = dbController;
this.main = main;
}
@Override
public void run() {
String output = null;
String posterPath = null;
// get by title, TODO implement search
try {
URL apiUrl = new URL(URL + mainWindowController.getOmdbAPIKey() + "&t="
+ mainWindowController.getTitle().replace(" ", "%20"));
BufferedReader ina = new BufferedReader(new InputStreamReader(apiUrl.openStream()));
output = ina.readLine();
ina.close();
LOGGER.info("response from " + URL + " was valid");
LOGGER.info(output);
} catch (IOException e) {
LOGGER.error("error while making api request or reading response");
LOGGER.error("response from " + URL + " was: \n" + output, e);
return;
}
JsonObject object = Json.parse(output).asObject();
responseString[0] = object.getString("Title", "");
responseString[1] = object.getString("Year", "");
responseString[2] = object.getString("Rated", "");
responseString[3] = object.getString("Released", "");
responseString[4] = object.getString("Runtime", "");
responseString[5] = object.getString("Genre", "");
responseString[6] = object.getString("Director", "");
responseString[7] = object.getString("Writer", "");
responseString[8] = object.getString("Actors", "");
responseString[9] = object.getString("Plot", "");
responseString[10] = object.getString("Language", "");
responseString[11] = object.getString("Country", "");
responseString[12] = object.getString("Awards", "");
responseString[13] = object.getString("Metascore", "");
responseString[14] = object.getString("imdbRating", "");
responseString[15] = object.getString("Type", "");
responseString[16] = object.getString("imdbVotes", "");
responseString[17] = object.getString("imdbID", "");
responseString[18] = object.getString("Poster", "");
responseString[19] = object.getString("Response", "");
//resize the image to fit in the posterImageView and add it to the cache
try {
BufferedImage originalImage = ImageIO.read(new URL(responseString[18])); //change path to where file is located
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
BufferedImage resizeImagePNG = resizeImage(originalImage, type, 198, 297);
posterPath = main.getPosterCache() + "/" + mainWindowController.getTitle() + ".png";
ImageIO.write(resizeImagePNG, "png", new File(posterPath));
LOGGER.info("adding poster to cache: "+posterPath);
} catch (Exception e) {
LOGGER.error(e);
}
// adding strings to the cache
dbController.addCache(mainWindowController.getStreamUrl(), responseString[0], responseString[1],
responseString[2], responseString[3], responseString[4], responseString[5], responseString[6],
responseString[7], responseString[8], responseString[9], responseString[10], responseString[11],
responseString[12], responseString[13], responseString[14], responseString[15], responseString[16],
responseString[17], posterPath, responseString[19]);
dbController.setCached(mainWindowController.getStreamUrl());
// load data to the MainWindowController
Platform.runLater(() -> {
dbController.readCache(mainWindowController.getStreamUrl());
});
}
/**
* resize a image
* @param originalImage is the original image
* @param type of the original image
* @param IMG_WIDTH width to resize
* @param IMG_HEIGHT heigth to resize
* @return resized image
*/
private static BufferedImage resizeImage(BufferedImage originalImage, int type, int IMG_WIDTH, int IMG_HEIGHT) {
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
return resizedImage;
}
}

239
src/main/java/kellerkinder/HomeFlix/controller/apiQuery.java

@ -1,239 +0,0 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2018 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package kellerkinder.HomeFlix.controller;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Scanner;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import javafx.scene.image.Image;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import kellerkinder.HomeFlix.application.Main;
import kellerkinder.HomeFlix.application.MainWindowController;
public class apiQuery{
public apiQuery(MainWindowController m, DBController db, Main main){
mainWindowController=m;
dbController=db;
this.main = main;
}
private MainWindowController mainWindowController;
private DBController dbController;
private Main main;
private Image im;
private String[] responseString = new String[20];
private String posterCache;
private String apiURL = "https://www.omdbapi.com/?apikey=";
private String apiKey = "";
ArrayList<Text> responseText = new ArrayList<Text>();
ArrayList<Text> nameText = new ArrayList<Text>();
private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName());
/**
* apiQuery for Project HomeFlix, sends a query to the omdb api
*/
public void startQuery(String title, String streamUrl){
URL queryURL = null;
Scanner sc = null;
String moviename = null;
String retdata = null;
String posterPath = null;
InputStream is = null;
BufferedReader br = null;
String fontFamily = main.getFONT_FAMILY();
posterCache = main.getPosterCache().toString();
int fontSize = (int) Math.round(mainWindowController.size);
responseText.removeAll(responseText);
nameText.removeAll(nameText);
try {
//get film title
sc = new Scanner(System.in);
moviename = title;
// in case of no or "" Film title
if (moviename == null || moviename.equals("")) {
LOGGER.warn("No movie found");
}
//remove unwanted blank
moviename = moviename.trim();
//replace blank with +
moviename = moviename.replace(" ", "+");
//queryURL is apiURL and additional parameters, response-types: http,json,xml (must be json, since the response is processed with minimal-json )
queryURL = new URL(apiURL + apiKey + "&t=" + moviename + "&plot=full&r=json");
is = queryURL.openStream();
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
//read data from response Stream
while ((retdata = br.readLine()) != null) {
//cut the json response into separate strings
LOGGER.info(retdata);
JsonObject object = Json.parse(retdata).asObject();
responseString[0] = object.getString("Title", "");
responseString[1] = object.getString("Year", "");
responseString[2] = object.getString("Rated", "");
responseString[3] = object.getString("Released", "");
responseString[4] = object.getString("Runtime", "");
responseString[5] = object.getString("Genre", "");
responseString[6] = object.getString("Director", "");
responseString[7] = object.getString("Writer", "");
responseString[8] = object.getString("Actors", "");
responseString[9] = object.getString("Plot", "");
responseString[10] = object.getString("Language", "");
responseString[11] = object.getString("Country", "");
responseString[12] = object.getString("Awards", "");
responseString[13] = object.getString("Metascore", "");
responseString[14] = object.getString("imdbRating", "");
responseString[15] = object.getString("Type", "");
responseString[16] = object.getString("imdbVotes", "");
responseString[17] = object.getString("imdbID", "");
responseString[18] = object.getString("Poster", "");
responseString[19] = object.getString("Response", "");
//adding poster to cache
BufferedImage originalImage = ImageIO.read(new URL(responseString[18]));//change path to where file is located
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
BufferedImage resizeImagePNG = resizeImage(originalImage, type, 198, 297);
if (System.getProperty("os.name").equals("Linux")) {
posterPath = posterCache+"/"+title+".png";
ImageIO.write(resizeImagePNG, "png", new File(posterCache+"/"+title+".png")); //change path where you want it saved
} else {
ImageIO.write(resizeImagePNG, "png", new File(posterCache+"\\"+title+".png")); //change path where you want it saved
posterPath = posterCache+"\\"+title+".png";
}
LOGGER.info("adding poster to cache: "+posterPath);
//adding strings to the cache
dbController.addCache( streamUrl, responseString[0], responseString[1],responseString[2], responseString[3], responseString[4], responseString[5],
responseString[6], responseString[7], responseString[8], responseString[9], responseString[10],responseString[11], responseString[12],
responseString[13], responseString[14], responseString[15], responseString[16], responseString[17], posterPath,
responseString[19]);
dbController.setCached(streamUrl);
for (int i = 0; i < 20; i++) {
Text text = new Text(responseString[i] + "\n");
responseText.add(text);
responseText.get(i).setFont(Font.font(fontFamily, fontSize));
}
// if response == false then show mainWindowController.noFilmFound else create new Texts and add them to flowText
if (retdata.contains("\"Response\":\"False\"")) { // TODO + FIXME
mainWindowController.getTextFlow().getChildren().add(new Text(mainWindowController.getBundle().getString("noFilmFound")));
im = new Image("resources/icons/close_black_2048x2048.png");
mainWindowController.getPosterImageView().setImage(im);
} else {
nameText.add(0, new Text(mainWindowController.getBundle().getString("title") + ": "));
nameText.add(1, new Text(mainWindowController.getBundle().getString("year") + ": "));
nameText.add(2, new Text(mainWindowController.getBundle().getString("rating") + ": "));
nameText.add(3, new Text(mainWindowController.getBundle().getString("publishedOn") + ": "));
nameText.add(4, new Text(mainWindowController.getBundle().getString("duration") + ": "));
nameText.add(5, new Text(mainWindowController.getBundle().getString("genre") + ": "));
nameText.add(6, new Text(mainWindowController.getBundle().getString("director") + ": "));
nameText.add(7, new Text(mainWindowController.getBundle().getString("writer") + ": "));
nameText.add(8, new Text(mainWindowController.getBundle().getString("actors") + ": "));
nameText.add(9, new Text(mainWindowController.getBundle().getString("plot") + ": "));
nameText.add(10, new Text(mainWindowController.getBundle().getString("language") + ": "));
nameText.add(11, new Text(mainWindowController.getBundle().getString("country") + ": "));
nameText.add(12, new Text(mainWindowController.getBundle().getString("awards") + ": "));
nameText.add(13, new Text(mainWindowController.getBundle().getString("metascore") + ": "));
nameText.add(14, new Text(mainWindowController.getBundle().getString("imdbRating") + ": "));
nameText.add(15, new Text(mainWindowController.getBundle().getString("type") + ": "));
for (int i = 0; i < nameText.size(); i++) {
nameText.get(i).setFont(Font.font(fontFamily, FontWeight.BOLD, fontSize));
}
mainWindowController.getTextFlow().getChildren().remove(0,
mainWindowController.getTextFlow().getChildren().size());
for (int i = 0; i < nameText.size(); i++) {
mainWindowController.getTextFlow().getChildren().addAll(nameText.get(i), responseText.get(i));
}
// if there is no poster
if (responseString[18].equals("N/A")) {
im = new Image("resources/icons/close_black_2048x2048.png");
} else {
im = new Image(responseString[18]);
}
mainWindowController.getPosterImageView().setImage(im);
}
}
} catch (Exception e) {
mainWindowController.getTextFlow().getChildren().remove(0, mainWindowController.getTextFlow().getChildren().size());
mainWindowController.getTextFlow().getChildren().add(new Text(e.toString()));
LOGGER.error(e);
} finally {
//closes datainputStream, InputStream,Scanner if not already done
try {
if (br != null) {
br.close();
}
if (is != null) {
is.close();
}
if (sc != null) {
sc.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static BufferedImage resizeImage(BufferedImage originalImage, int type, int IMG_WIDTH, int IMG_HEIGHT) {
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
return resizedImage;
}
}

2
src/main/resources/fxml/MainWindow.fxml

@ -42,7 +42,7 @@
<font>
<Font name="Arial" size="12.0" />
</font></JFXTextField>
<ImageView fx:id="image1" fitHeight="297.0" fitWidth="198.0" layoutX="481.0" layoutY="46.0" pickOnBounds="true" preserveRatio="true" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="44.0">
<ImageView fx:id="posterImageView" fitHeight="297.0" fitWidth="198.0" layoutX="481.0" layoutY="46.0" pickOnBounds="true" preserveRatio="true" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="44.0">
<image>
<Image url="@../icons/Homeflix_Poster.png" />
</image></ImageView>

Loading…
Cancel
Save

Du besuchst diese Seite mit einem veralteten IPv4-Internetzugang. Möglicherweise treten in Zukunft Probleme mit der Erreichbarkeit und Performance auf. Bitte frage deinen Internetanbieter oder Netzwerkadministrator nach IPv6-Unterstützung.
You are visiting this site with an outdated IPv4 internet access. You may experience problems with accessibility and performance in the future. Please ask your ISP or network administrator for IPv6 support.
Weitere Infos | More Information
Klicke zum schließen | Click to close