Open SWayfarer opened 4 years ago
Hi! In such situations, I use a slightly different approach. You have two ways to create dialog (modal) boxes.
Create build-in dialog box:
public class MyDialogBox extends Prototype {
// dialog window
public ResizableItem window = null;
public MyDialogBox() {
setPassEvents(false); // this prevent pass events through MyDialogBox
setStyle(Style.getFrameStyle()); // Frame style is Ok
setBackground(0, 0, 0, 150); // transparent background
// inside window we will add all another items (buttons, labels, titlebar and
// etc.)
window = new ResizableItem();
}
@Override
public void initElements() {
// window appearance
window.setBackground(55, 55, 55);
window.setShadow(5, 3, 3, new Color(0, 0, 0, 180));
window.setSize(400, 300);
window.setAlignment(ItemAlignment.HCENTER, ItemAlignment.VCENTER);
// add window
addItem(window);
// add titlebar and button to the window
TitleBar title = new TitleBar("MyDialogBox:");
ButtonCore okButton = new ButtonCore("Ok");
okButton.setWidth(100);
okButton.setAlignment(ItemAlignment.BOTTOM, ItemAlignment.HCENTER);
okButton.setMargin(0, 0, 0, 20);
window.addItems(title, okButton);
// change actions of titlebar close button
title.getMinimizeButton().setVisible(false); // hides button
title.getMaximizeButton().setVisible(false); // hides button
title.getCloseButton().eventMouseClick.clear();
title.getCloseButton().eventMouseClick.add((sender, args) -> {
close(); // now it closes the MyDialogBox not entire window
});
// Ok button will set the result
okButton.eventMouseClick.add((sender, args) -> {
_result = true; //set result
close(); // close
});
}
// event which will invoked when MyDialogBox is closed to perform actions.
public EventCommonMethod onCloseDialog = new EventCommonMethod();
// handler for self distaction after closing.
private CoreWindow _handler = null;
// show the MyDialogBox.
public void show(CoreWindow handler) {
_result = false;
_handler = handler;
_handler.addItem(this);
this.setFocus();
}
// close the MyDialogBox.
public void close() {
// perform assigned actions
if (onCloseDialog != null)
onCloseDialog.execute();
// and remove MyDialogBox
_handler.removeItem(this);
}
// getting result
boolean _result = false;
boolean getResult() {
return _result;
}
}
Create separate window with com.spvessel.spacevil.DialogWindow:
public class MyDialogBox extends DialogWindow {
public MyDialogBox() { }
@Override
public void initWindow() {
// window appearance
setParameters("MyDialogBox:", "MyDialogBox:", 400, 300, false);
setBackground(55, 55, 55);
setSize(400, 300);
isCentered = true;
// add titlebar and button to the window
TitleBar title = new TitleBar("MyDialogBox:");
ButtonCore okButton = new ButtonCore("Ok");
okButton.setWidth(100);
okButton.setAlignment(ItemAlignment.BOTTOM, ItemAlignment.HCENTER);
okButton.setMargin(0, 0, 0, 20);
addItems(title, okButton);
// change actions of titlebar close button
title.getMinimizeButton().setVisible(false); // hides button
title.getMaximizeButton().setVisible(false); // hides button
title.getCloseButton().eventMouseClick.clear();
title.getCloseButton().eventMouseClick.add((sender, args) -> {
close(); // now it closes the MyDialogBox
});
// Ok button will set the result
okButton.eventMouseClick.add((sender, args) -> {
_result = true; //set result
close(); // close
});
}
// event which will invoked when MyDialogBox is closed to perform actions.
public EventCommonMethod onCloseDialog = new EventCommonMethod();
// show the MyDialogBox.
public void show(CoreWindow handler) {
_result = false;
super.show();
}
// close the MyDialogBox.
public void close() {
super.close();
// perform assigned actions
if (onCloseDialog != null)
onCloseDialog.execute();
}
// getting result
boolean _result = false;
boolean getResult() {
return _result;
}
}
And the call of such windows is the same:
ButtonCore btn = new ButtonCore();
btn.eventMouseClick.add((sender, args) -> {
MyDialogBox myBox = new MyDialogBox();
// describe onCloseDialog event
myBox.onCloseDialog.add(() -> {
System.out.println("Ok is clicked? Result: " + myBox.getResult());
});
// show dialog
myBox.show(this);
});
Hi!
I meant the ability to interrupt the current thread before closing the window. I wrote simple code that should do this, but it does not work as I expected. The result is "magically" not predictable.
It must be something like: %some code% dialog.showAndWait(); %another code%
where %another code% runs after dialog close.
Hi! Good. I just compiled a new version, and you need to test it first (but be aware that this version not only solved your “dialog box” problem, but also contains many improvements that have not been properly tested yet). link: spacevil-jvm-0.3.5.5
And you can do that things: DialogBox example with showAndWait() method:
public class MyDialogBox extends DialogWindow {
public MyDialogBox() {
}
@Override
public void initWindow() {
// window appearance
setParameters("MyDialogBox:", "MyDialogBox:", 400, 300, false);
setBackground(55, 55, 55);
setSize(400, 300);
isAlwaysOnTop = true;
// add titlebar and button to the window
TitleBar title = new TitleBar("MyDialogBox:");
ButtonCore okButton = new ButtonCore("Ok");
okButton.setWidth(100);
okButton.setAlignment(ItemAlignment.BOTTOM, ItemAlignment.HCENTER);
okButton.setMargin(0, 0, 0, 20);
addItems(title, okButton);
// change actions of titlebar close button
title.getMinimizeButton().setVisible(false); // hides button
title.getMaximizeButton().setVisible(false); // hides button
title.getCloseButton().eventMouseClick.clear();
title.getCloseButton().eventMouseClick.add((sender, args) -> {
close(); // now it closes the MyDialogBox
});
// Ok button will set the result
okButton.eventMouseClick.add((sender, args) -> {
_result = true; // set result
close(); // close
});
}
CoreWindow _handler = null;
// show the MyDialogBox.
public void show(CoreWindow handler) {
_handler = handler;
_result = false;
super.show();
}
// close the MyDialogBox.
public void close() {
try {
synchronized (_handler) {
_handler.notify();
}
} catch (Exception e) {
}
super.close();
}
// getting result
boolean _result = false;
boolean getResult() {
return _result;
}
void showAndWait(CoreWindow handler) {
show(handler);
try {
synchronized (handler) {
handler.wait();
}
} catch (Exception e) {
}
}
}
And you can use it in your way:
btn.eventMouseClick.add((sender, args) -> {
MyDialogBox msg = new MyDialogBox();
msg.showAndWait(this);
// Do some after msg is closed
System.out.println("try get value " + msg.getResult());
});
PS. Tell me if it works for you.
Unfortunately, this did not help, the result is the same. Sometimes it works correctly, and sometimes it hangs on a lock.
Upd: Those. if you call the dialog many times, then you can catch the lock
Ok. I will continue to investigate the problem further. Why don't you want to use the "onCloseDialog" event?
I use dialogs as built-in to other programs, where they represent the implementation of some interface for interaction. In most cases, I / O stops the process until it is completed, so the use of a reactive approach will lead to the use of crutches specifically for UI on spacevil.
In addition, sometimes it is necessary to collect information from several windows in a row, then from a code point of view the reactive approach would look awful
Ok. I understand you point of view. In most cases, I am very limited due to the use of GLFW in SpaceVIL. That's why the dialogs in SpaceVIL work like this.
I have another version for you.
link: spacevil-jvm-t2
I added 2 methods for CoreWindow: hold()
and proceed()
. You should use them exactly as shown below.
Tell me if it works. Usage:
btn.eventMouseClick.add((sender, args) -> {
hold(); // important!!!
// if you describe `eventMouseClick` inside non-CoreWindow class use this approach:
// btn.getHandler().hold();
MyDialogBox msg = new MyDialogBox();
msg.showAndWait(this);
// Do some after msg is closed
System.out.println("try get value " + msg.getResult());
});
MyDialogBox (see showAndWait()
method)
public class MyDialogBox extends DialogWindow {
public MyDialogBox() { }
@Override
public void initWindow() {
// window appearance
setParameters("MyDialogBox:", "MyDialogBox:", 400, 300);
setBackground(55, 55, 55);
setSize(400, 300);
isAlwaysOnTop = true;
// add titlebar and button to the window
ButtonCore okButton = new ButtonCore("Ok");
okButton.setWidth(100);
okButton.setAlignment(ItemAlignment.BOTTOM, ItemAlignment.HCENTER);
okButton.setMargin(0, 0, 0, 20);
addItems(okButton);
eventClose.clear();
eventClose.add(() -> {
close();
});
// Ok button will set the result
okButton.eventMouseClick.add((sender, args) -> {
_result = true; // set result
close(); // close
});
}
CoreWindow _handler = null;
// show the MyDialogBox.
public void show(CoreWindow handler) {
_handler = handler;
_result = false;
super.show();
}
// close the MyDialogBox.
public void close() {
try {
synchronized (_handler) {
_handler.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
super.close();
}
// getting result
boolean _result = false;
boolean getResult() {
return _result;
}
void showAndWait(CoreWindow handler) {
try {
synchronized (handler) {
show(handler);
handler.wait();
handler.proceed(); // important!!
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Yes, it seems to work. Thank you! =)
And... In the process of analyzing the framework, I tried to look at the insides to understand the cause of the problem, but the code turned out to be obfuscated. Why obfuscate MIT-licensed code?
For now I kinda not ready to give the source code now... but I do not limit any use of examples and SpaceVIL binary.
Hi!
I am writing a dialog box and I need the current thread to wait for the dialog to finish working. For this, for example, in Java FX there is a method to showAndWait. Is there an analog here?