I am using Vaadin MessageBox, the problem that I have which is logic is that the code after MessageBox runs immediately and doesn't wait for your MessageBox answer. I tried to pack my code in a function which returns a boolean. But it seems impossible to do it with MessageBox(), here is a sample of what I want to do:
private boolean Delete(){
return true;
}
private boolean IsDone(){
MessageBox
.createQuestion()
.withCaption("Delete")
.withMessage("Are you sure?")
.withYesButton(()-> return Delete()) //here is where i have problem
.withNoButton(()-> {})
.open();
}
I tried also,
.withYesButton(()-> {return Delete();})
it seems to work like this but without return true;
.withYesButton(()-> {if(Delete){
return true; //doesn't work!
System.out.printLn("Works!"); // works :-?
}})
anyone know this situation or has any idea?
Actions that require user interaction are not "stopping" code execution. You need to organize your code so that it continues in handlers for yes and no buttons. So make sure that your "flow" stops to showing confirmation box and continues after yes or no has been answered.
private void IsDone(){
MessageBox
.createQuestion()
.withCaption("Delete")
.withMessage("Are you sure?")
.withYesButton(()-> onUserAnsweredYes())
.withNoButton(()-> onUserAnsweredNo())
.open();
}
The withYesButton method gets a Runnable that is gonna be executed when the user press the yes button. Let's see for a moment the implementation of Runnable:
public interface Runnable {
void run();
}
As you see, run returns void, so you cannot return any value, like true. Instead, you must provide the code you use to delete anything you want, like:
MessageBox
.createQuestion()
.withCaption("Delete")
.withMessage("Are you sure?")
.withYesButton(()-> codeToDeleteSomething())
.open();
Related
I have a jframe i want to display while my main frame is running. i want to pause my main code, until the user does the necessary actions on the other frame. I've read a lot of solutions but i need to see it done for my code to understand and grasp it fully. i do not want to use jdialog like I've seen listed as an answer before. My main goal is to understand better threading so that i can use what i learn in different cases.
With the code I've created, when running the thread, only just the frame loads, none of the other features are there on the frame. (the frame is simple it has a label, a list the user selects from, and a button to basically return the chosen list value.) its like the thread is cut off from completing or something.
here is my class calling the screen:
public class myThread implements Runnable {
String result = null;
public void run() {
MessageScreen ms = new MessageScreen();
ms.setVisible(true);
}
public String getResult() {
return result;
}
public void setResult(String AS) {
result = AS;
}
}
in my main code, a method is called that is returning a String[] value, with this method at some point i have the following code calling the new thread to get the value necessary to return in the original main method:
myThread mt = new myThread();
Thread t = new Thread(mt);
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
myreturn = new String[] {"true", mt.getResult()};
without listing the whole code for the second frame, when the user presses the button, and at the end of the listener tied to the button press the i want to close the frame and return a string that was selected from the list:
jf.dispose();
myt.setResult(AdminSelection);
in the frame class, i have the following instance variables declared:
String AdminSelection = null;
myThread myt;
i hope this is enough information for someone to help me out and understand whats gone wrong here.
The function join() waits until the end of the run() method, when you do t.join(), your thread is already or almost ended. This is because in your run() method there is nothing that blocks the thread until the user has clicked the confirm button. And is better like this!
There is no sense to create a thread here, you should use a callback, or more generally in Java, a listener. You can take a look at Creating Custom Listeners.
But, especially if you want to pause your main code, you should use a (modal) JDialog which is made for this! Don't try to block the UI by yourself, you could block the UI thread (handled by Swing/AWT) by mistake. Creating a JDialog is better because everything is already made for this usage on the UI thread.
Also, you must know that create a Thread is really long, use a Thread when you really need it.
I have an interface method which is supposed to return a Future object.
Future<Result> doSomething()
The implementation of this method shows some ui (javafx).
One of the ui elements has a listener, that needs to be called in order to receive the actual result, I need.
How do I achieve this?
Is there a better solution?
Here an example action I need to wait for:
// this is some framework method I cannot change
#Override
public Data execute(Data data) {
Future<Data> dataFuture = handler.doSomething(data);
// this should basically wait until the user clicked a button
return dataFuture.get();
}
// handler implementation
public Future<Data> doSomething(Data data) {
// the question is how to implement this part, to be able to
// return a future object
Button button = new Button("Wait until click");
// create thread that waits for the button click ?!????
// modify incoming data object when the button was clicked
// somehow create the Future object that's bound to the button click
return future;
}
This is what I want to achieve:
my method doSomething shows a new scene(ui) with a button on it
and returns immedeately the future object
future.get() waits until the user pressed the button
limitations: it has to be done with no extra library and on >=Java7
Use a javafx.concurrent.Task. It derives from FutureTask. There are extensive examples in the linked javadoc on Task usage.
Oracle also provide a tutorial which discusses Task usage:
Concurrency in JavaFX
I think this is what you want, but I may have understood the question, if so, please edit the question a bit to clarify requirements (perhaps with an mcve). The bit that makes me a little unsure is the part in your title "waiting for ui event?", I'm not quite sure what that means in this context.
This is a solution I was searching for. It's not very nice, since the Thread.sleep doesn't convince me.
but now you propably get an idea of what I want to achieve
// make sure this is not called on the ui thread
public Future<Data> doSomething(Data data) {
WaitingFuture future = new WaitingFuture(data);
Platform.runLater(() -> {
Button button = new Button("Wait until click");
button.setOnAction(future);
// show button on ui...
});
favouriteExecutorService.submit(future);
return future;
}
static class WaitingFuture extends Task<Data> implements EventHandler<ActionEvent> {
private Data data;
WaitingFuture(Data originalData) {
this.data = originalData;
}
private Data waitingData;
#Override
public void handle(ActionEvent event) {
waitingData = data.modify();
}
#Override
protected Data call() throws Exception {
while (waitingData == null) {
Thread.sleep(100);
}
return waitingData;
}
}
I would like to set a CheckBox ReadOnly when my new window pop up.
Here is my code.
getForm().getField("foreign").addValueChangeListener(
new Property.ValueChangeListener(){
#Override
public void valueChange(Property.ValueChangeEvent event) {
changeValueForCurrency(event.getProperty().getValue());
}
}
);
Tried to let it happen by calling the changeValueForCurrency()
changeValueForCurrency(getForm().getField("foreign"));
Does not work.
My mate told me something about to fire it, but It doesn't has any methods like firing it.
Also, I tried to set this method below true;
setImmediate(true);
Still does not work
Did you try to do setImmediate() after adding the listener? i had this issue with a table.
I was building a small test tool with Java Swing using Netbeans IDE.
I am trying to update a label, which is somehow not getting 'repainted'/'refreshed'. I looked into a couple of similar questions on SO but was not able to resolve my problem.
private void excelFileChooserActionPerformed(java.awt.event.ActionEvent evt)
{
if(!JFileChooser.CANCEL_SELECTION.equals(evt.getActionCommand()))
{
String selectedFile = excelFileChooser.getSelectedFile().getAbsolutePath();
loaderLabel.setText("Please Wait..");
try {
//This is sort of a blocking call, i.e. DB calls will be made (in the same thread. It takes about 2-3 seconds)
processFile(selectedFile);
loaderLabel.setText("Done..");
missingTransactionsPanel.setVisible(true);
}
catch(Exception e) {
System.out.println(e.getMessage());
loaderLabel.setText("Failed..");
}
}
}
loaderLabel is a JLabel and the layout used is AbsoluteLayout.
So, my problem is "Please Wait..." is never shown. Although call to the method processFile takes about 2-3 seconds, "Please Wait..." is never shown. However, "Done..."/"Failed..." are shown.
If I add a popup (JOptionPane) before the call to processFile, "Please Wait.." is shown. I am not able to clearly understand why this is happening.
Is there a "good practice" that I should follow before a heavy method call? Do I need to call an explicit repaint/refresh/revalidate?
You need to call
processFile(selectedFile);
in another thread (not in the AWT thread). To do so you can do something like this :
Thread t = new Thread(){
public void run(){
processFile(selectedFile);
// now you need to refresh the UI... it must be done in the UI thread
// to do so use "SwingUtilities.invokeLater"
SwingUtilities.invokeLater(new Runnable(){
public void run(){
loaderLabel.setText("Done..");
missingTransactionsPanel.setVisible(true);
}
}
)
}
};
t.start();
Please not that I didn't work with swing for a long time, so there may be some syntax issues with this code.
Have you tried dispatching the call to the EDT with SwingUtilities.invokeLater() ?
http://www.javamex.com/tutorials/threads/invokelater.shtml
I tried this
private void botaoConfIOMouseClicked(java.awt.event.MouseEvent evt) {
ConfigurarIO popup = new ConfigurarIO();
popup.setVisible(true);
botaoConfIO.setEnabled(false); //this line to avoid multiple dialogues
setIO=popup.getConfig(); //i need to get this boolean from the dialogue "ConfigurarIO"
//part of the program only to make my logic from the setIO
if(setIO[0]==false){
jToggleButton1.setEnabled(false);
jToggleButton1.setText("SaĆda");
}
else{
jToggleButton1.setEnabled(true);
if(jToggleButton1.isSelected()) jToggleButton1.setText("Pino 1 ON");
else jToggleButton1.setText("Pino 1 OFF");
}
}
And this is the dialogue
public class ConfigurarIO extends javax.swing.JFrame {
boolean[] inOut=new boolean[8];
boolean ok=false;
/** Creates new form ConfigurarIO */
public ConfigurarIO() {
initComponents();
}
public boolean[] getConfig(){
return inOut;
}
public boolean getOK(){
return ok;
}
public void setOK(){
ok=false;
}
//the logic was emited
private void botaoOKMouseClicked(java.awt.event.MouseEvent evt) {
dispose();
ok=true;
System.out.println(ok);
}
The problem is that the setIO is not modified by the second interface and, If I set this to make a loop broken only by the "ok" boolean, the window with the setting interface doesn't open. This is a very explored problem but I am new to Netbeans and I couldn't find it on Google. Thanks for the attention
Print screen: http://4.bp.blogspot.com/-B7VWmPelJek/T2ysJV8PJcI/AAAAAAAABqQ/0waWxxEEHkw/s320/temp.png
You haven't said whether a frame is required for some reason, or whether a dialog would do, or whether whatever it is needs to be modal.
The reason the frame doesn't show up if you loop is that you're on the Swing dispatch thread (since you are in a routine that responded to a mouse click), and until it returns, it isn't going to update the screen.
You cannot just call a method on the "frame dialog" to get a value until you know that the dialog has set the value. I would pass my calling class to the dialog as a parameter on the constructor, and then have the dialog code call a method on the calling class when it's all done. If you need to know when this happens, then you'll have to treat it as an event in your calling class; I can't guess what you need for that without knowing more about what you're trying to do overall.
If you need to wait until the dialog is done, and don't need the user to be able to do anything until it is done, then what you want is a "modal" dialog, and I recommend looking at JOptionPane and its various dialog options for what you want to do. THEN the call from your class can be synchronous, i.e., you can call the dialog and, when the call completes, the dialog is all done. Then you don't need to pass the calling class to the frame, since it doesn't need to notify you that it's done; you know it's done when your call completes, and you can call a method such as you have already done to get the value that you want.
Incidentally, your subclass-of-JFrame constructor doesn't call super(); I recommend you do that...
rc
// we will make this modal=true, to block access to the parent frame
public class ConfigurarIO extends javax.swing.JDialog {
For more details, see:
How to Make Dialogs
How to Use Modality in Dialogs