Hi this is the structure of my application.
MCVE:
#FXML
void OnSimulateClick(ActionEvent event) throws IOException {
if (event.getSource() == simulatebutton) {
primaryStage = (Stage) simulatebutton.getScene().getWindow();
pane = (Pane) FXMLLoader.load(TDC.class.getResource("view/Simulation.fxml"));
scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
FXML
<Pane prefHeight="500.0" prefWidth="750.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.mdw.tdc.view.SimulationController" >
<children>
<Button fx:id="abortbutton" layoutX="650.0" layoutY="230.0" onAction="#onAbortClicked" text="Abort" />
<Button fx:id="homebutton" layoutX="650.0" layoutY="330.0"onAction="#onHomeClicked" text="Home" />
<TextArea fx:id="logscreen" layoutX="21.0" layoutY="20.0" prefHeight="395.0" prefWidth="600.0" />
</children>
</Pane>
controller
public class SimulationController implements Initializable {
#FXML
private Button homebutton;
#FXML
private TextArea logscreen;
#FXML
private Button abortbutton;
private Simulate simulate;
#Override
public void initialize(URL location, ResourceBundle resources) {
simulate = new Simulate(list, logscreen);
simulate.setOnCancelled(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
System.out.println("Simulation Aborted by User...");
}
});
simulate.setOnFailed(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
System.out.println("Simulation Failed...");
}
});
simulate.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
System.out.println("Simulation Success...");
}
});
simulate.start();
}
#FXML
void onAbortClicked(ActionEvent event) throws IOException,
InterruptedException {
if (event.getSource() == abortbutton) {
simulate.cancel();
}
}
}
#FXML
void onHomeClicked(ActionEvent event) throws IOException {
if (event.getSource() == homebutton) {
simulate.reset();
/*back to Home screen*/
pane = (Pane) FXMLLoader.load(TDC.class.getResource("view/Simulation.fxml"));
scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Simulate Sercice
public class Simulate extends Service<Void> {
private ObservableList<TestData> list;
private TextArea logscreen;
private ConsoleStream consoleStream;
public Simulate(ObservableList<TestData> list, TextArea logscreen) {
this.list = list;
this.logscreen = logscreen;
}
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
consoleStream = new ConsoleStream(logscreen);
consoleStream.start();
/*Some Code*/
System.out.println("End of Simulation");
return null;
}
};
}
/* Few other methods called from inside my code inside createTask()>call() method */
// using this method to flag when cancelled
public void isFlagged(boolean b) {
consoleStream.isFlagged(true);
consoleStream.setOnCancelled(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
consoleStream.reset();
}
});
consoleStream.cancel();
}
}
ConsoleStream Service
public class ConsoleStream extends Service<Void> {
private PipedOutputStream outPipedOutputStream, errorPipedOutputStream;
private PipedInputStream outPipedInputStream, errorPipedInputStream;
private TextArea logscreen;
private Console outCon;
public ConsoleStream(TextArea logscreen) {
this.logscreen = logscreen;
}
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
try {
System.err.flush();
System.out.flush();
outPipedInputStream = new PipedInputStream();
outPipedOutputStream = new PipedOutputStream(
outPipedInputStream);
System.setOut(new PrintStream(outPipedOutputStream));
errorPipedInputStream = new PipedInputStream();
errorPipedOutputStream = new PipedOutputStream(
errorPipedInputStream);
System.setErr(new PrintStream(errorPipedOutputStream));
outCon = new Console(outPipedInputStream, logscreen);
outCon.setOnCancelled(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
// TODO Auto-generated method stub
System.out.println("ConsoleStream Aborted by User...");
outCon.reset();
}
});
outCon.start();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
}
public void isFlagged(boolean b) {
outCon.cancel();
}
}
Console Service
public class Console extends Service<Void> {
private final InputStream inputStream;
private TextArea logscreen;
public Console(PipedInputStream errorPipedInputStream, TextArea logscreen) {
inputStream = errorPipedInputStream;
this.logscreen = logscreen;
}
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
while(isCancelled()){
inputStream.close();
break;
}
try {
InputStreamReader is = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(is);
while (br.readLine() != null) {
String read = br.readLine();
logscreen.appendText(read + "\n");
}
is.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
}
}
This is the first attempt at JavaFx not sure this is good way of doing. any suggestions are appriciated
Thanks
Related
I Have two Activity. The MainActivity is calling the another Activity which extends AsyncTask. In AsyncTask i had display ProgressDailog onPreExecute(), but ProgressDailog is not been display. The reason may be AyncTask execute for less time but the response but response takes time and therefore ProgressDialog should be displayed.
The Following code is provide.
Aysnc class
public class NewConnections extends AsyncTask<Void,Void,String>{
Context context;
String[] name,value;
String Geturl,para;
ProgressDialog progressDialog;
NewConnections(Context context,String[] name,String[] value,String Url){
this.context = context;
this.name = name;
this.value = value;
Geturl = Url;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Please Wait");
progressDialog.show();
}
#Override
protected String doInBackground(Void... voids) {
try
{
para = DCBUtil.jsonCovertion(name,value);
URL url = new URL(Geturl);
String responseStr = XXX.callJsonHttp(url,para);
System.out.println("Response of Home Open FD :: "+responseStr);
return responseStr;
}catch(Exception e)
{
return "Error";
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
progressDialog.dismiss();
}
}
MainClass
public class FirstPage extends AppCompatActivity {
Button existUser,newUser;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first_page);
existUser = (Button)findViewById(R.id.existUser);
newUser = (Button)findViewById(R.id.newUser);
newUser.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String[] value = {"asdasd"};
String[] name = {"dprm"};
try {
NewConnections v= new NewConnections(FirstPage.this,name,value,"url is provided");
v.execute().get();
} catch (Exception e) {
e.printStackTrace();
}
}
});
try this :
public class NewConnections extends AsyncTask<Void,Void,String>{
Context context;
String[] name,value;
String Geturl,para;
public static ProgressDialog progressDialog;
NewConnections(Context context,String[] name,String[] value,String Url){
this.context = context;
this.name = name;
this.value = value;
Geturl = Url;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(context);
progressDialog.setCancelable(false);
progressDialog.setMessage("Please Wait");
progressDialog.show();
}
#Override
protected String doInBackground(Void... voids) {
try
{
para = DCBUtil.jsonCovertion(name,value);
URL url = new URL(Geturl);
String responseStr = XXX.callJsonHttp(url,para);
System.out.println("Response of Home Open FD :: "+responseStr);
return responseStr;
}catch(Exception e)
{
return "Error";
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(progressDialog!=null)
progressDialog.dismiss();
}
}
and when you exit from activity then write below code in onDestry() method of that Activity
#Override
protected void onDestroy() {
if(NewConnections.progressDialog!=null)
NewConnections.progressDialog.dismiss();
super.onDestroy();
}
Try this:: I hope this helps you.
Dialog dialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
showProgressBar();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try{
hideProgressBar();
}catch (Exception e){
e.printStackTrace();
}
}
public void showProgressBar() {
dialog = new Dialog(mContext, android.R.style.Theme_Translucent);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
dialog.setCancelable(false);
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View viewChild = inflater.inflate(R.layout.loader, null);
dialog.setContentView(viewChild);
Runtime.getRuntime().gc();
System.gc();
try {
dialog.show();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* Hide progress dialog
*/
public void hideProgressBar() {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
loader.xml::
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:gravity="center">
<ProgressBar
android:id="#+id/loading_spinner"
android:layout_width="48dp"
android:layout_height="48dp"
android:indeterminateTintMode="src_atop"
android:indeterminateTint="#color/colorAccent"
android:layout_gravity="center" />
</RelativeLayout>
All it's ok when i open light weight's pages but when i wan't to open some bigger the GUI blocks and not responding until the site load's. I try to give it to background thread but it's not working.
MainWindowController:
WebControl webcontroller = new WebControl();
DatabaseControl datacontroller;
#FXML
private ToggleButton PowypadkoweBt;
#FXML
private ToggleButton UszkodzoneBt;
#FXML
private ToggleButton MailBt;
#FXML
private ToggleButton SMSBt;
#FXML
private Button SendBt;
#FXML
private ScrollPane WynikiScroll;
#FXML
private TableView DoneTable;
#FXML
private TableColumn CheckCol, OpisCol, LoginCol;
#FXML
private TextArea MessageArea;
#FXML
private WebView WebControl;
#FXML
private Button NEXT;
#FXML
private Button PREVIOUS;
#FXML
private Label PAGE;
#Override
public void initialize(URL url, ResourceBundle rb) {
this.CheckCol.setCellValueFactory(
new Callback<CellDataFeatures<UsedTableRow, Boolean>, ObservableValue<Boolean>>() {
#Override
public ObservableValue<Boolean> call(CellDataFeatures<UsedTableRow, Boolean> param) {
return param.getValue().getCheckedProperty();
}
});
this.CheckCol.setCellFactory(CheckBoxTableCell.forTableColumn(this.CheckCol));
this.CheckCol.setEditable(false);
this.CheckCol.setMinWidth(50);
this.CheckCol.setMaxWidth(50);
this.OpisCol.setCellValueFactory(new PropertyValueFactory<UsedTableRow, String>("Description"));
this.LoginCol.setCellValueFactory(new PropertyValueFactory<UsedTableRow, String>("Login"));
ObservableList<UsedTableRow> data = FXCollections.observableArrayList();
try {
datacontroller = new DatabaseControl();
data.addAll(datacontroller.getRowsFromEntity());
} catch (ClassNotFoundException ex) {
Alert alert = new Alert(AlertType.WARNING);
alert.setContentText("Nie udało się nawiązać połączenia z bazą danych. Błąd klasy.");
alert.setHeaderText("Błąd klasy.");
alert.setTitle("Błąd");
alert.show();
} catch (SQLException ex) {
Alert alert = new Alert(AlertType.WARNING);
alert.setHeaderText("Błąd SQL.");
alert.setContentText("Nie udało się nawiązać połączenia z bazą danych. Błąd SQL.");
alert.setTitle("Błąd");
alert.show();
}
this.DoneTable.setItems(data);
this.WebControl.getEngine().load("http://otomoto.pl");
this.PAGE.setText((this.webcontroller.getIteratorAuctions() + this.webcontroller.getIteratorItems() - 10) + " z " + this.webcontroller.getItemsIds().size());
// loadNewSite();
this.WebControl.autosize();
this.WebControl.widthProperty().addListener(new ChangeListener<Object>() {
public void changed(ObservableValue<?> observable, Object oldValue, Object newValue) {
Double width = (Double) newValue;
WebControl.setPrefWidth(width);
WebControl.autosize();
}
});
this.WebControl.requestLayout();
this.WebControl.setContextMenuEnabled(false);
this.WebControl.getEngine().setJavaScriptEnabled(true);
this.WebControl.getEngine().setUserAgent("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36");
this.PowypadkoweBt.setSelected(true);
this.UszkodzoneBt.setSelected(true);
}
#FXML
private void PowypadkoweAction(ActionEvent event) {
if (this.PowypadkoweBt.isSelected()) {
this.webcontroller.refresh(true);
} else {
this.webcontroller.refresh(false);
}
loadNewSite();
}
#FXML
private void UszkodzoneAction(ActionEvent event) {
}
#FXML
private void SMSAction(ActionEvent event) {
}
#FXML
private void MailAction(ActionEvent event) {
}
#FXML
private void SendAction(ActionEvent event) {
}
#FXML
private void PREVIOUSAction(ActionEvent event) {
webcontroller.previousAuction();
loadNewSite();
}
#FXML
private void NEXTAction(ActionEvent event) {
webcontroller.nextAuction();
loadNewSite();
this.WebControl.autosize();
}
private void updateDoneTable() {
ObservableList<UsedTableRow> data = FXCollections.observableArrayList();
data.addAll(datacontroller.getRowsFromEntity());
this.DoneTable.getItems().clear();
this.DoneTable.setItems(data);
}
private void loadNewSite() {
Service<Void> service = new Service<Void>() {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
//Background work
final CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(new Runnable() {
#Override
public void run() {
try {
WebControl.getEngine().load(webcontroller.getSelectedURL());
PAGE.setText((webcontroller.getIteratorAuctions() + webcontroller.getIteratorItems() - 10) + " z " + webcontroller.getItemsIds().size());
} finally {
latch.countDown();
}
}
});
latch.await();
//Keep with the background work
return null;
}
};
}
};
service.start();
/* Task task = new Task(new Runnable() {
#Override
public void run() {
WebControl.getEngine().load(webcontroler.getSelectedURL());
}
});
tr.run();
this.PAGE.setText((this.webcontroler.getIteratorAuctions() + this.webcontroler.getIteratorItems() - 10) + " z " + this.webcontroler.getItemsIds().size());
*/
}}
CInsurance Application class :
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("/cinsurance/MainWindow.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("/cinsurance/mainwindow.css").toExternalForm());
primaryStage.setTitle("Aplikacja Ubezpieczeniowa CInsurance");
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException ex) {
Logger.getLogger(CInsurance.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}}
Thanks for any help.
After i lost a lot of time on thinking why , i just continue to code modules for this application and i add some multithreading into initialize method of controller and ... it was very strange . Everything is working ok , even when i'm loading heavy page's. I still don't know why multithreading unlocks the blockade... but it can be also the change of JDK because i must change it to 32 bit form 64 bit. After all it is strange.
In a JavaFX application I wish to update a status bar according to some work logic which I've implemented in an other class.
I can't figure out how to combine my desire to pass to work logic to the method (and not to write it inside the task) and to know about the work progress percentage.
This is an example of the controller with the Task:
public class FXMLDocumentController implements Initializable {
#FXML private Label label;
#FXML ProgressBar progressBar;
#FXML
private void handleButtonAction(ActionEvent event) {
Service<Void> myService = new Service<Void>() {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
try {
DatabaseFunctionality.performWorkOnDb();
//updateProgress(1, 1);
} catch (InterruptedException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
progressBar.progressProperty().bind(myService.progressProperty());
myService.restart();
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
This is the helper class:
public class DatabaseFunctionality {
public static void performWorkOnDb () throws InterruptedException {
for (int i = 1; i <= 100; i++) {
System.out.println("i=" + i);
Thread.sleep(100);
//Update progress
}
}
}
Thank you
You have a couple of options here. One is to do as Uluk suggests and expose an observable property in your DatabaseFunctionality class:
public class DatabaseFunctionality {
private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper();
public double getProgress() {
return progressProperty().get();
}
public ReadOnlyDoubleProperty progressProperty() {
return progress ;
}
public void performWorkOnDb() throws Exception {
for (int i = 1; i <= 100; i++) {
System.out.println("i=" + i);
Thread.sleep(100);
progress.set(1.0*i / 100);
}
}
}
And now in your Task, you can observe that property and update the task's progress:
Service<Void> myService = new Service<Void>() {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
try {
DatabaseFunctionality dbFunc = new DatabaseFunctionality();
dbFunc.progressProperty().addListener((obs, oldProgress, newProgress) ->
updateProgress(newProgress.doubleValue(), 1));
dbaseFunc.performWorkOnDb();
} catch (InterruptedException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
Another option (in case you don't want your data access object to depend on the JavaFX properties API) is to pass the data access object a callback to update the progress. A BiConsumer<Integer, Integer> would work for this:
public class DatabaseFunctionality {
private BiConsumer<Integer, Integer> progressUpdate ;
public void setProgressUpdate(BiConsumer<Integer, Integer> progressUpdate) {
this.progressUpdate = progressUpdate ;
}
public void performWorkOnDb() throws Exception {
for (int i = 1; i <= 100; i++) {
System.out.println("i=" + i);
Thread.sleep(100);
if (progressUpdate != null) {
progressUpdate.accept(i, 100);
}
}
}
}
and then
Service<Void> myService = new Service<Void>() {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
try {
DatabaseFunctionality dbFunc = new DatabaseFunctionality();
dbFunc.setProgressUpdate((workDone, totalWork) ->
updateProgress(workDone, totalWork));
dbaseFunc.performWorkOnDb();
} catch (InterruptedException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
public void initialize() {
Task<Void> task = new Task<>() {
#Override
protected Void call() {
try {
Double d = 0.0;
for (int i = 1; i <= 100; i++) {
Thread.sleep(100);
d = 1.0 * i / 100;
updateProgress(d, 1);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
};
task.progressProperty().addListener((obs, oldProgress, newProgress) -> {
System.out.println((newProgress.doubleValue() * 100) + "% completed");
});
new Thread(task).start();
}
I have a Problem with my JavaFX app. It is devided in to parts - a main Stage and a Stage as a Dialog. When i close the main stage setonclosedrequest is fired as expected, but setoncloserequest of the dialog Stage is never fired. What i do wrong ? Here is my code:
Main App:
public class TestApp extends Application{
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
FXMLDialogLoader loader = new FXMLDialogLoader("de/pasa/fxml/Dialog.fxml");
loader.setController(new DialogController(primaryStage));
loader.loadPrimaryStage(primaryStage, "Main App");
primaryStage.setOnCloseRequest(e->{
System.out.println("Do something before Close");
});
}
}
Controller:
public class DialogController implements Initializable{
#FXML private Button bOpen;
private Stage parentStage = null;
public DialogController(Stage parentStage) {
this.parentStage=parentStage;
}
#Override
public void initialize(URL location, ResourceBundle resources) {
bOpen.setOnAction(e->{
FXMLDialogLoader loader=new FXMLDialogLoader("de/pasa/fxml/Test.fxml", parentStage);
Stage dlgStage=loader.loadDialog();
dlgStage.setOnCloseRequest(t->{
//never reached - not fired, why ?
System.out.println("Do something before Dialog closed");
});
});
}
}
FXMLLoader:
public class FXMLDialogLoader {
private String _fxmlPath=null;
private String _title=null;
private Object _controller=null;
private ResourceBundle _bundle=null;
private Stage _parentStage=null;
private Stage _primaryStage=null;
private Stage stage=null;
private StageStyle _style=null;
private String _iconPath=null;
private LoggerEX _log = LoggerEX.getLogger(FXMLDialogLoader.class);
public FXMLDialogLoader(String fxmlPath){
this(fxmlPath,null);
}
public FXMLDialogLoader(String fxmlPath,Stage parentStage){
this(fxmlPath,parentStage,"Dialog",null,null,StageStyle.UTILITY);
}
public FXMLDialogLoader(String fxmlPath,Stage parentStage,String title,Object controller,ResourceBundle bundle,StageStyle style){
_fxmlPath=fxmlPath;
_parentStage=parentStage;
_controller=controller;
_bundle=bundle;
_title=title;
_style=style;
}
public Stage loadDialog(){
FXMLLoader loader=new FXMLLoader(getClass().getClassLoader().getResource(_fxmlPath));
loader.setController(_controller);
loader.setResources(_bundle);
try {
Parent root=loader.load();
Scene scene=new Scene(root);
if(_primaryStage==null){
stage=new Stage();
}
else{
stage=_primaryStage;
}
if(_iconPath!=null){
stage.getIcons().add(new Image(new FileInputStream(new File(_iconPath))));
}
stage.setTitle(_title);
stage.setScene(scene);
if(_primaryStage==null){
stage.initModality(Modality.WINDOW_MODAL);
}
stage.initStyle(_style);
if(_primaryStage==null){
stage.initOwner(_parentStage);
}
if(_primaryStage==null){
stage.showAndWait();
}
else{
stage.show();
}
stage.centerOnScreen();
}
catch(IOException ex){
ex.printStackTrace();
_log.error(ex);
}
return stage;
}
public Stage getDialogStage(){
return stage;
}
public Stage loadPrimaryStage(Stage primaryStage,String title){
return loadPrimaryStage(primaryStage,title,null);
}
public Stage loadPrimaryStage(Stage primaryStage,String title,String iconPath){
_primaryStage=primaryStage;
setTitle(title);
setIconPath(iconPath);
setStageStyle(StageStyle.DECORATED);
_primaryStage.centerOnScreen();
loadDialog();
return _primaryStage;
}
public void setIconPath(String iconPath){
_iconPath=iconPath;
}
public void setTitle(String title){
_title=title;
}
public void setStageStyle(StageStyle style){
_style=style;
}
public void setController(Object controller){
_controller=controller;
}
public void setResourceBundle(ResourceBundle bundle){
_bundle=bundle;
}
}
You are calling showAndWait() to display the dialog, which, as the method name implies, waits until the dialog is dismissed before returning. Only after the dialog is dismissed do you then register the onCloseRequest handler: by then it is too late to process the event.
Following this topic Context menu insight JavaFX Task I want to create Context Menu in JavaFX Task. I tested this code:
static private StringBuilder stringBuilder = new StringBuilder();
private static ContextMenu contextMenu;
private static CountDownLatch menuCreated = new CountDownLatch(1);
static synchronized void writeString(String s)
{
stringBuilder.append(s).append("\n");
}
public static BorderPane init(BorderPane bp) throws Exception
{
System.out.println("***** CALLED");
Task task = new Task()
{
#Override
protected Void call() throws Exception
{
writeString("Task started");
writeString(Thread.currentThread().getName() + " is fx thread: "
+ Platform.isFxApplicationThread());
Platform.runLater(new Runnable()
{
#Override
public void run()
{
writeString(Thread.currentThread().getName() + " is fx thread: "
+ Platform.isFxApplicationThread());
try
{
contextMenu = new ContextMenu();
contextMenu.setId("Test ID");
writeString("Created context menu");
menuCreated.countDown();
}
catch (Exception ex)
{
writeString(ex.getMessage());
ex.printStackTrace();
}
finally
{
writeString("Test");
}
}
});
writeString("Task finished");
return null;
}
};
new Thread(task).start();
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("About");
}
});
MenuItem item2 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("Preferences");
}
});
MenuItem item3 = new MenuItem("Close");
item3.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
//flow.getChildren().remove(bp);
}
});
contextMenu.getItems().addAll(item1, item2, item3);
bp.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>()
{
#Override
public void handle(ContextMenuEvent event)
{
//contextMenu.hide();
System.out.println("*********************** Shown Context Menu ***!!!!!!!");
contextMenu.show(bp, event.getScreenX(), event.getScreenY());
event.consume();
}
});
bp.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent event)
{
contextMenu.hide();
}
});
menuCreated.await();
return bp;
}
With this code I set Context Menu for BorderPane. When I click with the right mouse button I see the debug message *********************** Shown Context Menu ***!!!!!!! but there is no context menu. Can you help me to fix this code?