I noticed a behavior that I can't explain. In my GUI, on a button click I display a custom Jdialog that has panel and bunch of textfield. I populate these textfields.
Here is the scenario I am seeing using pseduo code.
public void actionPerformed(ActionEvent e) {
CustomDialog viewDialog = new CustomDialog (Jframe, true);
viewDialog.setVisible(true);
viewDialog.populateInfo();
}
When the code above runs then all textfields are empty. However if I move the setVisible to after the populateInfo method then all the textFields are populated. Basically the JTextField.setText inside the populate info does not seem to have an affect if the setVisible happens before
Why is this!
Likely your CustomDialog class is a modal JDialog (also as suggested by the true 2nd constructor parameter). If so, then program flow in the calling code is blocked by the setVisible(true) call, and so your populateInfo() method will only be called after the dialog is no longer visible. The solution is as you already know -- call the method before displaying the dialog.
This is not a bug but a feature. :)
Seriously, since now you know for a fact when program code flow will be halted and when it will resume, and so you can safely query the dialog for its state after the setVisible(true) has been called, and feel confident that in the very least the dialog has been presented to the user, and the user has had time to interact with it and dispose of it.
Related
I need my JFrame to freeze/ become inaccessible, similar to how it would with a model JDialog or setEnabled(false).
In most cases I would use JDialog but in this instance I am running a dialog through a C library.
Going down the setEnabled(false) line also doesn't work because it, on setEnabled(true), will send the window to the back. And even using toFront() will cause the window to go to the back for a split second then come to the front again.
Is there a better way to go about doing this, or an I stuck with the slight imperfection of the window flickering.
Also if you are familiar with the library I am using LWJGL's NativeFileDialog wrapper.
I have found a pretty good solution to this issue, originally answered as part of this post. It takes the idea of using a JDialog, but instead of displaying some message it is completely transparent, invisible to the user.
final JDialog modalBlocker = new JDialog();
modalBlocker.setModal(true);
modalBlocker.setUndecorated(true);
modalBlocker.setOpacity(0.0f);
modalBlocker.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
Then we can simply display our modal and show our file dialog
// Using invoke later we show our dialog after our frame has been blocked
// by setVisible(true)
SwingUtilities.invokeLater(()->{
// show dialog
});
modalBlocker.setVisible(true);
modalBlocker.dispose(); // immediately release resources
Then we can call modalBlocker.setVisible(false) at any point to stop the modality effect on our frame.
Again this is the solution that worked for me, it is not mine. The code was written to integrate JavaFX with Swing by Sergei Tachenov, all credit goes to him!
I have written an application in Java that has a JFrame with options. I now want a certain action to be executed when the user has confirmed the dialog with "Ok". I was recommended to add a return value to JFrame.
Unfortunately, I don't have any experience and need some help. Here are the details.
I want to extend JFrame so that I can have an Enum "DialogResult" when closing a JFrame like in the .Net Framework. Well, the Enum is no problem. My problem is to replicate the ShowDialog method from WinForms of the .Net Framework working in Java for the class JFrame.
Below is an example code in C#:
// DlgOptions : Form
DlgOptions dlg = new DlgOptions();
if(dlg.ShowDialog() == DialogResult.Ok)
{
// do something only when "Ok" was clicked
}
Here's a link from MSDN with the behavior I want to replicate:
https://msdn.microsoft.com/de-de/library/c7ykbedk(v=vs.110).aspx
How can I best implement this? Thanks in advance.
EDIT:
I changed my DlgOptions class so it doesn't extend JFrame but JDialog. I also added an enumeration DialogResult and added a public property of this type in my DlgOptions. But I still have a problem. When I use this code:
// executed when user clicked a JMenuItem in a JMenuBar
DlgOptions dlg = new DlgOptions();
dlg.setModal(true);
dlg.setVisible(true);
if(dlg.DialogResult == DialogResult.OK)
{
// do something
}
the program continues running before the user closed the modal dialog. What can I do?
EDIT 2:
My JDialog contains two JButtons; one to confirm changes that were made and one to abort changing the preferences for the program. I have several JCheckBoxes the user can check or uncheck.
So a JOptionPane would not be what I want / need (as far as I know). That's why I need a modal JDialog. But my Java code above doesn't work as I want it to. I read on a German website of a Java book that a JDialog set to modal with
setModal(true);
would cause the program to wait until the dialog is closed. The problem is, that the code continues too early.
I have a message I want to display with some information in a modeless JDialog. The parent class will call the dispose method to close it at the right point. Here is the code I have:
private static void waitMessage() {
JOptionPane msg=new JOptionPane("Trying to get probes. Please wait ...",
JOptionPane.INFORMATION_MESSAGE,JOptionPane.DEFAULT_OPTION,
null,new Object[]{},null);
waitDialog=msg.createDialog("Probe Scan");
waitDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
waitDialog.setModalityType(ModalityType.MODELESS);
waitDialog.setSize(300,100);
waitDialog.setVisible(true);
}
The problem is that when I set ModalityType.DOCUMENT_MODAL the message displays as expected. Of course the JDialog blocks which is not what I need.
However, when I set ModalityType.MODELESS, I get this:
The JDialog does not block but the message text does not show up. Can someone explain why the ModalityType munges up the pane? TIA.
Manually adding a JOptionPane as the content for a JDialog, doesn't look right to me.
JOptionPane has a method designed to create a relevant JDialog instance, so better try that :
waitDialog = msg.createDialog("Probe Scan");
The reason you cannot close the dialog programmatically is that you do not keep a reference to the dialog. One way to do that is to have the waitMessage() method return the waitDialog instance. Or you can do as #Berger suggests.
Also,
waitDialog.setSize(300,100);
waitDialog.setVisible(true);
waitDialog.pack();
Why call setSize() and also pack() ? Make up your mind - do you want it a specifie size, or do you want it to appear its preferred size? And you should call setVisible() AFTER calling either setSize or pack.
There is no 'SetDefaultCloseOperation' method.
But there is a setDefaultCloseOperation method. (note the lower case first letter)
I have action thread and since it is Swing software, EDT.
I want my program to draw dialog window, and when it appears and it's filled with data, I want to get focus on selected text field.
Code flow: When I execute, it will run main thread, which calls method to draw dialog in invokeLater on EDT. Then program proceeds and in main thread it calls next methods that are being run in ED thread, again using invokeLater.
Problem: When I run it normally, it will not get focus on my text field.
Observation: But when I add some sleep (300 milis) to main thread, introducing time gap between one invokeLater call and next call in EDT, it works just like I want.
It seems to me like two actions added to AWT queue must be separated by some time, otherwise the second one doesn't work. I mean here setVisible(true) on dialog, and then requestFocus() on textField. Maybe requestFocus() only work when it sees dialog window drawn?
Question:How can I make things work, some synchronization method, maybe checking on dialog before calling requestFocus() (may be hard, because its in other class).
Solution:I forgot about most important thing - after calling setVisible() next thing I do is call to setEnabled(false) so user cannot do anything before data filling is completed. The problem was there, in setEnabled() I also was adding tasks to AWT queue (by invokeLater()). This task caused corruption of next steps. What I do now to fix it is calling this setEnabled(false) from my main thread inside invokeAndWait(). If I understand it correctly, now the dialog popup section is called first, and then main thread waits until EDT proceed his work and then setEnabled(false) is called. So technically user is not enabled to do anything after the window is drawn, which makes sense for me.
Anyway thanks for your responses.
It's better to call the focus setting from the dialog. Add a WindowListener to the dialog and use either
public void windowOpened(WindowEvent e)
public void windowActivated(WindowEvent e);
to set focus on the JTextField instance
The requestFocusInWindow() method can only be invoked on a visible component. That means the frame/dialog must already be visible when you invoke the method.
If you are trying to do this on a modal dialog you may have problems. Check out Dialog Focus for a simple listener you can use to set focus on a component.
I am working on a program that is meant to keep track of footraces. The program is set up so that a right click(though this may be changed) at any time will indicate a runner has passed the finish line. This is important so that you can do things and still mark a runner as passing at any point. To finish the race and compile results, there is a button. To prevent a misclick from prematurely stopping the timer, I have a dialog that confirms while the timer is still running. This dialog is also right-clickable to mark a runner as passing. I have a method that gets the input from the dialog as a boolean.
public static boolean showDialog(Frame parent, boolean modal,String text,RacePanel r)
{
ConfirmBox c=new ConfirmBox(parent,modal,text);//this makes the dialog
for(Component comp:c.getComponents())//this adds a listener for right-click events, to record passing runners
r.addListener(comp);
c.setVisible(true);
return c.yes;//yes is the boolean that should be returned
}
I originally had the dialog modal, so that the setVisible method would wait for the dialog to close. However, this made the program ignore mouse clicks on the rest of the screen. When I set it as not modal, this showDialog method returned immediately, which was always false. I don't actually care if the dialog is modal or not.
Is there a way to get MouseEvents with a modal dialog up or make a non-modal dialog wait until input?
Thank you in advance for your advice.
Couple of solutions:
Use hot keys to react - will be faster. so F11 means stop race, with F12 to confirm it. And F9 to indicate a runner has passed the finish line
There are JNI packages for this like at http://code.google.com/p/jintellitype/
Have the user click the button and type a key or world like "end" for a sample see http://code.google.com/p/baby-smash/source/browse/src/quick/KeyBoardListen.java Do not like a dialog box as they take time to render and can increase to the timer.
If you must use a dialog box then implement your own. in that class take an instance of your main class (or interface that your controller implements) then call a method on the controller when window is acted on (yes or no pressed or window closed - default). In the window close do not close the window but just hide it. this will mean you can show it faster next time. You can also load this class on start up to make it ready in the background
If you just want mouse events can try extending JFrame and then over ride (javadoc of java.awt.Component):
protected void processMouseEvent(MouseEvent e)
Processes mouse events occurring on this component by dispatching them to any registered MouseListener objects.
This method is not called unless mouse events are enabled for this component. Mouse events are enabled when one of the following occurs:
A MouseListener object is registered via addMouseListener.
Mouse events are enabled via enableEvents.
You will need to use listeners to listen for changes in the dialog class's state. For instance a WindowListener can listen for the dialog's window closing. If you want to listen for other state changes in the dialog's classes, consider creating "bound" properties or fields by use of a PropertyChangeListener.