The container uses a BorderLayout. I have a JPanel that I added to the CENTER. However the JPanel doesn't have a variable name for it.
I could do contents.remove(nameofPanel)
But since I added it like this contents.add(new CustomJPanel(), BorderLayout.CENTER);
Now I'm trying to remove the current CustomJPanel and add a new one.
How do I do this?
While Carl's answer is probably the best one, a less-pleasant alternative if for some reason you can't modify the original add() call:
contents.remove(((BorderLayout)getLayout()).getLayoutComponent(BorderLayout.CENTER));
contents.add(someNewPanel);
Though if you think you need to do this, you may want to step back and evaluate why you're trying to do it.
Your best way is to extract the constructor call into a named variable - probably a field, actually - and then reduce to the previous case.
contents.add(new CustomJPanel(), BorderLayout.CENTER);
becomes
nameOfPanel = new CustomJPanel();
contents.add(nameOfPanel, BorderLayout.CENTER);
Or you can list all the elements in the container with the getComponents() function, and search your Panel by an other attribute (if you can).
The getName() attribute is useful for this purpose, e.g. you set a name for your panel before insertion and you can use that name as a search key.
I strongly suggest you declare a global CustomJPanel variable, instantiate it with your first panel, then add the panel. When you want to remove it, you use the same object. Then you assign the new object to the variable, and add it the same way.
Anonymous object are okay when you don't need to refer to them. But you do. So you should avoid using the anonymous way.
Related
Can a Java Swing JPanel hold a String value than can be modified/accessed where I can save some information?
I see no other option but to implement my own class holding a JPanel and a String... was just trying to save some space/coding..
I like the setName/getName of the Component super class... is there any inconvenience in using that ??
Yes it can. Any Swing component can hold client properties for the specific component.
See the putClientProperty(...) and getClientProperty(...) methods of JComponent. Using this approach you can define any number of client properties:
panel.putClientProperty("Title", "Panel1");
panel.putClientProperty("Description", "some text for the description");
You can also use the setName(..) and getName() methods if you just want to uniquely identify the panel with a string name. Many IDE's will use this property.
Of course if you are creating a panel with multiple Swing components and related instance variables then you would probably extend JPanel and customize its behaviour.
I like the setName/getName of the Component super class... is there any inconvenience in using that ??
If you feel the "name" property adequately describies the data you want to store then this is the most efficient way to store the data. However, if the data is not really the name of the component then don't force the data just because it is easy to use. Also it is possible some IDE's may use this property for generic debugging or messaging. That it may check display this value in an error message to help identify a specific component.
Several solutions, and it's hard to know what you're looking for here. You could create a MyJPanel class that extends JPanel and is identical except including a String field with getter/setter. You could also store information in silly ways like by setting/getting the name of the JPanel. (That is use setName and getName of the Component superclass.) Another solution is to add a JLabel or some other component with that information to the JPanel, and if necessary, making it invisible or hidden.
No, I think it cannot hold a String value.
You can see all getters/setters here:
http://docs.oracle.com/javase/7/docs/api/javax/swing/JPanel.html
Also, you can check the source code (if you want to go that far).
There's no getter/setter useful for holding a String value
(I mean ... e.g. no setText or setTitle).
Of course, you can add e.g. an invisible JTextField to your JPanel and
set the String into the JTextField. But that doesn't seem very nice to me.
JPanels hold JComponents, i.e. JButtons, JLabels, etc. A String is not a component. It would be best if you'd just use a JLabel with a String as its parameter, then add that to a JPanel.
You can add a Component like JLabel/JTextField and use setVisible(false). That object can hold strings.
note: Only for Buttons.
You could use setAtionCommand() but it is indented for something very specific. It would be horrible practice for anything else.
I've started to work with Java Swing and I'm asking myself if it is possible to get elements on a generic JPanel, by Id or simply by name.
I mean something like 'getElementById("example")', used in javascript.
This is a little example, in pseudo-code of what I'd like to get:
....
myButton = my_panel.getElementById("xxxxxxx");
// OR BY VARIABLE NAME
myButton = my_panel.getElementByVariableName("xxxxxxx");
....
Is that possible in java?
You can use putClientProperty and getClientProperty as shown in below code:
JPanel jPanel = new JPanel();
JLabel label=new JLabel("Hi");
jPanel.add(label);
jPanel.putClientProperty("hiLabel", label);
System.out.println(jPanel.getClientProperty("hiLabel").getClass().getName());
Swing core has no concept of an Id for components. You can use setName() to set an unique name and then traverse the component tree of the container recursively to get the component with a certain name (Get a Swing component by name).
While Swing components can have a name (http://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#getName()) this is not an id; it is up to you to ensure consistency.
This name property is not widely used. In SwingUtilities there is no method for finding a child by name, just an ancestor: SwingUtilities#getAncestorNamed.
You would have to to this by yourself. In general it is not impossible. You would start with a Container, iterate over its children (Component[] getComponents) and check for the name. Do this recursively for every child that is a Container itself. Break when found.
But this is untypical for Swing. The framework is not used declarative. (Other Java GUI toolkits are or can, like GWT or Android's native UI.) You would just store a reference to the component you create programmatically for later use.
Of course you can't search by variable name in Java. The name doesn't exist at runtime. Java works different than JavaScript. Most of the time it is not a good idea to directly transfer concepts from one system to another. You need to get used to each one to utilise it fully.
I have to write: jframe.getContentPane().add(button);
But I found out that it also works when I only write
jframe.add(button);
What are the differences between the two approaches? Is it favorable to write JFrame.getContentPane().add(button); ?
It a matter of taste. I always use getContentPane().add(..), as I think it is easier to read / know what's actually going on
Try this........
Before the arrival of Java 1.5, jframe.getContentPane().add(button) was Used..... and thats was the legal way of doing it....
But then from Java 1.5 and onwards, included the myframe.add(button)... as also one of the legal way of doing it.. Its just like, accessing the static variable with the Classname is the legal way of doing it...but still you can access the static variables using the class instance...
The class javadoc of JFrame is rather clear on this
The JFrame class is slightly incompatible with Frame. Like all other JFC/Swing top-level containers, a JFrame contains a JRootPane as its only child. The content pane provided by the root pane should, as a rule, contain all the non-menu components displayed by the JFrame. This is different from the AWT Frame case. As a conveniance add and its variants, remove and setLayout have been overridden to forward to the contentPane as necessary. This means you can write:
frame.add(child);
And the child will be added to the contentPane.
So you should know that elements like JButton, JTextArea etc. should be added to Container and your method:
getContentPane()
returns the Container object for this frame. So both approaches work same but second approach you should use.
In the case if you will have big application with many elements first approach is less readable and second is generally recommended.
Difference isn't:
Jframe.add() - Appends the specified component to the end of this container. This is
a convenience method for Container.addImpl.
To illustrate my problem, let's say I have an instance of Thing which has two text properties - 'foo' and 'bar'.
I want to create a Panel to edit instances of Thing. The panel has two TextField components, one for the 'foo' property and one for the 'bar' property.
I want to be able to call setDefaultModel() on my Panel with an instance of IModel<Thing> and for the TextField components to reference this model. How best to achieve this?
Should I override the Panel.setDefaultModel() method to also call setModel() on the two TextField components? Or perhaps create anonymous ReadOnlyModels for the TextField components, overriding the getObject() method to retrieve the object from the containing Panel's model?
Neither of these seem very elegant to me, so I was wondering if there's a better way?
You can use a PropertyModel for the textFields. Pass the IModel<Thing> into the constructor of the PropertyModel with foo as the property name:
add(new TextField("fooFieldId", new PropertyModel(thingModel, "foo")));
The PropertyModel will figure out that the thingModel is a Model and call getObject().getFoo() etc.
This assumes the IModel<Thing> instance doesn't change, only its underlying object which can be changed calling setDefaultModelObject.
Maybe I'm just missing the point, but I can't find a Panel.setModel() in the JavaDocs of neither 1.4 nor 1.5. If it's something you implemented maybe you could change it not to replace the model object but to call model.setObject() instead?
Disclaimer: Can't really check right now, cause there is no wicket at work and my home machine suffered a video card breakdown earlier...
Maybe this would help?
public abstract class AbstractWrapModel<T> extends Object implements IWrapModel<T>
Simple base class for IWrapModel objects.
See IComponentAssignedModel or IComponentInheritedModel so that you don't have to have empty methods like detach or setObject() when not used in the wrapper. The detach method calls the wrapped models detach.
If I have elements inside my gridLayout, can I get the reference to that object, if yes, which function do I need to use? Is it good idea to perform some actions on the objects inside gridLayout? Or there is another better language idiom?
No you cannot get references to items from a layout. However, you can from the container that holds the button. A better solution might be to hold a reference to the button at a higher level of scope in order to be able to access it later.
You can't get stuff out of a LayoutManager unless it specifically supports it, and GridLayout doesn't.
If you are putting Components into a Container then you probably have a reference to them anyway. Can't you pass this reference around?