Blurry Pdf after zooming - javafx

I have a pdf reader developped using Apache PdfBox, my problem is that i have a blurry image after zooming , this problem is only with PDF even if the resolution is very good of the pdf file.
this code working good with png or jpg files, but the problem still with pdf files, i'am really confused, i search on google but i found some solutions that are not complete.
Controller
package application;
import java.nio.file.Paths;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.fxml.FXML;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
public class Controller {
String imagePath = "C:\\Users\\piratack007\\Desktop\\1.jpg";
private ImageView imageView = new ImageView();
String path="C:\\Users\\piratack007\\Desktop\\file.pdf";
private PdfModel model= new PdfModel(Paths.get(path));
private ScrollPane scrollPane = new ScrollPane();
private DoubleProperty zoom = new SimpleDoubleProperty(1.1);
private PageDimensions currentPageDimensions ;
#FXML private VBox vbox;
String cssLayout = "-fx-border-color: red;\n" +
"-fx-border-insets: 5;\n" +
"-fx-border-width: 3;\n" +
"-fx-border-style: dashed;\n";
String scrollCssLayout= "-fx-border-color: green;\n" +
"-fx-border-insets: 5;\n" +
"-fx-border-width: 3;\n" +
"-fx-border-style: dashed;\n"+
//Ne pas afficher le petit trait gris
"-fx-background-color:transparent";
public void initialize() {
afficheImage();
}
void afficheImage() {
/*try {
imageView = new ImageView(new Image(new FileInputStream(imagePath)));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
//loading the first page
imageView = new ImageView(model.getImage(0));
System.out.print("1-imageView.getFitHeight(): "+imageView.getImage().getHeight()+"\n");
System.out.print("imageView.getFitWidth(): "+imageView.getImage().getWidth()+"\n");
currentPageDimensions = new PageDimensions(imageView.getImage().getWidth(), imageView.getImage().getHeight());
zoom.addListener(new InvalidationListener() {
#Override
public void invalidated(Observable arg0) {
//My problem is in this part of code
int width = (int) (imageView.getImage().getWidth() * zoom.get());
int height = (int) (imageView.getImage().getHeight() * zoom.get());
imageView.setFitWidth(width);
System.out.print("Largeur: "+ (width) +"px\n");
imageView.setFitHeight(height);
System.out.print("Hauteur: "+ height +"px\n");
//==================================================
}
});
imageView.preserveRatioProperty().set(true);
scrollPane.setPannable(true);
scrollPane.setStyle(scrollCssLayout);
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setContent(imageView);
vbox.setStyle(cssLayout);
vbox.getChildren().add(scrollPane);
}
#FXML private void zoomIn() {
zoom.set(zoom.get()*1.1);
// System.out.print("zoom.get(): "+zoom.get()*100 +"%\n");
}
#FXML private void zoomOut() {
zoom.set(zoom.get()/1.1);
// System.out.print("zoom.get(): "+zoom.get()*100 +"%\n");
}
#FXML private void zoomFit() {
}
#FXML private void zoomWidth() {
}
private class PageDimensions {
private double width ;
private double height ;
PageDimensions(double width, double height) {
this.width = width ;
this.height = height ;
}
#Override
public String toString() {
return String.format("[%.1f, %.1f]", width, height);
}
}
}
PdfModel
package application;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.rendering.PDFRenderer;
/**
* #author toru
*/
class PdfModel {
//private static final Logger logger = Logger.getLogger(PdfModel.class.getName());
private PDDocument document;
private PDFRenderer renderer;
Path chemin;
PdfModel() {
}
PdfModel(Path path) {
try {
chemin=path;
document = PDDocument.load(path.toFile());
renderer = new PDFRenderer(document);
} catch (IOException ex) {
throw new UncheckedIOException("PDDocument thorws IOException file=" + path, ex);
}
}
int nombreDePages() {
return document.getPages().getCount();
}
PDPage getPage (int num) {
PDPage page = document.getPage(num);
return page;
}
void fermer() {
try {
document.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void setPath(Path pPays)
{
chemin = pPays;
System.out.println("On est dans la page pdfmodel");
System.out.println("Path: "+pPays);
}
Image getImage(int pageNumber) {
BufferedImage pageImage;
try {
pageImage = renderer.renderImage(pageNumber);
} catch (IOException ex) {
throw new UncheckedIOException("PDFRenderer throws IOException", ex);
}
return SwingFXUtils.toFXImage(pageImage, null);
}
}
ui.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="10.0" minWidth="10.0" prefHeight="400.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<bottom>
<HBox prefHeight="50.0" prefWidth="400.0" BorderPane.alignment="CENTER">
<children>
<Button mnemonicParsing="false" onAction="#zoomIn" text="+">
<HBox.margin>
<Insets left="5.0" top="5.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" onAction="#zoomOut" text="-">
<HBox.margin>
<Insets left="5.0" top="5.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" onAction="#zoomFit" text="ZoomFit">
<HBox.margin>
<Insets left="5.0" top="5.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" onAction="#zoomWidth" text="ZoomWidth">
<HBox.margin>
<Insets left="5.0" top="5.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</bottom>
<center>
<VBox fx:id="vbox" prefHeight="350.0" prefWidth="400.0" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
Main.java
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*#author toru
*/
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final Parent parent = FXMLLoader.load(getClass().getResource("ui.fxml"));
primaryStage.setTitle("Zoom ImageView Demo ");
primaryStage.setScene(new Scene(parent,800, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Best regards

Use the two-parameter renderImage(page, scale) method. 1 is the default scale and is 72 dpi, 4 is 288 dpi which is usually pretty good. So I suggest you start with scale 4, and in a later step you increase when zooming (note that rendering may become slower with higher resolutions).
So a code example for your code would be
pageImage = renderer.renderImage(pageNumber, 4);

Related

JavaFX NullpointerException with FXML in own dialogbox when trying to close window

I am new to JavaFX. I programmed a tableview with a list of persons with their address. Everything worked fine. Then I wanted to write it in the MVC or even better the MVP Design pattern.
I am working with FXML and scenebuilder to layout the scenes.
Now with the MVC I have the problem that I get a NUllpointerException when i.e. I wanna close the confirm dialog box.
And I also can't change the labeltext for the confirmdialog window scene.
I think I know what the problem is but don't know how to solve this properly. The controller gets instantiated twice and therefore the first values of the variables form the fxml are NUll.
So this is how I wrote my little app:
MiniTest.java - my main App
package AddressBook;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MiniTest extends Application {
private static Stage window;
#Override
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
window.setTitle("Adresslist of Clients");
Model model = new Model();
try {
FXMLLoader mainViewloader = new FXMLLoader(getClass().getResource("View.fxml"));
Parent root = (Parent) mainViewloader.load();
MainController mainController = mainViewloader.<MainController>getController();
window.setScene(new Scene(root));
window.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Stage getPrimaryStage() {
return window;
}
public static void main(String[] args) {
launch(args);
}
}
Model.java - this is my model, not sure if the content has to be in here. For the next step I wanna collect the data from a mysql db and save it to the db. For now I have the persons like this.
package AddressBook;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Model {
public ObservableList<Person> getPerson() {
ObservableList<Person> personList = FXCollections.observableArrayList();
Address addressPerson1 = new Address("Jaguarweg 12", "23454", "Bensheim");
Address addressPerson2 = new Address("Friedrich-Ebert-Str. 134", "82635", "Berlin");
Address addressPerson3 = new Address("Adam-Opel-Str. 1", "92364", "Bamberg");
Address addressPerson4 = new Address("Power-Shell-Pfad 21", "10083", "Hamburg");
Address addressPerson5 = new Address("Schwertstr. 76", "749236", "Stuttgart");
Address addressPerson6 = new Address("Hans-Jacob-Weg 4", "66396", "Wiesbaden");
Address addressPerson7 = new Address("Georg-Lucas-Str. 110", "53421", "Wien");
Address addressPerson8 = new Address("Andalusienweg 17", "723612", "Ostfildern");
Address addressPerson9 = new Address("Mercedes-Benz-Str. 9", "883621", "Wolfsburg");
Address addressPerson10 = new Address("Heinrich-Schwein-Str. 43", "134923", "Frankfurt");
Address addressPerson11 = new Address("Engel-Teufel-Str. 66", "083273", "Hildesheim");
personList.add(new Person("Georg Sorresto", addressPerson1));
personList.add(new Person("Flynn Bozzen", addressPerson2));
personList.add(new Person("Bill Klang", addressPerson3));
personList.add(new Person("Wilhelm Busch", addressPerson4));
personList.add(new Person("Gertrud Raven", addressPerson5));
personList.add(new Person("Markus Berg", addressPerson6));
personList.add(new Person("Juergen Schmidt", addressPerson7));
personList.add(new Person("Fritz Titz", addressPerson8));
personList.add(new Person("Bodo Bambino", addressPerson9));
personList.add(new Person("Ortrun Giner", addressPerson10));
personList.add(new Person("Jakob Huber", addressPerson11));
return personList;
}
}
Person.java - my Person class
package AddressBook;
import javafx.beans.property.SimpleStringProperty;
public class Person {
private SimpleStringProperty name;
private Address address;
public Person() {
this.name = new SimpleStringProperty("");
this.address = new Address("", "", "");
}
public Person(String name, Address address) {
this.name = new SimpleStringProperty(name);
;
this.address = address;
}
public String getName() {
return name.get();
}
public void setName(String name2) {
name.set(name2);
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
In MainController.java - for certain things like closing the window or for deleting a person I call a method like this as my own confirmdialogwindow with corresponding String for the Label.
boolean answer = confirmDialogBoxController.display("Exiting Window", "Are you sure you want to close the window?");
if (answer) {
MiniTest.getPrimaryStage().close();
}
and here is the full MainController.java - this is the mainController for the mainView(View.fxml)
package AddressBook;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Callback;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class MainController implements Initializable {
#FXML
private MenuItem exitMenu;
#FXML
private TableView<Person> personTable;
#FXML
private TextField zipInput;
#FXML
private TextField cityInput;
#FXML
private TextField streetInput;
#FXML
private TextField nameInput;
#FXML
private TableColumn<Person, String> cityColumn;
#FXML
private TableColumn<Person, String> zipColumn;
#FXML
private TableColumn<Person, String> streetColumn;
#FXML
private TableColumn<Person, String> nameColumn;
#FXML
private Button addButton;
#FXML
private Button deleteButton;
#FXML
private SimpleStringProperty message;
private Stage window;
private ConfirmDialogBoxController confirmDialogBoxController;
private AlertEmptyNameController alertEmptyNameController;
private Model model;
public MainController(){
model = new Model();
System.out.println("+1 MainController()");
}
public MainController(Model model){
this.model = model;
System.out.println("+1 MainController(model)");
}
#Override
public void initialize(URL location, ResourceBundle resources) {
Callback<TableColumn<Person, String>, TableCell<Person, String>> cellFactory = (TableColumn<Person, String> p) -> new MainController.EditingCell();
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
nameColumn.setCellFactory(cellFactory);
nameColumn.setOnEditCommit(
(
TableColumn.CellEditEvent<Person, String> t) ->
{
((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setName(t.getNewValue());
}
);
streetColumn.setCellValueFactory(person -> new
SimpleStringProperty(person.getValue().
getAddress().
getStreet()));
streetColumn.setCellFactory(cellFactory);
streetColumn.setOnEditCommit(
(
TableColumn.CellEditEvent<Person, String> t) ->
{
((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).getAddress().setStreet(t.getNewValue());
});
zipColumn.setCellValueFactory(person -> new
SimpleStringProperty(person.getValue().
getAddress().
getZip()));
zipColumn.setCellFactory(cellFactory);
zipColumn.setOnEditCommit(
(
TableColumn.CellEditEvent<Person, String> t) ->
{
((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).getAddress().setZip(t.getNewValue());
});
cityColumn.setCellValueFactory(person -> new
SimpleStringProperty(person.getValue().
getAddress().
getCity()));
cityColumn.setCellFactory(cellFactory);
cityColumn.setOnEditCommit(
(
TableColumn.CellEditEvent<Person, String> t) ->
{
((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).getAddress().setCity(t.getNewValue());
});
personTable.setItems(model.getPerson());
personTable.setEditable(true);
MiniTest.getPrimaryStage().setOnCloseRequest(e -> {
try {
e.consume();
closeWindow(e);
} catch (IOException ex) {
ex.printStackTrace();
}
});
}
public SimpleStringProperty getMessageProperty(){
return message;
}
public void setMessage(String message) {
this.message.setValue(message);
}
public String getMessage() {
return this.message.getValue();
}
#FXML
public void closeWindow(WindowEvent e) throws IOException {
boolean answer = confirmDialogBoxController.display("Exiting Window", "Are you sure you want to close the window?");
if (answer) {
MiniTest.getPrimaryStage().close();
}
}
#FXML
public void closeWindowFromMenu(ActionEvent e) throws IOException {
boolean answer = confirmDialogBoxController.display("Exiting Window", "Are you sure you want to close the window?");
if (answer) {
MiniTest.getPrimaryStage().close();
}
}
public Stage getPrimaryStage() {
return window;
}
#FXML
public void addNewPerson() throws IOException {
alertEmptyNameController = new AlertEmptyNameController();
Person person = new Person();
person.setName(nameInput.getText());
if(nameInput.getText().isEmpty()){
alertEmptyNameController.alertEmptyName();
}else{
person.getAddress().setStreet(streetInput.getText());
person.getAddress().setZip(zipInput.getText());
person.getAddress().setCity(cityInput.getText());
personTable.getItems().add(person);
}
nameInput.clear();
streetInput.clear();
zipInput.clear();
cityInput.clear();
}
#FXML
public void deletePerson() throws IOException {
boolean answer = confirmDialogBoxController.display("Deleting Entry", "Are you sure you want to delete this entry?");
if (answer) {
ObservableList<Person> personSelected, allPersons;
allPersons = personTable.getItems();
personSelected = personTable.getSelectionModel().getSelectedItems();
personSelected.forEach(allPersons::remove);
}
}
static class EditingCell extends TableCell<Person, String> {
private TextField textField;
public EditingCell() {
}
#Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.focusedProperty().addListener((ObservableValue<? extends Boolean> arg0,
Boolean arg1, Boolean arg2) -> {
if (!arg2) {
commitEdit(textField.getText());
}
});
}
private String getString() {
return getItem() == null ? "" : getItem();
}
}
}
View.fxml - this is the main View
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="borderPane" stylesheets="#MyStyle.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="AddressBook.MainController">
<bottom>
<HBox fx:id="bottomLayout" alignment="CENTER" style="-fx-background-color: #292929;" BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets />
</BorderPane.margin>
<children>
<TextField fx:id="nameInput" promptText="Name" style="-fx-background-radius: 0;">
<HBox.margin>
<Insets bottom="8.0" left="8.0" right="5.0" top="10.0" />
</HBox.margin>
</TextField>
<TextField fx:id="streetInput" layoutX="15.0" layoutY="15.0" promptText="Street" style="-fx-background-radius: 0;">
<HBox.margin>
<Insets bottom="8.0" left="5.0" right="5.0" top="10.0" />
</HBox.margin>
</TextField>
<TextField fx:id="zipInput" layoutX="163.0" layoutY="15.0" promptText="Zip" style="-fx-background-radius: 0;">
<HBox.margin>
<Insets bottom="8.0" left="5.0" right="5.0" top="10.0" />
</HBox.margin>
</TextField>
<TextField fx:id="cityInput" layoutX="312.0" layoutY="15.0" promptText="City" style="-fx-background-radius: 0;">
<HBox.margin>
<Insets bottom="8.0" left="5.0" right="5.0" top="10.0" />
</HBox.margin>
</TextField>
<Button fx:id="addButton" mnemonicParsing="false" onAction="#addNewPerson" style="-fx-background-color: #5ebcff; -fx-background-radius: 0; -fx-text-fill: white;" text="Add">
<HBox.margin>
<Insets bottom="8.0" left="5.0" right="5.0" top="10.0" />
</HBox.margin>
</Button>
<Button fx:id="deleteButton" layoutX="474.0" layoutY="15.0" mnemonicParsing="false" onAction="#deletePerson" style="-fx-background-radius: 0; -fx-background-color: #5ebcff; -fx-text-fill: white;" text="Delete">
<HBox.margin>
<Insets bottom="8.0" left="5.0" right="8.0" top="10.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</bottom>
<center>
<TableView fx:id="personTable" editable="true" style="-fx-background-color: #5e5e5e;" stylesheets="#MyStyle.css" BorderPane.alignment="CENTER">
<columns>
<TableColumn fx:id="nameColumn" prefWidth="152.0" text="Name" />
<TableColumn fx:id="streetColumn" prefWidth="196.0" text="Street" />
<TableColumn fx:id="zipColumn" prefWidth="88.0" text="Zip" />
<TableColumn fx:id="cityColumn" prefWidth="163.0" text="City" />
</columns>
</TableView>
</center>
<top>
<HBox fx:id="menuLayout" style="-fx-background-color: #292929;" stylesheets="#MyStyle.css" BorderPane.alignment="CENTER">
<children>
<MenuBar fx:id="menuBar" stylesheets="#MyStyle.css">
<menus>
<Menu fx:id="fileMenu" mnemonicParsing="false" text="File">
<items>
<MenuItem fx:id="exitMenu" mnemonicParsing="false" onAction="#closeWindowFromMenu" text="Exit" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</HBox>
</top>
</BorderPane>
ConfirmDialogBoxController.java - this is the controller for the confirm dialog box for closing window with the "X" or in the menu File->Exit and for asking the user if he really wants to delete the entry in the tableview
package AddressBook;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class ConfirmDialogBoxController implements Initializable {
private static Boolean answer;
#FXML
private Button yesButton;
#FXML
private Button noButton;
#FXML
private Label confirmLabel;
#FXML
private Stage stage;
#FXML
private Model model;
public ConfirmDialogBoxController(){
System.out.println("+1 ConfirmDialogBoxController() object instantiated");
}
public ConfirmDialogBoxController(Model model){
this.model = model;
System.out.println("+1 ConfirmDialogBoxController(model) object instantiated");
}
public boolean display(String title, String message) throws IOException {
FXMLLoader confirmViewLoader = new FXMLLoader(getClass().getResource("ConfirmDialogBoxView.fxml"));
confirmViewLoader.load();
ConfirmDialogBoxController confirmDialogBoxController = confirmViewLoader.getController();
confirmDialogBoxController.confirmLabel.setText(message);
Parent root = confirmViewLoader.getRoot();
Stage stage = new Stage();
stage.setTitle(title);
stage.setScene(new Scene(root));
stage.initModality(Modality.APPLICATION_MODAL);
System.out.println("MessageVariable in DisplayMethod is:"+message);
stage.showAndWait();
return answer;
}
public Label getLabel(){
return confirmLabel;
}
#FXML
public boolean yesButtonClicked(ActionEvent actionEvent) {
answer = true;
stage = (Stage) yesButton.getScene().getWindow();
stage.close();
return answer;
}
#FXML
public boolean noButtonClicked(ActionEvent actionEvent) {
answer = false;
Stage confirmWindow = (Stage) noButton.getScene().getWindow();
confirmWindow.close();
return answer;
}
#Override
public void initialize(URL location, ResourceBundle resources) {
// confirmLabel.textProperty().bindBidirectional(messageProperty);
// System.out.println("messageProperty.getValue(): "+ messageProperty.getValue());
// System.out.println("DEBUG: message is = " + messageProperty.get());
}
}
ConfirmDialogBoxView.fxml - this is the ConfirmDialogBox View
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefWidth="450.0" stylesheets="#MyStyle.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="AddressBook.ConfirmDialogBoxController">
<children>
<VBox fx:id="vBox" alignment="CENTER" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label fx:id="confirmLabel" textAlignment="CENTER" />
<HBox fx:id="hBox" alignment="CENTER" spacing="10.0">
<children>
<Button fx:id="yesButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#yesButtonClicked" text="Yes" textAlignment="CENTER">
<HBox.margin>
<Insets />
</HBox.margin>
</Button>
<Button fx:id="noButton" alignment="CENTER" contentDisplay="CENTER" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" onAction="#noButtonClicked" text="No" textAlignment="CENTER">
<HBox.margin>
<Insets />
</HBox.margin>
</Button>
</children>
<VBox.margin>
<Insets />
</VBox.margin>
</HBox>
</children>
<padding>
<Insets bottom="50.0" top="30.0" />
</padding>
</VBox>
</children>
</AnchorPane>
AlertEmptyNameController.java - this is the controller for the view when the name field is empty and you click on add person
package AddressBook;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
public class AlertEmptyNameController {
#FXML
private Button okButton;
#FXML
private Label emptyNameLabel;
private Stage alertEmptyNamestage;
private Model model;
private AlertEmptyNameController alertEmptyNameController;
public AlertEmptyNameController() {
System.out.println("+1 AlertEmptyNameControlle() object instantiated");
}
public AlertEmptyNameController(Model model){
this.model = model;
System.out.println("+1 AlertEmptyNameController(model) object instantiated");
}
public void alertEmptyName() throws IOException {
FXMLLoader alertEmptyNameLoader = new FXMLLoader(getClass().getResource("AlertEmptyNameView.fxml"));
alertEmptyNameLoader.load();
AlertEmptyNameController alertEmptyNameController = alertEmptyNameLoader.getController();
Parent root = alertEmptyNameLoader.getRoot();
alertEmptyNamestage = new Stage();
alertEmptyNamestage.setScene(new Scene(root));
alertEmptyNamestage.setTitle("The Namefield is empty!");
alertEmptyNamestage.initModality(Modality.APPLICATION_MODAL);
alertEmptyNamestage.showAndWait();
}
#FXML
public boolean okButtonClicked(ActionEvent actionEvent) {
boolean answer = true;
alertEmptyNamestage = (Stage) okButton.getScene().getWindow();
alertEmptyNamestage.close();
return answer;
}
}
AlertEmptyNameView.fxml - the view for AlertEmptyName
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<AnchorPane prefHeight="250.0" prefWidth="450.0" stylesheets="#MyStyle.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="AddressBook.AlertEmptyNameController">
<children>
<VBox fx:id="vBox" alignment="CENTER" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label fx:id="emptyNameLabel" text="The Namefield cannot be empty!" textAlignment="CENTER" />
<HBox fx:id="hBox" alignment="CENTER" spacing="10.0">
<children>
<Button fx:id="okButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#okButtonClicked" text="Ok" textAlignment="CENTER">
<HBox.margin>
<Insets />
</HBox.margin>
</Button>
</children>
<VBox.margin>
<Insets />
</VBox.margin>
</HBox>
</children>
<padding>
<Insets bottom="50.0" top="30.0" />
</padding>
</VBox>
</children>
</AnchorPane>
And this is for example the NullPointerException when I wanna close the window:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at AddressBook.MainController.closeWindow(MainController.java:163)
at AddressBook.MainController.lambda$initialize$8(MainController.java:137)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at com.sun.javafx.stage.WindowPeerListener.closing(WindowPeerListener.java:88)
at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:122)
at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:40)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassWindowEventHandler.lambda$handleWindowEvent$3(GlassWindowEventHandler.java:151)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:410)
at com.sun.javafx.tk.quantum.GlassWindowEventHandler.handleWindowEvent(GlassWindowEventHandler.java:149)
at com.sun.glass.ui.Window.handleWindowEvent(Window.java:1273)
at com.sun.glass.ui.Window.notifyClose(Window.java:1177)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:186)
at java.lang.Thread.run(Thread.java:748)
I hope that someone can help me.
Cheers
I deleted now the display() method in confirmDialogBoxController.java and put it in mainController.java
...
public boolean display(String title, String message) throws IOException {
FXMLLoader confirmViewLoader = new FXMLLoader(getClass().getResource("ConfirmDialogBoxView.fxml"));
confirmViewLoader.load();
ConfirmDialogBoxController confirmDialogBoxController = confirmViewLoader.getController();
confirmDialogBoxController.getLabel().setText(message);
Parent root = confirmViewLoader.getRoot();
Stage stage = new Stage();
stage.setTitle(title);
stage.setScene(new Scene(root));
stage.initModality(Modality.APPLICATION_MODAL);
System.out.println("MessageVariable in DisplayMethod is:"+message);
stage.showAndWait();
return answer;
}
#FXML
public void closeWindow(WindowEvent e) throws IOException {
boolean answer = display("Exiting Window", "Are you sure you want to close the window?");
if (answer) {
MiniTest.getPrimaryStage().close();
}
}
...
Your confirmDialogBoxController in the main controller is null: it is never initialized. The way you have set this up is problematic: the ConfirmDialogBoxController is only initialized when the corresponding FXML is loaded (common to any FXML-controller pair), but the code for loading the FXML is in the ConfirmDialogBoxController class, so you can't load the FXML until you have a controller instance.
It's not really the responsibility of the ConfirmDialogBoxController to display the UI defined by its FXML. You should move the display() method to your MainController class:
public class MainController implements Initializable {
// Existing code omitted...
// updated close method:
#FXML
public void closeWindow(WindowEvent e) throws IOException {
boolean answer = display("Exiting Window", "Are you sure you want to close the window?");
if (answer) {
MiniTest.getPrimaryStage().close();
}
}
public boolean displayConfirmDialog(String title, String message) throws IOException {
FXMLLoader confirmViewLoader = new FXMLLoader(getClass().getResource("ConfirmDialogBoxView.fxml"));
confirmViewLoader.load();
ConfirmDialogBoxController confirmDialogBoxController = confirmViewLoader.getController();
confirmDialogBoxController.setConfirmMessage(message);
Parent root = confirmViewLoader.getRoot();
Stage stage = new Stage();
stage.setTitle(title);
stage.setScene(new Scene(root));
stage.initModality(Modality.APPLICATION_MODAL);
System.out.println("MessageVariable in DisplayMethod is:"+message);
stage.showAndWait();
// Get the user response (true = Yes button clicked) from controller:
return confirmDialogBoxController.getResponse() ;
}
}
And then update the ConfirmDialogBoxController:
public class ConfirmDialogBoxController implements Initializable {
// existing code omitted...
// This should not be static, and should be a primitive type:
// private static Boolean answer ;
private boolean answer ;
// this method removed:
/*
public boolean display(String title, String message) throws IOException {
FXMLLoader confirmViewLoader = new FXMLLoader(getClass().getResource("ConfirmDialogBoxView.fxml"));
confirmViewLoader.load();
ConfirmDialogBoxController confirmDialogBoxController = confirmViewLoader.getController();
confirmDialogBoxController.confirmLabel.setText(message);
Parent root = confirmViewLoader.getRoot();
Stage stage = new Stage();
stage.setTitle(title);
stage.setScene(new Scene(root));
stage.initModality(Modality.APPLICATION_MODAL);
System.out.println("MessageVariable in DisplayMethod is:"+message);
stage.showAndWait();
return answer;
}
*/
// This added for convenience:
public void setConfirmMessage(String message) {
confirmLabel.setText(message);
}
// This added to return the response (answer):
public boolean getResponse() {
return answer ;
}
// Note also your event handlers should be void:
#FXML
public void yesButtonClicked(ActionEvent actionEvent) {
answer = true;
stage = (Stage) yesButton.getScene().getWindow();
stage.close();
// return answer;
}
#FXML
public void noButtonClicked(ActionEvent actionEvent) {
answer = false;
Stage confirmWindow = (Stage) noButton.getScene().getWindow();
confirmWindow.close();
// return answer;
}
}
You probably want a similar refactoring for your other dialog.

How to connect multiple controllers to one model? Simple window application in JavaFX

I've seen bunch of posts connected with my problem but it seems like nothing works for me. I'm writing simple window app in Java FX and FXML. I have a Main class which has field with days names. I've got also two controller classes - Controller (which is like more important controller) and ShowDays. Each controller has their own FXML and they are responsible for switching scenes and working with user (and with Model = Main). In Controller class user can add a new day to our days names or remove last day. In ShowDays class user can print on window names of days. It's all connected with clicking buttons.
I know that I can organize my program easier and I can print names of days in Controller class and remove all ShowDays class but it's only a part of project I want to create and I just want to understand how real programmers would have done this kind of things.
This is my code:
public class Main extends Application {
private ArrayList<String> daysNames;
public Main() {
daysNames = new ArrayList<>();
}
public void addDay() {
String[] days = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
System.out.println("I'm adding day!" + daysNames.size());
if (getDaysNames().size() < 7)
getDaysNames().add(days[getDaysNames().size()]);
else
System.out.println("Can't add more days!");
}
public void removeDay() {
if (!getDaysNames().isEmpty())
getDaysNames().remove(getDaysNames().get(getDaysNames().size()-1));
}
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
//setters,getters...
}
Controller class:
public class Controller implements Initializable {
private Main myMain;
#FXML
private ShowDays showDays;
public Controller() {
myMain=new Main();
showDays = new ShowDays(myMain);
}
public Controller(Main main) {
this.myMain = main;
showDays = new ShowDays(myMain);
}
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
public void addDay() {
myMain.addDay();
}
public void removeDay() {
myMain.removeDay();
}
public void GOTOshowDays(ActionEvent event) throws IOException {
Parent showDaysParent = FXMLLoader.load(getClass().getResource("ShowDays.fxml"));
Scene showDaysScene = new Scene(showDaysParent);
Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();
window.setScene(showDaysScene);
window.show();
}
}
ShowDays class:
public class ShowDays implements Initializable {
#FXML
private Text text;
private Main myMain;
public ShowDays() {
myMain = new Main();
}
public ShowDays(Main main) {
myMain = main;
}
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
public void BackToController(ActionEvent event) throws IOException {
Parent controllerParent = FXMLLoader.load(getClass().getResource("sample.fxml"));
Scene controllerScene = new Scene(controllerParent);
Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();
window.setScene(controllerScene);
window.show();
}
public void showDaysInWindow(ActionEvent event) throws IOException {
String allText = "";
for (String day : myMain.getDaysNames())
allText += day + " ";
text.setText(allText);
}
}
and the FXML files:
sample.fxml
<HBox prefHeight="100.0" prefWidth="483.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Button layoutX="-8.0" layoutY="48.0" mnemonicParsing="false" onAction="#GOTOshowDays" text="GOTO show days" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
<Button mnemonicParsing="false" onAction="#addDay" text="add day" />
<Button mnemonicParsing="false" onAction="#removeDay" text="remove day" />
ShowDays.fxml
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.ShowDays">
<center>
<Text fx:id="text" strokeType="OUTSIDE" strokeWidth="0.0" BorderPane.alignment="CENTER" />
</center>
<top>
<Button mnemonicParsing="false" onAction="#showDaysInWindow" text="Show days" BorderPane.alignment="CENTER" />
</top>
<bottom>
<Button mnemonicParsing="false" onAction="#BackToController" text="Go back" BorderPane.alignment="CENTER" />
</bottom>
</BorderPane>
I'm not sure if ShowDays user actions works as expected (it's all about that...) but Controller do. The problem is when I add a few days in Controller scene and then switch scene to ShowDays scene, it seems like I lose my Main instance... When I have one controller class, my code cope with working all time on the same instance of Main and adding/removing days works as expected but I can't cope with connecting multiple controllers to model and them each other... I've spend so much time trying to fix this and I don't really understand all of the tips which I found on the internet, so I ask you.
You should use Ideas from #James_D answer here. Your problem is how to pass a model from one Controller to the next. In this example, the model is a List<String>. The model is passed to the initial Controller named FXMLDocumentController. From that point, the model is passed between FXMLDocumentController and ShowDayscontroller. The showDaysInWindow method, shows the current model info in a Text node. addDay adds a day from the array days if the model is missing a day. removeDay removes a day from the model.
Main
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication320 extends Application
{
#Override
public void start(Stage stage)
{
try {
String[] days = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
List<String> daysNames = new ArrayList();
for (int i = 0; i < days.length; i++) {
daysNames.add(days[i]);
}
//Load the FXML. Pass the model to initModel
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
loader.load();
FXMLDocumentController fXMLDocumentController = loader.getController();
fXMLDocumentController.initModel(daysNames);
Scene scene = new Scene(loader.getRoot());
stage.setScene(scene);
stage.show();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
FXMLDocumentController
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable
{
List<String> model;
#FXML
private void goToShowDays(ActionEvent event)
{
try {
FXMLLoader showDaysLoader = new FXMLLoader(getClass().getResource("ShowDays.fxml"));
showDaysLoader.load();
ShowDaysController showDaysController = showDaysLoader.getController();
showDaysController.initModel(this.model);
Stage stage = (Stage) ((Button) event.getSource()).getScene().getWindow();
stage.setScene(new Scene(showDaysLoader.getRoot()));
}
catch (IOException ex) {
ex.printStackTrace();
}
}
#FXML
private void addDay(ActionEvent event)
{
String[] days = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
List<String> tempDays = new ArrayList(Arrays.asList(days));
if (!this.model.containsAll(tempDays)) {
tempDays.removeAll(this.model);
if (tempDays.size() > 0) {
this.model.add(tempDays.get(0));
}
}
}
#FXML
private void removeDay(ActionEvent event)
{
if (this.model.size() > 0) {
Random random = new Random();
this.model.remove(random.nextInt(this.model.size()));
}
}
#Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
public void initModel(List<String> model)
{
// ensure model is only set once:
if (this.model != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.model = model;
this.model.forEach(System.out::println);
}
}
FXMLDocument
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<HBox prefHeight="100.0" prefWidth="483.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication320.FXMLDocumentController">
<children>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Button layoutX="-8.0" layoutY="48.0" mnemonicParsing="false" onAction="#goToShowDays" text="GOTO show days" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
<Button mnemonicParsing="false" onAction="#addDay" text="add day" />
<Button mnemonicParsing="false" onAction="#removeDay" text="remove day" />
</children>
</HBox>
ShowDaysController
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.text.Text;
import javafx.stage.Stage;
/**
* FXML Controller class
*
* #author blj0011
*/
public class ShowDaysController implements Initializable
{
#FXML
Text text;
List<String> model;
#FXML
private void showDaysInWindow(ActionEvent event)
{
text.setText(String.join(" ", this.model));
}
#FXML
private void backToController(ActionEvent event)
{
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
loader.load();
FXMLDocumentController fXMLDocumentController = loader.getController();
fXMLDocumentController.initModel(this.model);
Stage stage = (Stage) ((Button) event.getSource()).getScene().getWindow();
stage.setScene(new Scene(loader.getRoot()));
}
catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* Initializes the controller class.
*
* #param url
* #param rb
*/
#Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
public void initModel(List<String> model)
{
// ensure model is only set once:
if (this.model != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.model = model;
this.model.forEach(System.out::println);
}
}
ShowDays FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication320.ShowDaysController">
<center>
<Text fx:id="text" strokeType="OUTSIDE" strokeWidth="0.0" BorderPane.alignment="CENTER" />
</center>
<top>
<Button mnemonicParsing="false" onAction="#showDaysInWindow" text="Show days" BorderPane.alignment="CENTER" />
</top>
<bottom>
<Button mnemonicParsing="false" onAction="#backToController" text="Go back" BorderPane.alignment="CENTER" />
</bottom>
</BorderPane>

JavaFX with fxml TableView updating some columns but not others [duplicate]

This question already has answers here:
The table cells are empty in my tableview. JavaFX + Scenebuilder
(2 answers)
Closed 4 years ago.
In my application Some of the columns in my table are populating like they should be the columns labeled Name Priority and BurstTime have the correct values being added but for some reason the other two ProcessID and State do not update with the values I am adding to my ArrayList.
It looks like my code should be working can anybody see something I have missed?
Here is my controller
package application;
import java.net.URL;
import java.util.ResourceBundle;
import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.StringTokenizer;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
public class Controller implements Initializable {
private ArrayList<String> buf = new ArrayList<>();
protected ArrayList<PCB> array = new ArrayList<>();
protected ArrayList<Process> arrayP = new ArrayList<>();
ObservableList<Process> processData = FXCollections.observableArrayList();
#FXML
private Button SubmitButton;
#FXML
private Button LoadButton;
#FXML
private TextArea textArea;
#FXML
private TextField inputBox;
#FXML
private TableView<Process> ProcessTable;
#FXML
private TableColumn<Process, String> processIDP;
#FXML
private TableColumn<Process, String> processTypeP;
#FXML
private TableColumn<Process, String> priorityCodeP;
#FXML
private TableColumn<Process, String> burstTimeP;
#FXML
private TableColumn<Process, String> StatusCodeP;
#Override
public void initialize(URL url, ResourceBundle rb) {
processIDP.setCellValueFactory(new PropertyValueFactory<Process, String>("processIDP"));
processTypeP.setCellValueFactory(new PropertyValueFactory<Process, String>("processTypeP"));
priorityCodeP.setCellValueFactory(new PropertyValueFactory<Process, String>("priorityCodeP"));
burstTimeP.setCellValueFactory(new PropertyValueFactory<Process, String>("burstTimeP"));
StatusCodeP.setCellValueFactory(new PropertyValueFactory<Process, String>("StatusCodeP"));
Process p1 = new Process();
p1.setprocessIDP("22");
p1.setProcessTypeP ("Apname");
p1.setPriorityCodeP("1");
p1.setBurstTimeP ("13");
p1.setstatusCodeP("Tada");
arrayP.add(p1);
ProcessTable.getItems().addAll(arrayP.get(0));
ProcessTable.setItems(FXCollections.observableArrayList(arrayP));
Process p2 = new Process();
p2.setprocessIDP("24");
p2.setProcessTypeP ("Bpname");
p2.setBurstTimeP ("15");
p2.setPriorityCodeP("2");
arrayP.add(p2);
ProcessTable.getItems().addAll(arrayP.get(1));
// edit existing cell ?
arrayP.get(1).setPriorityCodeP("8");
arrayP.get(1).setstatusCodeP("This");
arrayP.get(1).setprocessIDP("TEST");
}
public ObservableList<Process> getProcessData() {
return processData;
}
#FXML
private TextField LoadProgram;
#FXML
private void handleButtonAction() {
textArea.appendText(inputBox.getText() + "\n");
StringTokenizer st1 = new StringTokenizer(inputBox.getText(), " ");
switch(st1.nextToken()) {
// case "proc": proc(); break;
case "mem": textArea.appendText("Memory: " + String.valueOf(Memory.getUsedMemory()) + "/" + String.valueOf(Memory.getTotalMemory()) + "\n"); break;
// case "exe": exe(); break;
// case "reset": reset(); break;
case "load": buf.add(inputBox.getText()) ;
// edit existing cell ?
arrayP.get(1).setPriorityCodeP("9");
ProcessTable.refresh();
break;
case "exit": System.exit(0); break;
case "clear": textArea.clear(); break;
default: break;
}
}
#FXML
private void handleLoadAction() {
File infile = new File("files/" + LoadProgram.getText() + ".txt");
if (infile.exists() == true ) {
textArea.appendText("Loading " + LoadProgram.getText() + "\n");
}
//call to read data here
else {
textArea.appendText("No Program named " + LoadProgram.getText() + " found \n");
}}
public class textLine {
private String infile;
private String cmd, value;
private Scanner input;
public void parseFile(String filename) {
this.infile = "files/" + filename + ".txt";
parseFile();
}
public void addbuf(String textline) {
buf.add(textline);
}
private void parseFile() {
buf.clear();
try {
File file = new File(infile);
if (file.exists() == true)
input = new Scanner(file);
while (input.hasNext()) {
buf.add(input.next());
}
} catch (Exception e) {
e.printStackTrace();
}
input.close();
}
}
}
Here is my class for Procsess
package application;
public class Process {
String processTypeP = "";
String priorityCodeP = "0";
int lineCodeP = 0;
String burstTimeP = "0";
String processIDP = "0";
String StatusCodeP = "0";
public Process (){}
public String getProcessTypeP() {
return processTypeP;
}
public void setProcessTypeP(String processTypeP) {
this.processTypeP = processTypeP;
}
public String getPriorityCodeP() {
return priorityCodeP;
}
public void setPriorityCodeP(String priorityCodeP) {
this.priorityCodeP = priorityCodeP;
}
public int getLineCodeP() {
return lineCodeP;
}
public void setLineCodeP(int lineCodeP) {
this.lineCodeP = lineCodeP;
}
public String getBurstTimeP() {
return burstTimeP;
}
public void setBurstTimeP(String burstTimeP) {
this.burstTimeP = burstTimeP;
}
public String getprocessIDP() {
return processIDP;
}
public void setprocessIDP(String processIDP) {
this.processIDP = processIDP;
}
public String getstatusCodeP() {
return StatusCodeP;
}
public void setstatusCodeP(String StatusCodeP) {
this.StatusCodeP = StatusCodeP;
}
}
Here is my main application
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader(Main.class.getResource("/Main.fxml"));
// Parent root = FXMLLoader.load(getClass().getResource("/Main.fxml"));
AnchorPane root = (AnchorPane) loader.load(Main.class.getResource("/application/Main.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
and my fxml file
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<children>
<TabPane layoutX="4.0" layoutY="4.0" prefHeight="700.0" prefWidth="900.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab text="Processes">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TextField fx:id="inputBox" layoutX="14.0" layoutY="54.0" />
<Button fx:id="SubmitButton" layoutX="109.0" layoutY="94.0" mnemonicParsing="false" onAction="#handleButtonAction" text="Submit" />
<TextArea fx:id="textArea" layoutX="197.0" layoutY="14.0" prefHeight="105.0" prefWidth="493.0" />
<TableView fx:id="ProcessTable" layoutX="36.0" layoutY="157.0" prefHeight="430.0" prefWidth="654.0">
<columns>
<TableColumn fx:id="processIDP" prefWidth="75.0" text="ProccessID" />
<TableColumn fx:id="processTypeP" prefWidth="101.0" text="Name" />
<TableColumn fx:id="priorityCodeP" prefWidth="94.0" text="Priority" />
<TableColumn fx:id="StatusCodeP" prefWidth="119.0" text="State" />
<TableColumn fx:id="burstTimeP" prefWidth="100.0" text="BurstTime" />
</columns>
</TableView>
<TextField fx:id="LoadProgram" layoutX="712.0" layoutY="492.0" />
<Button fx:id="LoadProgramButton" layoutX="725.0" layoutY="531.0" mnemonicParsing="false" onAction="#handleLoadAction" text="Load External Program" />
</children></AnchorPane>
</content>
</Tab>
<Tab text="Scheduler">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Memory">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
Try renaming your getter methods from getprocessIDP and getstatusCodeP to getProcessIDP and getStatusCodeP respectively (note the capital 'S' and 'P'). To avoid problems like this in the future it's a good habit to generate getters, setters and constructors with the IDE instead of doing it manually.

How to apply MVC pattern on combobox with javafx and database source (in this case SQLite)

i am trying to transform my previous javafx program into an MVC machine. i actually do not have any compilation error neither do i have runtime errors. but when i run my login application i cannot see the database values in the combobox.
yes of course i can login, it works fine.
This are my codes for the combobox splited into LoginView, LoginController, and LoginModel:
package com.login;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by DELL PC on 7/25/2016.
*/
public class LoginModel {
Connection connection;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
public LoginModel()
{
connection = SqliteConnection.connector();
if(connection == null)
{
System.exit(1);
}
}
public boolean isDBConnected()
{
try {
return !connection.isClosed();
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
public ComboBox fillCombobox()
{
try
{
final ObservableList options = FXCollections.observableArrayList();
String query = "SELECT role from admin";
preparedStatement = connection.prepareStatement(query);
resultSet = preparedStatement.executeQuery();
while(resultSet.next())
{
options.add(resultSet.getString("role"));
}
preparedStatement.close();
resultSet.close();
}
catch(SQLException ex)
{
Logger.getLogger(LoginModel.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public boolean isLogin(String user, String pass) throws SQLException
{
String query = "SELECT * FROM admin WHERE username = ? and password = ?";
try {
preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, user);
preparedStatement.setString(2, pass);
resultSet = preparedStatement.executeQuery();
if(resultSet.next())
{
return true;
}
else
{
return false;
}
}catch(Exception e){
return false;
}
finally
{
preparedStatement.close();
resultSet.close();
}
}
}
code for Controller
package com.login;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.util.ResourceBundle;
public class LoginController implements Initializable{
public LoginModel loginModel = new LoginModel();
#FXML
private TextField txtusername;
#FXML
private PasswordField pwpaswword;
#FXML
private Label isConnected;
#FXML
private ComboBox comboBox;
#Override
public void initialize(URL location, ResourceBundle resources) {
comboBox.getItems().contains(loginModel.fillCombobox());
if(loginModel.isDBConnected())
{
isConnected.setText("Connected");
}
else
{
isConnected.setText("Not Connected");
}
}
public void Login(ActionEvent event)
{
try {
if (loginModel.isLogin(txtusername.getText(), pwpaswword.getText()))
{
isConnected.setText("Login Successfully ");
((Node)event.getSource()).getScene().getWindow().hide();
Stage window = new Stage();
FXMLLoader loader = new FXMLLoader();
Pane root = loader.load(getClass().getResource("CivilStateView.fxml").openStream());
CivilStateController civilStateController = (CivilStateController)loader.getController();
civilStateController.getUser(txtusername.getText());
Scene scene = new Scene(root);
window.setTitle("Hello World");
window.setScene(scene);
window.show();
}
else
{
isConnected.setText("Login Unsuccessful");
}
} catch (SQLException e) {
isConnected.setText("Exception occurred:" + e);
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
the view is made with fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="346.0" prefWidth="360.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.login.LoginController">
<children>
<Label fx:id="isConnected" layoutX="31.0" layoutY="30.0" prefHeight="36.0" prefWidth="150.0" text="Status" textFill="#f20f0f">
<font>
<Font size="18.0" />
</font>
</Label>
<TextField fx:id="txtusername" layoutX="26.0" layoutY="75.0" prefHeight="48.0" prefWidth="160.0" promptText="Username">
<font>
<Font size="19.0" />
</font>
</TextField>
<PasswordField fx:id="pwpaswword" layoutX="26.0" layoutY="137.0" prefHeight="48.0" prefWidth="160.0" promptText="Password">
<font>
<Font size="19.0" />
</font>
</PasswordField>
<ComboBox fx:id="comboBox" layoutX="26.0" layoutY="196.0" prefHeight="36.0" prefWidth="150.0">
<padding>
<Insets left="20.0" />
</padding>
</ComboBox>
<Button layoutX="26.0" layoutY="245.0" mnemonicParsing="false" onAction="#Login" prefHeight="36.0" prefWidth="68.0" text="Button" />
</children>
</AnchorPane>
I was able to create a test case that runs this though not using any of the DB interaction. The critical parts are:
public class LoginModel {
...
public ObservableList fillCombobox() {
ObservableList options = FXCollections.observableArrayList();
// replace this with your DB code to add the options.
for (int i = 1; i < 10; i++) {
options.add("Role " + i);
}
//
return options;
}
}
public class LoginController implements Initializable {
...
#Override
public void initialize(URL location, ResourceBundle resources) {
comboBox.setItems(loginModel.fillCombobox());
...
}
}

JavaFX: how to make a netbeans like tool-window?

I am working on a new GUI client and we are considering using JavaFX. I was wondering if anyone has a suggestion regarding making a draggable ToolWindow:
(Customer window) in the example. This mini-window should be able to get minimized and dragged out of the parent window, and docked back to it. I really do not want to use netbeans platform (or eclipse or swing for that matter).
You just have to create a custom pane for that:
The complete example is available on gist.
CustomPane.java
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
public class CustomPane extends AnchorPane implements Initializable {
#FXML Button closePane;
#FXML Button minPane;
#FXML Label title;
#FXML Pane contentPane;
#FXML Rectangle separator;
private boolean restoreFlag = false;
private double prefX;
private double prefY;
public CustomPane(String title){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(
"CustomPane.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
this.title.setText(title);
setButtonsLayout();
setStandardLayout();
}
public CustomPane(String title, double y, double x){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(
"CustomPane.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
this.title.setText(title);
this.setPrefSize(x, y);
setButtonsLayout();
setStandardLayout();
restoreRoot();
}
#Override
public void initialize(URL location, ResourceBundle resources) {
closePane.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event) {
setInvisible();
}
});
minPane.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event) {
if(restoreFlag){
restoreFlag = false;
minPane.setText("_");
restoreRoot();
}
else{
restoreFlag = true;
minPane.setText("▭");
minimizeRoot();
}
}
});
}
protected void minimizeRoot() {
this.setPrefSize(prefX/2, title.getPrefHeight() + 5.0);
separator.setWidth(prefX/2 + 5);
this.setLayoutX(0);
this.setLayoutY(prefY-40);
setButtonsLayout();
contentPane.setVisible(false);
}
protected void restoreRoot() {
this.setPrefSize(prefX, prefY);
separator.setWidth(prefX);
contentPane.setVisible(true);
this.setLayoutX(0);
this.setLayoutY(0);
setButtonsLayout();
}
private void setStandardLayout() {
prefX = this.getPrefHeight();
prefY = this.getPrefWidth()-50;
}
public void setButtonsLayout(){
closePane.setLayoutX(this.getPrefWidth()-30);
minPane.setLayoutX(this.getPrefWidth()-55);
}
public void setInvisible(){
this.setVisible(false);
}
public ObservableList<Node> getContent(){
return contentPane.getChildren();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.shape.*?>
customPane.fxml
<fx:root prefHeight="400.0" prefWidth="400.0"
type="javafx.scene.layout.AnchorPane" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1">
<children>
<Rectangle fx:id="separator" arcHeight="5.0" arcWidth="5.0" fill="WHITE"
height="33.0" layoutY="1.0" stroke="BLACK" strokeType="INSIDE" width="600.0" />
<Button fx:id="closePane" layoutX="573.0" layoutY="6.0"
mnemonicParsing="false" text="X" />
<Button fx:id="minPane" layoutX="545.0" layoutY="6.0"
mnemonicParsing="false" text="__" />
<Label fx:id="title" layoutX="14.0" layoutY="12.0" text="Title" />
<Pane fx:id="contentPane" layoutY="34.0" prefHeight="366.0"
prefWidth="600.0" />
</children>
</fx:root>

Resources