I want to move to next stage after Timer but when I run the page is frozen.
I want some help please to resolve this problem, I'm new in JavaFX .
I want to go to next screen after a specific time that I choose because this screen is a load screen
this is my code:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package chapitreapp;
import ressources.FadeInLeftTransition;
import ressources.FadeInRightTransition;
import ressources.FadeInTransition;
import ressources.config;
import ressources.config2;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import javafx.application.Platform;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.springframework.beans.*;
import org.springframework.context.*;
/**
* FXML Controller class
*
* #author anas
*/
public class LoadController implements Initializable {
#FXML
private Text lblWelcome;
#FXML
private Text lblRudy;
#FXML
private VBox vboxBottom;
#FXML
private Label lblClose;
Stage stage;
#FXML
private ImageView imgLoading;
/**
* Initializes the controller class.
* #param url
* #param rb
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
longStart();
lblClose.setOnMouseClicked((MouseEvent event) -> {
Platform.exit();
System.exit(0);
});
// TODO
}
private void longStart() {
Service<ApplicationContext> service = new Service<ApplicationContext>() {
#Override
protected Task<ApplicationContext> createTask() {
return new Task<ApplicationContext>() {
#Override
protected ApplicationContext call() throws Exception {
ApplicationContext appContex = config.getInstance().getApplicationContext();
int max = appContex.getBeanDefinitionCount();
updateProgress(0, max);
for (int k = 0; k < max; k++) {
try
{
Thread.sleep(50);
updateProgress(k+1, max);
}
catch(InterruptedException e)
{
System.exit(0);
}
}
return appContex;
}
};
}
};
service.start();
service.setOnRunning((WorkerStateEvent event) -> {
new FadeInLeftTransition(lblWelcome).play();
new FadeInRightTransition(lblRudy).play();
new FadeInTransition(vboxBottom).play();
});
service.setOnSucceeded((WorkerStateEvent event) -> {
config2 config = new config2();
config.newStage(stage, lblClose, "/chapitreapp/FXMLDocument.fxml", "Sample Apps", true, StageStyle.UNDECORATED, false);
});
}
}
where did I go wrong?
Something along these lines, in your onSucceeded event handler, or a method that it calls...
try {
URL url = this.getClass().getResource("nextScene.fxml");
if (url != null) {
FXMLLoader loader = new FXMLLoader(url);
Parent root = loader.load(url);
Scene newScene = new Scene(root);
this.getStage().setScene(newScene);
} else {
System.out.println("URL was null");
}
} catch (Exception e) {
System.out.println(e);
}
In your controller, you will need to have some means of setting the stage, either via a constructor that accepts the Stage object or via a setStage() method. I've used a getStage() method above to access the Stage and set the new Scene object on it.
You could also use the static FXMLLoader load method: Parent root = FXMLLoader.load(url);
This may also be of benefit: https://blogs.oracle.com/acaicedo/entry/managing_multiple_screens_in_javafx1
Related
I am fairly new to javafx and have been following a tutorial (http://code.makery.ch/library/javafx-8-tutorial/) where all my code has come from.
I am having an issue with populating a table with an xml file which I believe is because I want to switch scene first and then display the table on this new scene. In the guide they do it on just the first scene that loads, which if I do I can get to work fine, but when I want the table data to be viewable on a different scene, it doesn't seem to work. All I did was change where some of the code was located within the class to try to reflect this as I didn't want it on my first scene but now it won't display.
LibraryApp
package libraryapp;
import java.io.File;
import java.io.IOException;
import java.util.prefs.Preferences;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import libraryapp.model.Book;
import libraryapp.model.BookListWrapper;
import libraryapp.view.HomeOverviewController;
import libraryapp.view.RootLayoutController;
public class LibraryApp extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
/**
* The data as an observable list of Books.
*/
private ObservableList<Book> bookData = FXCollections.observableArrayList();
/**
* Constructor
*/
public LibraryApp() {
// Add some sample data
bookData.add(new Book("Hans", "Muster"));
bookData.add(new Book("Ruth", "Mueller"));
bookData.add(new Book("Heinz", "Kurz"));
bookData.add(new Book("Cornelia", "Meier"));
bookData.add(new Book("Werner", "Meyer"));
bookData.add(new Book("Lydia", "Kunz"));
bookData.add(new Book("Anna", "Best"));
bookData.add(new Book("Stefan", "Meier"));
bookData.add(new Book("Martin", "Mueller"));
}
/**
* Returns the data as an observable list of Books.
* #return
*/
public ObservableList<Book> getBookData() {
return bookData;
}
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("LibraryApp");
initRootLayout();
showHomeOverview();
}
/**
* Initializes the root layout and tries to load the last opened
* person file.
*/
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(LibraryApp.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
// Give the controller access to the main app.
RootLayoutController controller = loader.getController();
controller.setLibraryApp(this);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
// Try to load last opened person file.
File file = getBookFilePath();
if (file != null) {
loadBookDataFromFile(file);
}
}
/**
* Shows the book overview inside the root layout.
*/
public void showHomeOverview() {
try {
// Load home overview.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(LibraryApp.class.getResource("view/HomeOverview.fxml"));
AnchorPane homeOverview = (AnchorPane) loader.load();
// Set home overview into the center of root layout.
rootLayout.setCenter(homeOverview);
// Give the controller access to the main app.
HomeOverviewController controller = loader.getController();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Returns the main stage.
* #return
*/
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
/**
* Returns the book file preference, i.e. the file that was last opened.
* The preference is read from the OS specific registry. If no such
* preference can be found, null is returned.
*
* #return
*/
public File getBookFilePath() {
Preferences prefs = Preferences.userNodeForPackage(LibraryApp.class);
String filePath = prefs.get("filePath", null);
if (filePath != null) {
return new File(filePath);
} else {
return null;
}
}
/**
* Sets the file path of the currently loaded file. The path is persisted in
* the OS specific registry.
*
* #param file the file or null to remove the path
*/
public void setBookFilePath(File file) {
Preferences prefs = Preferences.userNodeForPackage(LibraryApp.class);
if (file != null) {
prefs.put("filePath", file.getPath());
// Update the stage title.
primaryStage.setTitle("LibraryApp - " + file.getName());
} else {
prefs.remove("filePath");
// Update the stage title.
primaryStage.setTitle("LibraryApp");
}
}
/**
* Loads book data from the specified file. The current book data will
* be replaced.
*
* #param file
*/
public void loadBookDataFromFile(File file) {
try {
JAXBContext context = JAXBContext
.newInstance(BookListWrapper.class);
Unmarshaller um = context.createUnmarshaller();
// Reading XML from the file and unmarshalling.
BookListWrapper wrapper = (BookListWrapper) um.unmarshal(file);
bookData.clear();
bookData.addAll(wrapper.getBooks());
// Save the file path to the registry.
setBookFilePath(file);
} catch (Exception e) { // catches ANY exception
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not load data");
alert.setContentText("Could not load data from file:\n" + file.getPath());
alert.showAndWait();
}
}
/**
* Saves the current book data to the specified file.
*
* #param file
*/
public void saveBookDataToFile(File file) {
try {
JAXBContext context = JAXBContext
.newInstance(BookListWrapper.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// Wrapping our book data.
BookListWrapper wrapper = new BookListWrapper();
wrapper.setBooks(bookData);
// Marshalling and saving XML to the file.
m.marshal(wrapper, file);
// Save the file path to the registry.
setBookFilePath(file);
} catch (Exception e) { // catches ANY exception
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not save data");
alert.setContentText("Could not save data to file:\n" + file.getPath());
alert.showAndWait();
}
}
}
HomeOverViewController
package libraryapp.view;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.layout.AnchorPane;
import libraryapp.view.BrowseController;
public class HomeOverviewController implements Initializable {
#FXML
private AnchorPane homePane;
#FXML
private void goToBrowse(ActionEvent event) throws IOException {
AnchorPane pane = FXMLLoader.load(getClass().getResource("Browse.fxml"));
homePane.getChildren().setAll(pane);
}
#FXML
private void goToManageAccount(ActionEvent event) throws IOException {
AnchorPane pane = FXMLLoader.load(getClass().getResource("ManageAccount.fxml"));
homePane.getChildren().setAll(pane);
}
#FXML
public void logout(ActionEvent event) throws IOException {
AnchorPane pane = FXMLLoader.load(getClass().getResource("Login.fxml"));
homePane.getChildren().setAll(pane);
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
BrowseController
package libraryapp.view;
import java.io.File;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.AnchorPane;
import libraryapp.LibraryApp;
import libraryapp.model.Book;
public class BrowseController {
#FXML
private TableView<Book> bookTable;
#FXML
private TableColumn<Book, String> titleColumn;
#FXML
private Label titleLabel;
#FXML
private Label authorLabel;
#FXML
private Label isbnLabel;
#FXML
private Label quantityLabel;
#FXML
private AnchorPane browsePane;
// Reference to the main application.
private LibraryApp libraryApp;
/**
* The constructor.
* The constructor is called before the initialize() method.
*/
public BrowseController() {
}
/**
* Initializes the controller class. This method is automatically called
* after the fxml file has been loaded.
*/
#FXML
private void initialize() {
// Initialize the book table
titleColumn.setCellValueFactory(
cellData -> cellData.getValue().titleProperty());
// Clear person details.
showBookDetails(null);
// Listen for selection changes and show the person details when changed.
bookTable.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> showBookDetails(newValue));
}
/**
* Is called by the main application to give a reference back to itself.
*
* #param libraryApp
*/
public void setLibraryApp(LibraryApp libraryApp) {
this.libraryApp = libraryApp;
// Add observable list data to the table
bookTable.setItems(libraryApp.getBookData());
}
private void showBookDetails(Book book) {
if (book != null) {
// Fill the labels with info from the book object.
titleLabel.setText(book.getTitle());
authorLabel.setText(book.getAuthor());
isbnLabel.setText(book.getIsbn());
quantityLabel.setText(Integer.toString(book.getQuantity()));
} else {
// Book is null, remove all the text.
titleLabel.setText("");
authorLabel.setText("");
isbnLabel.setText("");
quantityLabel.setText("");
}
}
/**
* Called when the user clicks on the borrow button.
*/
#FXML
private void handleDeleteBook() {
int selectedIndex = bookTable.getSelectionModel().getSelectedIndex();
if (selectedIndex >= 0) {
bookTable.getItems().remove(selectedIndex);
} else {
// Nothing selected.
Alert alert = new Alert(AlertType.WARNING);
alert.initOwner(libraryApp.getPrimaryStage());
alert.setTitle("No Selection");
alert.setHeaderText("No book Selected");
alert.setContentText("Please select a book.");
alert.showAndWait();
}
}
#FXML
public void logout(ActionEvent event) throws IOException {
File bookFile = libraryApp.getBookFilePath();
libraryApp.saveBookDataToFile(bookFile);
AnchorPane pane = FXMLLoader.load(getClass().getResource("Login.fxml"));
browsePane.getChildren().setAll(pane);
}
}
The idea is that I want to press a button which calls goToBrowse which will load the Browse scene and then populate the table there with the data from the xml file. It goes to browse scene fine but does not populate the table.
Please excuse any messy code and any bad naming conventions as I am pretty new to this javafx stuff and have been trying to follow the tutorial that was mentioned before and tweak it to what I thought would be correct.
I believe it is the setLibraryApp that I want to be calling in the BrowseController, but what I have tried doesn't seem to work.
I am begging with JavaFx, and I realized that I need some help to update a TreeView with some TreeItems in runtime, and it should be updated in the main window.
Here, you can see a screenshot of the two windows:
The bigger is the main window and it calls (by clicking in File >> New Project), new smaller. In the smaller window, I could get the String that is typed and than the enter button is clicked.
The trouble is: How can I show the new items created by the "new project window" (the smaller window in the pic) in the TreeView in the main window(the bigger)?
The treeview is in the left side of the main window.
I hope I was clear.
Here is the code of the controllers of these windows:
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeItem.TreeModificationEvent;
import javafx.scene.control.TreeView;
import javafx.stage.Modality;
import javafx.stage.Stage;
/**
* this class handles with the main window of our LDF Tool
* #author Vinicius
* #version 1.0
*/
public class MainController implements Initializable{
#FXML
TreeView<String> treeView;
#FXML
MenuItem newProject;
private boolean flag = false;
private NewProjectWindowController npwc;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#FXML
public void newProjectClicked(ActionEvent event){
try{
flag = true;
FXMLLoader fxml = new FXMLLoader(getClass().getResource("newProjectWindow.fxml"));
Parent root = (Parent) fxml.load();
Stage newWindow = new Stage();
newWindow.setTitle("New Project");
newWindow.initModality(Modality.APPLICATION_MODAL);
newWindow.setScene(new Scene(root));
newWindow.show();
} catch (Exception e) {
System.out.println("caiu na exceção");
}
}
/**
* to this method, choose the project's name as argument, and it will be put on the
* tree with the archives that should be created together
* #param projectName
*/
public void doTree(String projectName){
TreeItem<String> root = new TreeItem<>("projectName");
root.setExpanded(true);
//TreeItem<String> folha1 = new TreeItem<String>(projectName + " arquivo 1");
//root.getChildren().add(folha1);
treeView.setRoot(root);
}
The other controller class:
package application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
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.TextField;
import javafx.stage.Stage;
public class NewProjectWindowController implements Initializable{
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#FXML
Button cancelButton;
#FXML
Button enterButton;
#FXML
TextField textInput;
private String input;
public String getInput(){
return this.input;
}
#FXML
public void cancelButtonClicked(ActionEvent event) {
Stage window = (Stage) this.cancelButton.getParent().getScene().getWindow();
window.close();
}
#FXML
public void enterButtonClicked(ActionEvent event) {
input = hasString();
Stage window = (Stage) this.enterButton.getParent().getScene().getWindow();
window.close();
}
private String hasString(){
if (this.textInput.getText().isEmpty())
return null;
return this.textInput.getText();
}
}
Please, assume that I mapped everything ok in the FXML file.
thanks
#FXML
public void newProjectClicked(ActionEvent event){
try{
flag = true;
FXMLLoader fxml = new FXMLLoader(getClass().getResource("newProjectWindow.fxml"));
Parent root = (Parent) fxml.load();
Stage newWindow = new Stage();
newWindow.setTitle("New Project");
newWindow.initModality(Modality.APPLICATION_MODAL);
newWindow.setScene(new Scene(root));
// showAndWait blocks execution until the window closes:
newWindow.showAndWait();
NewProjectWindowController controller = fxml.getController();
String input = controller.getInput();
if (input != null) {
TreeItem<String> currentItem = treeView.getSelectionModel().getSelectedItem();
if (currentItem == null) currentItem = treeView.getRoot();
currentItem.getChildren().add(new TreeItem<>(input));
}
} catch (Exception e) {
System.out.println("caiu na exceção");
}
}
Im working on Javafx. I have created an echo ServerClient system i.e Sending data to server and back to all clients(broadcast). It works fine when Client sends data to Server. But the frame freezes when Server sends the data back to Client. Here is the code:
Client:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.rajeshpatkar;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
*
* #author Dimpi
*/
public class Client extends Application{
int flag = 999;
public void start(Stage primaryStage) throws Exception {
Connect cnn = new Connect(primaryStage);
cnn.sconnect();
}
public static TextArea Frame(Stage primaryStage, PrintWriter nos, BufferedReader nis) throws IOException {
TextField tf = new TextField();
TextArea ta = new TextArea();
Button btn = new Button();
btn.setText("Click");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
String get = tf.getText();
nos.println(get);
try {
Connect.chat(nis,ta);
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
BorderPane root = new BorderPane();
root.setCenter(ta);
BorderPane panel = new BorderPane();
root.setBottom(panel);
panel.setCenter(tf);
panel.setRight(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
return ta;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
class Connect {
Stage primaryStage;
Connect(Stage primaryStage) {
this.primaryStage = primaryStage;
}
public void sconnect() throws IOException {
System.out.println("Client Signing IN");
Socket soc = new Socket("localhost", 9081);
PrintWriter nos = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(soc.getOutputStream()
)
), true);
BufferedReader nis = new BufferedReader(
new InputStreamReader(soc.getInputStream()
)
);
TextArea ta=Client.Frame(primaryStage, nos, nis);
}
public static void chat(BufferedReader nis,TextArea ta) throws IOException{
String set = nis.readLine();
while (!set.equals("End")) {
ta.appendText(set+"\n");
set = nis.readLine();
}
}
}
Server: /*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.rajeshpatkar;
import static com.rajeshpatkar.Server.a1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
*
* #author Dimpi
*/
public class Server extends Application {
public static ArrayList<PrintWriter> a1=new ArrayList<PrintWriter>();
#Override
public void start(Stage primaryStage) throws IOException {
System.out.println("Server signing IN");
ServerSocket ss = new ServerSocket(9081);
for (int i = 0; i < 5; i++) {
Socket soc = ss.accept();
Conversation c = new Conversation(soc);
c.start();
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
class Conversation extends Thread {
Socket soc;
Conversation(Socket soc) {
this.soc = soc;
}
public void run() {
try {
PrintWriter nos = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(soc.getOutputStream()
)
), true);
BufferedReader nis = new BufferedReader(
new InputStreamReader(soc.getInputStream()
)
);
Server.a1.add(nos);
String get=nis.readLine();
while(true){
for(PrintWriter p:a1){
System.out.println(get);
p.println(get);
}
get=nis.readLine();
}
} catch (Exception e) {
}
}
}
the issue of freezing the client-ui is caused your method: chat(). which is called by your button. it contains the method readLine() of BufferedReader which will wait for an input to happen. this wait will cause your freeze since it happens on the Application Thread.
so what you can do is: on your button-eventhandler: only write output:
String get = tf.getText();
nos.println(get);
but add a Thread which will update your TextArea if your InputStream receives an input, e.g. like this:
static void handleInput(BufferedReader nis, TextArea ta) throws IOException {
final Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
String output;
while ((output = nis.readLine()) != null) {
final String value = output;
Platform.runLater(new Runnable() {
#Override
public void run() {
ta.appendText(value + System.getProperty("line.separator"));
}
});
}
return null;
}
};
new Thread(task).start();
}
and call that method once:
handleInput(nis, ta);
EDIT:
I have an alert box that pops up if the user clicks "Delete" for removing an item in a ListView. It works, but I would like it to pop over the original stage. It showed up in my first monitor. Is there any way to set the position of the alert when it's shown?
Note, the "owner" is in a different class, and I created everything with Scenebuilder/FXML. I cannot figure out how to get initOwner() to work. Here is the "Main" class:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Assignment_5 extends Application {
public Stage primaryStage;
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("Assignment_5.fxml"));
primaryStage.setTitle("Plant Pack");
primaryStage.setScene(new Scene(root, 1200, 500));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Here is the working code within the Controller class. It's not necessary to implement the modality of this alert, but it would be a nice addition to make it more convenient. I simply don't know how to pass the main Window from the Main class to this:
protected void handleDeleteButtonClick(ActionEvent event) {
Alert alertBox = new Alert(Alert.AlertType.CONFIRMATION, "Confirm Delete", ButtonType.OK, ButtonType.CANCEL);
alertBox.setContentText("Are you sure you want to delete this " + plantType.getValue().toString().toLowerCase() + "?");
alertBox.showAndWait();
if(alertBox.getResult() == ButtonType.OK) {
int selectedPlant = plantList.getSelectionModel().getSelectedIndex();
observablePlantList.remove(selectedPlant);
}
else {
alertBox.close();
}
}
I understand this is fairly new, so it's difficult to find many resources. If anyone knows any info I may have missed, please let me know. Thanks for any help offered.
I am using Java 8 with IntelliJ 14.1.5.
As #jewelsea suggests, setting the modality and owner for the alert box will assure that the alert will appear over the stage, even if the stage is moved.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class DeleteAlertDemo extends Application {
Stage owner;
ObservableList<String> observablePlantList;
ListView<String> plantList;
protected void handleDeleteButtonClick(ActionEvent event) {
String item = plantList.getSelectionModel().getSelectedItem();
Alert alertBox = new Alert(Alert.AlertType.CONFIRMATION, "Confirm Delete",
ButtonType.OK, ButtonType.CANCEL);
alertBox.setContentText("Are you sure you want to delete this "
+ item.toLowerCase() + "?");
alertBox.initModality(Modality.APPLICATION_MODAL); /* *** */
alertBox.initOwner(owner); /* *** */
alertBox.showAndWait();
if (alertBox.getResult() == ButtonType.OK) {
int selectedPlant = plantList.getSelectionModel().getSelectedIndex();
observablePlantList.remove(selectedPlant);
} else {
alertBox.close();
}
}
#Override
public void start(Stage primaryStage) {
owner = primaryStage; /* *** */
Button deleteBtn = new Button();
deleteBtn.setText("Delete");
deleteBtn.setOnAction(this::handleDeleteButtonClick);
observablePlantList = FXCollections.observableArrayList("Begonia",
"Peony", "Rose", "Lilly", "Chrysanthemum", "Hosta");
plantList = new ListView<>(observablePlantList);
plantList.getSelectionModel().select(0);
BorderPane root = new BorderPane();
root.setCenter(plantList);
root.setRight(deleteBtn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Delete Alert Demo");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
This is my sample code, In my project I have used scroll pane, but i am click outside of node and use arrow keys that nodes are move to Center,left,right,bottom.how to lock the node in same position,
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
/**
*
* #author reegan
*/
public class ComboBoxEditable extends Application {
Node sub;
#Override
public void start(Stage primaryStage) {
ComboBox mainCombo = new ComboBox(listofCombo());
Button save = new Button("Save");
sub = new ComboBox(listofCombo());
HBox root = new HBox(20);
root.getChildren().addAll(mainCombo, sub,save);
ScrollPane pane = new ScrollPane(root);
mainCombo.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
if (newValue == "Others") {
sub = new TextField();
} else {
sub = new ComboBox(listofCombo());
}
root.getChildren().remove(1);
root.getChildren().add(1, sub);
}
});
save.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println(mainCombo.getValue());
if(sub.getClass() == ComboBox.class) {
ComboBox sub1 = (ComboBox)sub;
System.out.println(sub1.getValue());
} else {
TextField field = (TextField)sub;
System.out.println(field.getText());
}
}
});
Scene scene = new Scene(pane, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public ObservableList listofCombo() {
ObservableList<String> list = FXCollections.observableArrayList();
for (int i = 0; i < 10; i++) {
list.add(String.valueOf("Hello" + i));
}
list.add("Others");
return list;
}
}
I am ref this example code :JavaFX: scrolling vs. focus traversal with arrow keys
#James_D told "The default behavior for a scroll pane is that, if it has keyboard focus, the cursor (arrow) keys will cause it to scroll".So consume that event Ref for this solution JavaFX: scrolling vs. focus traversal with arrow keys
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package comboboxeditable;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
/**
*
* #author reegan
*/
public class ComboBoxEditable extends Application {
Node sub;
#Override
public void start(Stage primaryStage) {
ComboBox mainCombo = new ComboBox(listofCombo());
Button save = new Button("Save");
sub = new ComboBox(listofCombo());
HBox root = new HBox(20);
root.getChildren().addAll(mainCombo, sub, save);
ScrollInterceptor pane = new ScrollInterceptor(root);
mainCombo.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
if (newValue == "Others") {
sub = new TextField();
} else {
sub = new ComboBox(listofCombo());
}
root.getChildren().remove(1);
root.getChildren().add(1, sub);
}
});
save.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println(mainCombo.getValue());
if (sub.getClass() == ComboBox.class) {
ComboBox sub1 = (ComboBox) sub;
System.out.println(sub1.getValue());
} else {
TextField field = (TextField) sub;
System.out.println(field.getText());
}
}
});
Scene scene = new Scene(pane, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public ObservableList listofCombo() {
ObservableList<String> list = FXCollections.observableArrayList();
for (int i = 0; i < 10; i++) {
list.add(String.valueOf("Hello" + i));
}
list.add("Others");
return list;
}
private static class ScrollInterceptor extends ScrollPane {
public ScrollInterceptor() {
remapArrowKeys(this);
}
public ScrollInterceptor(Node content) {
ScrollInterceptor.this.setContent(content);
remapArrowKeys(this);
}
private void remapArrowKeys(ScrollPane scrollPane) {
scrollPane.addEventFilter(KeyEvent.ANY, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case UP:
case DOWN:
case LEFT:
case RIGHT:
event.consume();
}
}
});
}
}
}