I'm creating a custom Swing component that inherits from JPanel.
What is the right way to override/implement the various sizing methods (getPreferredSize, setPreferredSize, getMinimumSize etc.) in order to get "good behaviour", particularly with regards to:
Working with different layout managers
Behaving correctly when setPreferredSize() is called
Reacting appropriately when a border is set via setBorder()
Don't inherit from JPanel unless your component is a composite of several subcomponents. In most cases inheriting from JComponent is enough.
As far as resizing goes... override getPreferredSize, getMinimumSize and getMaximumSize methods to get an appropriate behavior in layout managers.
If your component is a composite of subcomponents in most cases preferred size is already defined by combination of your subcomponents so you don't have to override this one.
Although rather annoying: that depends, on the layoutmanager in this case. Usually the layoutmanager can best be used along with constaints to get a good layout.
I've used GridBagLayout, and after getting used to it, I found it worked pretty well using right GridBagConstraint for each component.
Sometimes a good visual ui designer can help too, like the one from Netbeans, or you could consider a paid one like Swing Designer or JFormDesigner. Can save you some time fiddling with pixels.
Related
I am creating simple application in java - Eclipse - WindowBuilder Editor. JFrame`s contentPane has JGoodies FormLayout in which I have to place 3 or 4 Panels - depending on mode.
It is proper way to make if construction that decides if content pane will be divided 1x3 or 1x4(facilitation because between all I use relatedgaps and so on..)?
I am not sure if this is good approach but I do not know how can I do this in other way than if construction. It has to be practical and flexible approach - to handle resizing the window, et cetera..
Common approaches for dynamic layout include these:
Use revalidate(), and possibly repaint(), to layout a Container again after adding or removing components, as shown here.
Replace the layout and validate() the Container, as shown here.
Use CardLayout to replace one panel with another, as shown here and here.
I've been staring at Oracle's JLayeredPane tutorials but they are laid out in a manner that is confusing to me and doesn't get at what I am trying to do.
I have an application that up to now has had no concept of layers. Everything is laid out in a single layer, inside a JFrame.
I now want to introduce a component that appears sporadically, as needed, in a certain location, overlaying existing components that stay there normally. Do I have to modify my existing application JFrame so that all its top-level contents (that is, the components that are directly added to the JFrame) are instead added to the JFrame's JLayeredPane?
Or what, exactly?
I'm looking for an easy way to adapt this gui to use layers with the minimum rework of the existing GUI.
Thanks in advance for any help here.
You may want to instead consider drawing your overlay element on the glass pane. That way you can leave the underlying structure completely as-is.
I have about 3 frames in my java swing application. What it the correct way how to handle with these frames? I mean some pattern or something else. Now I have always one class which represent frame and one class for panel which is main in this frame. Now I have defined frames as static variable and when I wanna hide them I call
classname.frameName.setVisible(false);
is this the correct solution?
Besides the (excellent) suggestions of a CardLayout or JFrame with multiple JDialog instances, here are some other strategies which might work singly or in combination, to collapse a variety of content panes into a single frame.
JDesktopPane/JInternalFames (Tut.).
JSplitPane (Tut.).
JTabbedPane (Tut.).
JLayeredPane, if you're feeling brave (Tut.).
JToolBar - floatable if needed (Tut.).
Different constraints of a JPanel in a nested layout.
There are probably more..
Of course, as Adamski pointed out, there are some further quirks to consider..
What if each frame has JMenuBars or JMenus?
Possibly combine them as sub-menus.
Take a look at a decent docking framework such as MyDoggy. This allows you to display all three components in a single JFrame, but is very flexible in that you can view the data side-by-side, resize and maximise components.
This design seems flawed. Instead of having multiple containers, you should use an appropriate layout manager. In this case, I recommend using CardLayout. This way, you would have a single container with multiple exchangeable views.
Controlling frames through static references seems to be a very fragile solution. What if the reference is null? What if the frame isn't in a completed state when setVisible() is called on it?
It would probably be a better idea to separate this logic out into a separate class and either have the frames register themselves to it , or construct everything up front.
In my Netbeans code I have JPanels and JDialog which are driving me crazy at times. Some of the controllers on these containers decide not to show up or automatically change size even though I have set up both their size and contents within the code and through using the IDE properties. For instance some of my jButtons on a certain JPanel does not show its text label or the sizes of some of my text field change.
Any solution to this would be grately appreciated!
When you create GUI using the NetBeans IDE wizards the Layout manager attached with JPanel and JFrame is GroupLayout and it works as expected. It keep the size of your JPanel and JFrame as you have specified.
Now if you change the LayoutManager of the JPanel or JFrame then you are on your own. You must know the consequences of changing the LayoutManager and update / add the required code to make the code to run as expected.
I will suggest you to keep the default LayoutManager as GroupLayout if you want to get what you see in the NetBeans component designer.
Unfortunately you did not provide any code snippet that can show your problem. But let me assume that you are confused with layout behavior. Typically we use Layout manager and delegate to it the responsibility of placing and re-sizing the graphical elements. Layout manager does it work when the parent element is being painted, i.e. during execution of method paint() that happens asynchronously and may be caused by various events (e.g. changing focus, re-sizing of window etc).
In this case all your attempts to change size of specific element by calling its setSize() could be overridden by layout manager that decides to change size of the same element differently.
So, if my assumption is correct learn to use layout managers and ask more specific questions if you have any difficulties with them.
everyone, I have some problem with Java I created panel with five rows and one column, also I added button to the one of the rows, finally I added this panel to the frame, and I received button which is stretched to full frame, can I reduce the size of the button, I used
myButton.setSize(10,10);
but it doesn't seem to work, also I use
frame.pack();
may it be the problem, thanks in advance
You should refrain from setting the size yourself. You should select a proper LayoutManager that does the job for you.
(Unless you explicitly do setLayout(null) the sizes you set will be discarded and the current layout manager will assign new sizes to the components.)
You say that you're using a GridLayout. This layout is fairly "unflexible", and if you want the benefits of GridLayout but more flexibility, you could give GridBagLayout a try.
If you don't find a layout manager that suites your needs, don't be afraid of writing your own. (It's five relatively easy methods to implement.)
If you post a screen-shot of your current application, and an explanation on how you want it to look, we'll be able to help you further.
Some useful links
Trail: Using Layout Manager
Create a Custom Swing/AWT Layout Manager in Java
When aloobe seems to have a more general solution for you. I'd say the immediate solution would be to add the button to a JPanel, set the Layoutmanager a layout like GridLayout, or another LayoutManager, if you find another suits you better.
And add this panel to your original panel, in place of the button.
When you are using layout managers (like GridLayout) then calls to setSize() generally don't work, because the layout manager ultimately decides how to size and place each component in a container.
What you can do is call setPreferredSize(), setMaximumSize() and/or setMinimumSize(). Depending on the layout manager in use one or more of these requests (because that's really what they are) will be honoured. When you call frame.pack() it will try to size everything in the container (and subcontainers) to their preferred sizes.
So, in your case, calling myButton.setPreferredSize (10, 10); will probably work. However, it will still be resized if the container changes size. If you don't want that, there are other solutions I can post.