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.
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.
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.
In a rich client CRUD framework I'm working on, I have a so-called edit panel, which as the name suggests, is involved in editing row objects via the usual swing input components.
Now, the panel has a default focus component field, which references the input field which should receive focus when the edit panel is initialized or cleared. The problem is the most logical name for the method which performs the focus request.
public boolean requestDefaultFocus()
return getDefaultFocusComponent().requestFocusInWindow();
}
The edit panel extends JPanel so this overrides the now deprecated JComponent method. The method name I'm currently using to avoid this is setDefaultFocus().That just doesn't sound quite right, although I will be able to live with it in case the answer to the question turns out to be a resounding no.
So, what are your thoughts on overriding a deprecated method like that?
I would not recommend it. There's no way to stop your code from issuing deprecation warnings. It makes it look like there's something wrong. And that takes developer time to verify that the warnings are spurious.
How about setInitialFocus()?
I'm using Java Swing and I have the following problem:
I have a class TnaiPanel that extends JPanel. In this class I am creating 3 components and then lay them out in a horizontal line using a BoxLayout.
Also, I have a class TnaimDinamimPanel that also extends JPanel. This class contains multiple occurances of TnaiPanel, layed out vertically using a BoxLayout.
Also, I have a class MainFrame that extends JFrame. This frame contains a menu-bar and one main panel. The main panel can change (when choosing a certain menu-item, I create a new panel and set it to show as the main panel of the frame).
Now, for some reason I get "BoxLayout can't be shared" when I add the newly created TnaimDinamimPanel to the components of the frame.
I don't mind using different layout objects.
The result I want to get is a sort of "table" of components, where each TnaiPanel will have fixed component sizes and spacing, essentially serving the role os a "row" in the "table".
Thanks,
Malki.
You probably create only a single BoxLayout instance. Create a new one each time you need one (i.e. one per TnaiPanel, one per TnaimDinamimPanel and probably one per MainFrame).
To answer the second part of your question, ie "having a table of components", I would say that you can't do it with different panels, except if you start setting the individual min, pref and max sizes of components and panels, which is highly unadvised.
If you need to have correct alignment as in a table of components, then you need to put all your components in one panel, which also means you need to use only one layout. However, the only default swing layout that can allow you to do what you want is the GridBagLayout. Actually the GroupLayout (java 6) would also fit the bill but it absolutely requires a graphical designer (eg the one within netbeans).
If, like me, you are allergic to builders, then you'd better use one 3rd-party LayoutManager that is intended to be use programmatically (I would not consider GridBagLayout to be in this category although I have already used it that way in the past).
MigLayout (as suggested by Skeptic) is one option. Another option is DesignGridLayout which might fit your purpose better and is easier to use than MigLayout.
Try MiGLayout instead.
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.