How to find if JPanel has null components? - java

if (cardPanel.getComponent(0) != null) cardPanel.remove(0);
I need to remove anything potentially on the cardPanel which is a JPanel...
if there is nothing then it should not attempt to remove.

You can use:
cardPanel.removeAll();
There is no need to check if there are any components on the panel.

Only remove JPanel? You can try this:
Component[] components = cardPanel.getComponents();
for(Component c : components)
if(c instanceof JPanel)
cardPanel.remove(c);

One potential way would be to use the following code to first check if there is anything there, before the potentially erroneous situation where a component is removed from and empty JPanel:
boolean isComponentInPanel(Component component) {
return
java.util.Arrays.asList(panel.getComponents())
.contains(component);
}

Related

Adding more than one mouse listener to a panel

I'm trying to add more than one mouse listener to a panel, but I want them to be on the same line like this:
Paint.paint.addMouseListener(Shape.circle,Shape.blah);
Is that possible?
I know you can do it like this instead:
Paint.paint.addMouseListener(Shape.circle);
Paint.paint.addMouseListener(Shape.blah);
And that's not too bad, but I thought it would be easier if you're not using arrays, and you can add it to the same line if it's possible. So, anyone know if this is possible? Thanks.
There is no addMouseListener(...) method that accepts more than one listener, but you can write your own utility method to do so:
public static void addManyMouseListeners( Component component, MouseListener... mouseListeners ) {
if ( component != null && mouseListeners != null ) {
for ( MouseListener mouseListener : mouseListeners ) {
component.addMouseListener( mouseListener );
}
}
}
The varargs parameter allows you to call the method like:
addManyMouseListeners( Paint.paint, Shape.circle, Shape.blah );
And in fact add as many mouse listeners as you like. Inside the method, the varargs parameter is interpreted as an array, and you iterate on it as you would on any array.

Find all modal dialogs belonging to a frame

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!

Swing ยท Changing the JFrame's titlebar's icon's context menu's font

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!

Retrieve JTextField text value

I'm trying to retrieve the text value from a JTextField but first I need to cast a component object (java.awt.Component) to a JTextFiel...
mi code is like this
Component[] x = this.getComponents();
for(int i = 0; i < x.length; i++)
{
if (x[i] instanceof JTextComponent)
{
//retrieve text...something like
//(JTextField)x[i].getText();
}
}
I'm doing this because I know all the controls of mi page are in "x" (JLabels and JTextField) but they are Components and that's why i'm making the cast to JTextField.
I'm really lost here and i don't know if this is the right way to do it.
Thanks for your time!
I'm really lost here and i don't know
if this is the right way to do it.
Thanks for your time!
You are never forced to write all you code on one line. So to simplify your problem simplify the code. Something like:
Component component = x[i];
JTextField textField = (JTextField)component;
String text = textField.getText();
That way if you have a compile error or something the compiler will point out the exact line.
I think you need to rethink your design. Why not expose a getText() method in the class that contains your JTextField. That method can delete to your JTextField's getText() method, and avoid that God-awful instanceof.
((JTextComponent) x[i]).getText(); should work.
(Just because x[i] is an instance of a JTextComponent, doesn't mean it's neccesarily a JTextField though.) But JTextComponent has a .getText() so casting to JTextComponent should be ok.
Through reflection API.
Just for horizons expanding =)
import java.lang.reflect.Method;
...
for ( Component component : this.getComponents() ) {
try {
Method getText = component.getClass()
.getDeclaredMethod("getText");
String text = (String)getText.invoke();
//Do something with text
} catch ( Exception exc ) {} // no such method
}

loop through JPanel

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.

Categories