I have a program that in somepoint needs to open a dialog "anDialog" which contains buttons that opens more dialogs "B" and "C", some of those child dialogs are not modal, so if I set the dialog "anDialog" as modal it raises above them right after opening and blocks them. But if I set "anDialog" as not modal, the class which calls it keeps running and it should not.
Calling dialog "A"
OpenAttributesAssistentCommand attrAssistent = new OpenAttributesAssistentCommand((InternalInterfaceAttributes) parent, transcriptor);
attrAssistent.execute();
//... more stuff after
Execute
public void execute() {
AttributesAssistentDialog anDialog = new AttributesAssistentDialog(intFrame, transcriptor);
anDialog.setVisible(true);
}
I want that the caller waits the dialog "anDialog" finishing before keep running. It would be nice if it could understand the difference between closing and btnOk. Also if there is a way to make it don't block non-modal childs it would be ok.
I believe you can do this with a SecondaryLoop, which blocks a thread without blocking the user interface until its exit method is called:
private SecondaryLoop attrAssistantLoop;
// ...
OpenAttributesAssistentCommand attrAssistent =
new OpenAttributesAssistentCommand(
(InternalInterfaceAttributes) parent, transcriptor);
attrAssistantLoop = Toolkit.getSystemEventQueue().createSecondaryLoop();
attrAssistent.execute(attrAssistantLoop);
attrAssistantLoop.enter(); // Wait for dialog to close
// OpenAttributesAssistentCommand class
public void execute(SecondaryLoop loop) {
AttributesAssistentDialog anDialog = new AttributesAssistentDialog(intFrame, transcriptor);
anDialog.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent event) {
if (loop != null) {
loop.exit(); // Allow waiting code to proceed
}
}
});
anDialog.setVisible(true);
}
Related
I use Vaadin version 8.9.3. I need to show a modal window when I click a button. In this window, the user enters the information, clicks on the button, the information is saved and displayed in a table in the main window.
Main page:
Modal page:
To display the modal window I use BrowserWindowOpener. In order not to overload the question, I will give only a small piece of code. The FormLayout in which there is TextField("uid"), Grid and Button("Создать") - DeviceForm:
private BrowserWindowOpener opener = new BrowserWindowOpener(ButtlonClickUI.class);
private DeviceConfigsService configsService = DeviceConfigsService.getInstance();
private Grid<DeviceConfigs> grid = new Grid<>(DeviceConfigs.class);
public DeviceForm(MyUI myUI, Devices device) {
opener.extend(button);
opener.setFeatures("resizable");
configsService.setDevice(device);
configsService.addSaveEventListener(new OnSaveEventListener() {
#Override
public void SaveEvent() {
updateList();
}
});
grid.setColumns(NAME_COLUMN, VERSION_COLUMN, STATE_COLUMN);
grid.getColumn(NAME_COLUMN).setCaption(NAME_COLUMN_NAME).setExpandRatio(1);
grid.getColumn(STATE_COLUMN).setCaption(STATE_COLUMN_NAME).setExpandRatio(1);
grid.getColumn(VERSION_COLUMN).setCaption(VERSION_COLUMN_NAME).setExpandRatio(1);
updateList();
}
public void updateList() {
List<DeviceConfigs> configs = configsService.findAll();
if(configs.size() == 0) {
delete.setVisible(false);
}
grid.setItems(configs);
}
Here, config service is a service that allows you to save, delete and find the information displayed in the grid (DeviceConfigs), in this case, it does not matter which one. OnSaveEventListener is the listener I created, called when the save method in configsService is called:
public synchronized void save(DeviceConfigs entry) {
if(entry == null) {
LOGGER.log(Level.SEVERE,
"DeviceConfigs is null");
return;
}
if(entry.getName() == null || entry.getName().isEmpty()) {
LOGGER.log(Level.SEVERE,
"DeviceConfigs name is null");
}
try {
entry = (DeviceConfigs) entry.clone();
} catch (Exception e) {
throw new RuntimeException(e);
}
device.putConfig(entry);
if(listener != null) { listener.SaveEvent(); }
}
UI that is called in opener:
public class ButtlonClickUI extends UI {
private DeviceConfigsService configsService = DeviceConfigsService.getInstance();
private Button close = new Button("close", VaadinIcons.CLOSE);
#Override
protected void init(VaadinRequest request) {
VerticalLayout layout = new VerticalLayout();
layout.addComponent(close);
...
close.addClickListener(event ->{
configsService.save(new DeviceConfigs(requestStr.getValue(), true, typeOfClick.getValue()));
closeThis();
});
}
private void closeThis() {
JavaScript.eval("close()");
// Detach the UI from the session
getUI().close();
}
}
The problem is this - I couldn't think of a better way to track the event of writing new data and closing the modal window to update the values of the table until I got to creating a listener.
But now, after clicking the Close button in the modal window, it closes, the data is updated but not displayed until I interact with some element on the main page (by trial and error, I got to the point where the components on the main page will not update their visibility until the modal window closes and the main page returns focus).
But I can't think of any way to automatically update the table values in the main menu when the modal window is closed.
Any possible solution to the problem, please.
My program opens a dialog if a certain string is clicked inside a StyledText. So in the mouseDown() I first want to check what has been clicked and then open a dialog. This works. After closing the dialog the mouseUp() is not called. This leads to selecting the text when moving the cursor, as if the user tries to select a text.
I can reproduce the behavior by performing the following tasks:
Click on String in StyledText
-> Dialog Opens
Close Dialog
Move Mouse without clicking
-> Text gets marked as selected
In my use case I don't need mouseUp() to be fired. But having it not fired means the OS assumes that the mouse button is still down and selects text. This may be the correct behavior if a dialog opens and steals the focus. But than there must be a possibility to tell the system, that the mouse button has been released.
myStlyedText.addMouseListener(new MouseListener() {
#Override
public void mouseUp(MouseEvent e) {
System.out.println("MouseUp is fired");
}
#Override
public void mouseDown(MouseEvent e) {
if (certainStringClicked()) {
openDialog();
}
}
#Override
public void mouseDoubleClick(MouseEvent e) {}
});
I can verify that mouseUp() is not called because "MousUp is fired" is not printed on console.
What is the best way to handle this? I already tried to set focus on another widget (setFocus() and forceFocus()), but that didn't help.
I tried to call mouseUp myself:
Event event = new Event();
event.type = SWT.MouseUp;
event.button = 1;
MouseEvent mouseUpEvent = new MouseEvent(event);
mouseUp(mouseUpEvent);
This leads to the message "MousUp is fired", but the selection problem still exists.
I could move the code into the mouseUp() method, but that's not actually what I want. The dialog should appear immediately. What else can I do?
Try adding myStlyedText.notifyListeners(SWT.MouseUp, null); to your code.
It should work.
myStlyedText.addMouseListener(new MouseListener() {
#Override
public void mouseUp(MouseEvent e) {
System.out.println("MouseUp is fired");
}
#Override
public void mouseDown(MouseEvent e) {
if (certainStringClicked()) {
myStlyedText.notifyListeners( SWT.MouseUp, null );
openDialog();
}
}
#Override
public void mouseDoubleClick(MouseEvent e) {}
});
This is not a good solution. But it may be a workaround for some.
It is possible to add SWT.MODELESS to the shell style in the constructor of the Dialog, which extends jface.dialog.Dialog.
setShellStyle(SWT.MODELESS);
MouseUp() get's fired now.
The problem here is that it is possible to open many dialogs by clicking the text although one dialog is already open.
I have a method that returns a certain int variable, but this variable should be modified by the user using a JFrame that pops out when this method is called before it's returned.
So I thought of using a timer that would delay the return statement by certain a more-than-needed number of seconds and when the button for example is pressed, the timer would stop and the variable would change
Here is the method:
public static int c(){
x.setVisible(true);// x is the name of the frame
timer.schedule(new TimerTask() {
public void run() {
System.out.println("Text");
}
}, 5000);
return q;
}
And here is the ActionListener set on the button in the constructor:
d.addActionListener(new ActionListener(){ //d is the name of the button
#Override
public void actionPerformed(ActionEvent arg0) {
q=5;
timer.cancel();
x.setVisible(false);
}
});
But all it does is delaying the printing statement inside the run method, and of course i cannot return inside the delayed task since its type is void
Thanks
but this variable should be modified by the user using a JFrame that pops out when this method is called before it's returned
An application should only have a single main JFrame (see: The Use of Multiple JFrames: Good or Bad Practice?). Child windows should be a model JDialog. Then when show the dialog, the code after the setVisible() statement will not execute until the dialog is close.
You can create you own custom JDialog or it may be easier to use a JOptionPane. See the section from the Swing tutorial on How to Make Dialogs for more information and examples.
In a Swing (J)Dialog, setModal sets the modality - that is, whether the dialog should block input to other windows or not. Then, setVisible docs say for modal dialogs:
If the dialog is not already visible, this call will not return until the dialog is hidden by calling setVisible(false) or dispose.
Indeed, setVisible does return right away if the dialog is not modal. Sample code:
JDialog jd = new JDialog();
jd.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
/**
* If set to false, setVisible returns right away.
* If set to true, setVisible blocks until dialog is disposed.
*/
jd.setModal(false);
System.out.println("setting visible");
jd.setVisible(true);
System.out.println("set visible returned");
I want to make a dialog that doesn't block input to other windows, but still does block the caller. What is a good way to do this, now that setVisible doesn't block when the dialog is not modal?
Is there some rationale why setVisible's behavior depends on the modality?
I need to make a dialog that doesn't block input to other windows, but does block the caller so that I know when the dialog has been closed.
I usually solve this not by blocking the caller, but by using a callback of some sort - a simple interface that the dialog invokes when it's done. Let's say your dialog has an "OK" and a "Cancel" button and you need to distinguish which one is pressed. Then you could do something like this:
public interface DialogCallback {
void ok();
void cancel();
}
public class MyModelessDialog extends JDialog {
private final DialogCallback cbk;
private JButton okButton, cancelButton;
public MyModelessDialog(DialogCallback callback) {
cbk = callback;
setModalityType(ModalityType.MODELESS);
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onOK();
}
};
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
};
// Treat closing the dialog the same as pressing "Cancel":
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
onCancel();
}
};
}
private void onOK() {
cbk.ok();
}
private void onCancel() {
cbk.cancel();
}
}
Then you just pass in an instance of DialogCallback to the constructor:
MyModelessDialog dlg = new MyModelessDialog(new DialogCallback() {
public void onOK() {
// react to OK
}
public void onCancel() {
// react to Cancel
}
});
EDIT
Is there some rationale why setVisible's behavior depends on the modality?
Well, that's just how how modal windows are supposed to work, no? A modal window should block the current workflow when displayed, and a non-modal/modeless should not. See e.g. the Wikipedia pages on modal windows or dialog boxes.
Just put this.setModal(true) but not set the parent dialog on the constructor:
MyDialog dlg = new JDialog();
this.setModal(true);
When you call setVisible(true), it wont stop
The direct approach is by:
JDialog dialog = new JDialog(owner, ModalityType.DOCUMENT_MODAL);
I have found another way to do this. In the constructor of my progress bar, which extends javax.swing.JDialog, I added:
setModalityType(ModalityType.APPLICATION_MODAL);
I then overrode the setVisible method:
#Override
public void setVisible(boolean b) {
if (b) {
new Thread(new Runnable() {
#Override
public void run() {
showProgress();
}
}).start();
} else {
super.setVisible(false);
}
}
In the run(), you can see a call to showProgress(). This simply is:
public void showProgress() {
super.setVisible(true);
}
What happens here, is the setVisible() method of JDialog blocks. So I overrode it, and called setVisible() of the JDialog, in a thread. Resulting in it not blocking.
I have a JDialog which popup whenever my main application recieves an event.
The problem I'm facing is that the dialog pops up evenif the main window is minimised. A similar question was asked here but no answer was given as to how to solve this except a link to sun's guide on focus handling Hide JDialog window when the window lost focus.
Suppose I have the function createandshowDialog() such as
public void createAndShowDialog(boolean manualLaunch) {
if (manualLaunch || shouldShowMessage()) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (dialog == null) {
dialog = new xyzDialog(getPendingList());
}
GUIHelper.flash(PLAFHelper.getMainFrame(), true, false);
dialog.setVisible(true);
}
});
}
}
And the xyzDialog class is defined as :
public class xyzDialog extends SimpleStandardDialog
{
protected final static Log logger = LogFactory.getLog(xyzDialog.class);
private xyzPanel panel;
public xyzDialog(ObjectArrayList list) {
super(PLAFHelper.getMainFrame(), "Pending Cancel/Replace");
initializeLocalVars();
panel = new xyzPanel(list, mediator);
super.setSize(750,600);
setResizable(true);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
setModal(false);//todo: for testing...
if(PUMAGUIOptions.cFocusOnxyzPopup){
setFocusableWindowState(true);
validate();
}
else{
setFocusableWindowState(false);
validate();
}
}
The default behaviour should be such that it should not popup if main window is minimised or we explicitly set cFocusOnxyzPopup as false to force this default behaviour (which is the case when it is open on say secondary monitor and we are working on primary monitor or application is maximised or is in background i.e. is not the focusOwner.
I have set focusableWindowState as false so that it would not satisy the condition for gaining focus and return isFocusable as false if invoked as given in java-docs. But this is not working. Any suggestions?
USe JFrame's method
public synchronized int getExtendedState()
e.g. PLAFHelper.getMainFrame().getExtendedState()
if it's JFrame.ICONIFIED skip the dialog opening.
I have meet the same problem and search the stackoverflow ! finally, I find out the
corrent answer answered by Markus Lausberg in
JDialog lets main application lose focus
just calling the following method during dialog create:
setFocusableWindowState(false);
setFocusable(false);