I need to be able to tell if there are any modal dialogs open in my application. Is there any way to do this?
Solution
Alright, so based on the accepted answer, this is what I came up with do accomplish what I needed:
Window[] wins : myMainFrame.getOwnedWindows();
for(Window w : wins) {
if(w instanceof JDialog) {
JDialog jd = (JDialog)w;
if(jd.isModal() && jd.isVisible()) {
// back out of current operation (return null in my case)
return null;
}
}
Perhaps calling Window's getOwnedWindows() is what you're looking for, and all class that derive from Window will have this method, including JFrame and JDialog.
But I agree that more context would help!
Related
Here is the below code snippet, where i would like to display the dialog using JOptionPane.showConfirmDialog() by setting its parent as resultsTablePanel:
public class SearchResultsTablePanel extends JPanel{...}
public class DefaultSearchListener{
private SearchResultsTablePanel resultsTablePanel = null;
public void f(X x) {
int response = JOptionPane.showConfirmDialog(
resultsTablePanel,
"hai",
"Warning", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (response == JOptionPane.NO_OPTION) {
// do something
} else if (response == JOptionPane.YES_OPTION) {
// do something
} else if (response == JOptionPane.CLOSED_OPTION) {
// do something
}
}
}
My question:
For java swing api JOptionPane.showConfirmDialog(),
Do i need to pass resultsTablePanel as first argument?
or
Do i need to pass JOptionPane.getframeforcomponent(resultsTablePanel) as first argument?
It doesn't really matter.
As part of the processing, JOptionPane invokes getWindowForComponent on the argument before passing it through to the underlying JDialog (which is slightly more general).
As for the implicit question "What's the difference anyway?", well this has to do with modality. Here I would urge you to read Oracle's guide to modality.
JOptionPane uses the default modality type for JDialog, which is the Application-modal from the guide above. This means that the dialog will block input to all windows in the application, except windows that have the dialog as the parent. Hence, if you open 2 dialogs that have the same parent - you're in trouble, but if one has the other as the parent - then the child has controls and will transfer them to their parent once closed.
I want to know how to change the font of the text that appears in the context menu originated from right clicking at the icon that's all the way to the left in the titlebar of JFrames that use the default look and feel for decoration (JFrame.setDefaultLookAndFeelDecorated(true);).
I searched around and found nothing. I thought that I could use what I learned about changing the font of the titlebar's title, but that didn't worked.
Thanks in advance.
After some more messing around, I finally made it! I like Java so much that it makes me a bit sad how hard it is to do stuff like this. Anyway, I found a method here to recursively change the font of all components from a JFileChooser, but it doesn't work on the JPopupMenu (now I know the name) that pops up from the titlebar's icon. So I messed around with that method, used some casting, and was able to change the JMenuItems' font:
public static void setSubComponentFont (Component comp[], Font font) {
for (int x = 0; x < comp.length; x++) {
if (comp[x] instanceof Container) {
setSubComponentFont(((Container)comp[x]).getComponents(), font);
}
try {
//comp[x].setFont(font);
if (comp[x].toString().contains("JMenu")) {
for (Component y : ((JMenu)comp[x]).getPopupMenu().getComponents()) {
if (y.toString().contains("JMenu")) {
y.setFont(font);
}
}
}
} catch (Exception ex) {}
}
}
I was inspired to use .toString().contains() by this thread.
I also did this with nested loops, so the path to the menu items can be seen:
for (Component a : frame.getLayeredPane().getComponents()) {
System.out.println(a.toString());
if (a.toString().contains("MetalTitlePane")) {
for (Component b : ((Container)a).getComponents()) {
System.out.println(b.toString());
if (b.toString().contains("SystemMenuBar")) {
for (Component c : ((Container)b).getComponents()) {
System.out.println(c.toString());
for (Component d : ((JMenu)c).getPopupMenu().getComponents()) {
System.out.println(d.toString());
if (d.toString().contains("JMenu")) {
d.setFont(font);
}
}
}
}
}
}
}
Every System.out.println() gives a hint to what should go on the following if condition, so they should be used one at a time. This doesn't work for the JFileChooser's title font though. When I have time I'll either look further into it or ask another question.
So, if someone else needs it like I did, here it is. As a tip, System.out.println() and .toString() are your friends! That's how I learned what was contained in each object, and what path I needed to take to get to the objects of interest.
Thanks anyway!
I have a JButton which launches a JFileChooser. However the JFileChooser often takes a few seconds to come up, during which time the user might think that nothing is happening. I tried to make the button become disabled until the JFileChooser is finished with, but the disabling of the button doesn't even happen until the JFileChooser is loaded. Is there something I can do?
My code:
public void actionPerformed(ActionEvent e) {
System.err.println("clicked");
((JButton) e.getSource()).setEnabled(false);
System.err.println("set");
JFileChooser b = new JFileChooser("C:\\");
b.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int res = b.showOpenDialog((Component) e.getSource());
if (res == JFileChooser.APPROVE_OPTION) {
try {
//Blah
}
catch (Exception err) {
JDialog j = new JDialog(window, "An error occured:\n" + err.getMessage());
}
}
((JButton) e.getSource()).setEnabled(true);
}
Move these lines..
JFileChooser b = new JFileChooser("C:\\");
b.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
..from the action performed method to the constructor of the action listener, change them to..
b = new JFileChooser("C:\\");
b.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
..then declare..
private JFileChooser b;
..as a class attribute (so it is visible to the action performed method).
You might also want to give it a better name.
The chooser will be constructed when the class is created, and be ready for use when needed. This has the added benefit that the chooser will remember the position, size, path & file display type, the subsequent times the user activates the button.
Yet another strategy is to declare the chooser as a class attribute, don't instantiate it in the constructor, but check in the action performed if it is null, and if so, create and configure it.
Continued..
I might want to do something a bit slower like this at some point, that doesn't quite deserve its own thread.
With the last strategy I outlined, I was considering adding something that I will add now.
..Continued
..Of course, that last method will give exactly the same problem you describe, but just once when the user 1st clicks the button. For that situation, you should probably be looking to pop a JOptionPane with an indeterminate JProgressBar from inside a SwingWorker.
Obviously, a SwingWorker creates a new Thread, but OTOH, Thread objects in Java are cheap. There are a number of them running for any app. with a GUI. A couple more will not hurt.
Greetings,
I have a question with regards to limiting duplicate JInternalFrames to a JDesktopPane.
Basically, adding an instance JInternalFrame to the JDesktopPane is comprehensive.
But limiting duplicate JInternalFrame of the same instance on the JDesktopPane and making that instance to the top layer of the JDesktopPane.
How could I implement this?
Am I going to store all instances to a ArrayList and check whether it's the instance about the execute is already opened?
You're reply is highly appreciated.
Thanks,
Cyril H.
/**
* method to search for active internal frame windows
* and return true or false depending on the outcome. this method uses internalframe names
*/
public boolean searchIFrame(String search, JInternalFrame frame[])
{
for(int i = 0; i < frame.length; i++)
if(frame[i].getTitle().toString().equals(search))
return true;
return false;
}
//its implementation in your program. "Information Form" is the internalframe's name
//jdesk is the desktoppane object or instance
boolean srch = searchIFrame("Information Form", jdesk.getAllFrames());
if(!srch) {
VisitationForm at = new VisitationForm();
at.pack();
jdesk.add(at);
try
{
at.setSelected(true);
at.setVisible(true);
// We're done, so clear the feedback message
//bar.setString(" ");
//bar.setIndeterminate(false);
at.requestFocus();
}
catch (PropertyVetoException pve)
{
//bar.setString(" ");
//bar.setIndeterminate(false);
// Then display the error in a dialog box
System.out.println(pve);
}
}
In order to initialize all JTextfFields on a JPanel when users click a "clear button", I need to loop through the JPanel (instead of setting all individual field to "").
How can I use a for-each loop in order to iterate through the JPanel in search of JTextFields?
for (Component c : pane.getComponents()) {
if (c instanceof JTextField) {
((JTextField)c).setText("");
}
}
But if you have JTextFields more deeply nested, you could use the following recursive form:
void clearTextFields(Container container) {
for (Component c : container.getComponents()) {
if (c instanceof JTextField) {
((JTextField)c).setText("");
} else
if (c instanceof Container) {
clearTextFields((Container)c);
}
}
}
Edit: A sample for Tom Hawtin - tackline suggestion would be to have list in your frame class:
List<JTextField> fieldsToClear = new LinkedList<JTextField>();
and when you initialize the individual text fields, add them to this list:
someField = new JTextField("Edit me");
{ fieldsToClear.add(someField); }
and when the user clicks on the clear button, just:
for (JTextField tf : fieldsToClear) {
tf.setText("");
}
Whilst another answer shows a direct way to solve your problem, your question is implying a poor solution.
Generally want static dependencies between layers to be one way. You should need to go a pack through getCommponents. Casting (assuming generics) is an easy way to see that something has gone wrong.
So when you create the text fields for a form, add them to the list to be cleared in a clear operation as well as adding them to the panel. Of course in real code there probably other things you want to do to them too. In real code you probably want to be dealing with models (possibly Document) rather than JComponents.