Just a quick question here. I have a program in which I need to create a number of JPanels, which will then each contain some objects (usually JLabels).
There are a few operations that I have to do each time i create a new JPanel, and I'm wondering if the order in which I do them has any bearing, or if there is a standard practice.
The operations I do are the following:
Declare the JPanel: JPanel panel = new JPanel(...)
Declare the JLabel: JLabel laberl = new JLabel...
Add the JPanel to some other content pane: frame.getContentPane().add(panel)
Set the bounds of the JPanel: panel.setBounds(...)
Add the JLabel to the JPanel: panel.add(label)
In general order isn't important as long as you add all the components to the panel and the panel is added to the content pane "before" you make the frame visible.
The standard practice is to use a layout manager, so there would be no need to set the bounds of the panel you added to the content pane.
The order doesn't matter. However, after creating and adding everything, you need to call revalidate() on the panel (or pack() on its parent window) so that the layout manager (I presume you're using one!) arranges the components as they should be.
Have a method createPanel() that returns the panel with all its children added.
Panel p = createPanel();
p.setBounds(...); // if you must
frame.getContentPane().add(p);
And then
Panel createPanel() {
Panel p = new Panel();
Label l = new Label("Heading");
p.add(l);
return p;
}
The order of constructing and adding items isn't important, except that when you add children, you should add them in the order you want them in the panel.
Related
I was trying to add JsplitPane into my project.Requirement is i need to add two Jpanel inside right panel of JSplitPane.
so what i had done is first add Jpanel say it panel1 to right panel and set BoxLayout.Y-AXIS and than add two panel inside panel1.
now in that two panel first panel have BoxLayout and i want the width of this panel to be of size of panel1 but i am not able to do it.
anyone have idea how to do it?
I was trying to add JsplitPane into my project.Requirement is i need
to add two Jpanel inside right panel of JSplitPane.
When using JSplitPane, we should remember that it only divides the pane into two components say Left and Right or Top and Bottom. So when we again want to add more than one components in a single side of that JSplitPane, say in our case Right, it is better to use Nesting Split Panes. That means creating Split Panes inside Split Panes.
so what i had done is first add Jpanel say it panel1 to right panel
and set BoxLayout.Y-AXIS and than add two panel inside panel1.
now in that two panel first panel have BoxLayout and i want the width
of this panel to be of size of panel1 but i am not able to do it.
If you use Nesting Split Panes, you may not have to create an extra Parent JPanel what you said as panel1. Actually the Split Pane is used to divide the Pane into two segments. So, by using Nesting Split Panes you are creating another Split Pane in stead of what you were creating as panel1 and then put your two child panels inside the two Panes created by new JSplitPane which is nested. So, you don't have to think about the size issue, too. I hope I could make you clear and it solved your issue.
A simple way to achieve that by using:
Declaration:
private JSplitPane jSplitPane1;
private JSplitPane jSplitPane2;
private JPanel jPanel1;
private JPanel jPanel2;
In Constructor:
jSplitPane1 = new JSplitPane();
jSplitPane2 = new JSplitPane();
jSplitPane1.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
jSplitPane1.setRightComponent(jSplitPane2);
jSplitPane2.setOrientation(JSplitPane.VERTICAL_SPLIT);
jSplitPane1.setTopComponent(jPanel1);
jSplitPane1.setBottomComponent(jPanel2);
The above described method is the simplest to achieve what you wanted. However, without nesting the Split Pane, it is possible to use Multi Split Panes which may not be so handy. Still you can have a look at this old article at Oracle:
https://community.oracle.com/docs/DOC-983539
Colleagues.
I'm trying to construct simple GUI in Java, where JFrame has Border Layout. I want to put JScrollPane with JTable to CENTER, and JPanel without layout to NORTH.
The problem is that JPanel doesn't visible. There is simple examle of the problem:
JFrame frame = new JFrame("Test frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Test button");
button.setBounds(10, 10, 40, 20);
JPanel panelN = new JPanel(null); // layout = null, panelN without layout
panelN.add(button);
frame.add(panelN, BorderLayout.NORTH);
JTable table = new JTable(new DefaultTableModel(4, 4));
JScrollPane scrollPane = new JScrollPane(table);
frame.add(scrollPane, BorderLayout.CENTER);
frame.setSize(400, 400);
frame.setVisible(true);
You have to use a LayoutManager. It's totally discouraged not using layoutManager, but if you want this you have to set panel.setBounds(..) to the panel too.
By default JPanel has FlowLayout so if you put
JPanel panelN = new JPanel(); // FlowLayout used
panelN.add(button);
frame.add(panelN, BorderLayout.NORTH);
So your frame will look like this.
Layout Managers determines the size and position of the components within a container. Although components can provide size and alignment hints, a container's layout manager has the final say on the size and position of the components within the container.
It's strongly recommended cause for example if you have to resizes components or show in differentes resolutions you delegate this work to layout managers
I don't know the expected behavior of a null layout, but without further requirements you might as well just instantiate with the zero-arg constructor:
new JPanel();
If you didn't set any layout to the panel, when adding components the panel don't know where to put the component, so baisicly the component don't show until you set a specific location for components one by one by component.setBounds(x,y,width,hieght) method.
Note that it's not a good practice to remove the layout manager because of the different platformes, suppose that your program working on Window and MacOS and Linux, you'v better to use the layout managers instead.
Take a look at this post also and see #Andrew Thompson's comment on my answer:
Java GUIs might have to work on a number of platforms, on different
screen resolutions & using different PLAFs. As such they are not
conducive to exact placement of components. For a robust GUI, instead
use layout managers, or combinations of them, along with layout
padding & borders for white space, to organize the components.
After all:
If you have a requirement or an assignment telling you you must use absolute layout, then use it, otherwise avoid it.
It is OK to use containers with no layout manager because you actually CAN set container's layout to NULL. And it's a nice idea to position your components with setBounds(). But in this case, you just have to consider your container. What size it need to be? A layout manager would calculate this for you, and if you don't have one, you have to set the size of your panel by yourself, according to components you have added to it.
As pointed by others here, the case it that the border-layout manager of your frame needs the preferred size of your NORTH panel (actually, the preferred height). And you have to set it, or values will be zeros and the container will become invisible. Note that for the CENTER panel this is not needed as it gets all space possible.
I had a problem like yours before and have written a fast function to resize a container according to bounds of a given component. It will be as large as needed to show this component, so dimension (w,h) and position (x,y) are considered. There's an "auto-resize" version that can be used once, after all components are added.
public static void updatePreferredSize(Container cont, Component comp) {
int w = cont.getPreferredSize().width;
int h = cont.getPreferredSize().height;
int W = comp.getBounds().x + comp.getBounds().width;
int H = comp.getBounds().y + comp.getBounds().height;
if (W>w||H>h) cont.setPreferredSize(new Dimension(W>w?W:w, H>h?H:h));
}
public static void autoPreferredSize(Container cont) {
for (Component comp : cont.getComponents())
updatePreferredSize(cont, comp);
}
You can use updatePreferredSize() after adding every component to a panel, or use autoPreferredSize() once, after all addings.
// [...]
panelN.add(button);
updatePreferredSize(panelN, button);
// [...]
// or...
// [...]
autoPreferredSize(panelN);
// [...]
frame.setVisible(true);
This way, if you do not set you north panel height with a fixed value, with help of these functions you can expect your button will be visible according the position you set it with setBounds().
I'm looking to wrap a JPanel when it reaches the 'edge' of the screen using MigLayout. At the moment I have a JScrollPane (which I only want to be enabled vertically). The JScrollPane contains any number of JPanels which are arranged horizontally - when a panel is added so that the JPanel would go off the edge I want it to add to the next line. Is this possible?
This is the code:
public void setupPanels(){
JScrollPane scrollPane = new JScrollPane();
JPanel mainPanel = new JPanel(new MigLayout("insets 2"));
for (Object object : objects){
JPanel subPanel = new JPanel(new MigLayout("insets 0"));
mainPanel.add(subPanel, "alignx left, gapx 2px 5px, gapy 2px 2px, top");
}
scrollPane.setViewportView(mainPanel);
}
Also, to add an extra factor, every time it reaches the edge I need to add a new/different panel (a timeline) - so is there a way of finding out when it is going to wrap onto a new line?
Thanks
MigLayout does not have such a feature. It is based on a grid and while you can use the nogrid option to flow components horizontally or vertically in a cell span, you cannot make them flow into the next row or column.
The java.awt.FlowLayout contained in the JDK wraps the contained components automatically:
JPanel mainPanel = new JPanel(new FlowLayout());
mainPanel.add(subPanel1);
mainPanel.add(subPanel2);
mainPanel.add(subPanel3);
...
The preferred height is off, but there are ways to fix this, see WrapLayout.
As for the second requirement:
Also, to add an extra factor, everytime it reaches the edge I need to
add a new/different panel (A timeline) - so is there a way of finding
out when it is going to wrap onto a new line?
A layout manager should layout components that have already been added to a container, not add new components based on the results of the layout. Adding invisible placeholder components for the timeline after each subpanel that are made visible by the layout manager on demand might work.
You definitely need a custom layout manager to do this. To get started I would recommend to take the source of FlowLayout. In the layoutContainer implementation there is a loop that iterates over all components. After a line wrap, check if the next component is a timeline placeholder component, make it visible and wrap again.
I have a JFrame window, and I'd like to add a scrollable JTable towards the middle of it. I have a method, called collectionTableScrollPane() that generates the JScrollPane (and I know this is guaranteed to work).
I then proceed to add it to my mainPanel panel. However, I'd like there to be some forced 30px padding on the left and right of the JScrollPane. Logically, I would create a holding JPanel with a centred FlowLayout, and add Box.createHorizontalStrut(30) either side of the JScrollPane.
JPanel tableHolderPanel = new JPanel(new FlowLayout());
mainPanel.add(tableHolderPanel);
tableHolderPanel.add(Box.createHorizontalStrut(30));
tableHolderPanel.add(collectionTableScrollPane());
tableHolderPanel.add(Box.createHorizontalStrut(30));
However, I'm getting a strange result, where the JScrollPane in the middle of the window (denoted by the arrows) sort of becomes ineffectual.
Does anyone know what the problem is?
Note that the JTable contains four rows, of which only two are visible.
I had some issues in the past when i used a JScrollPane inside a panel with a FlowLayout. The behaviour could be tricky, when the content grow, the horizontal scrollbar may appear or the FlowLayout should add a new line.
In your case, i will replace the FlowLayout by a BorderLayout :
JPanel tableHolderPanel = new JPanel(new BorderLayout());
mainPanel.add(tableHolderPanel);
tableHolderPanel.add(Box.createHorizontalStrut(30), BorderLayout.WEST);
tableHolderPanel.add(collectionTableScrollPane(), BorderLayout.CENTER);
tableHolderPanel.add(Box.createHorizontalStrut(30), BorderLayout.EAST);
As far as I'm aware, Box is suppose to be used with the BoxLayout, this may be causing you some issues. Instead, why not use a EmptyBorder on the tableHolderPane
BoxLayout accepting size that came from JComponents, the same issue with default FlowLayout pre_implemented for JPanel
you have to returns PreferredSize by overrode JPanel nested JScrollPane,
use another LayoutManager, e.g. GridBagLayout or todays MigLayout
use NestedLayout, by using BorderLayout where you put two JLabels (e.i. that returns PreferredSize) to the EAST and WEST area
everything depends if you really to want to create the empty area and if shoud be resiziable or not
I need to get two JPanels into one JApplet.
paneel = new RekenmachinePaneel();
nummer = new NummerPaneel();
setContentPane(paneel);
Now I need to get the nummer panel to show up beneath the paneel. How should I do that?
If you want to add both panels you will have to create a third one:
JPanel myPanel = new JPanel();
myPanel.add(paneel);
myPanel.add(nummer);
setContentPane(myPanel);
If you want to get the number of panels you have inside an specific component use this:
int no = yourComponent.getComponents().length;
You can use a layout to position them.
setLayout(new GridLayout(0,1));
add(paneel);
add(nummer);
Make the layout as null.
paneel.setLayout(null);
nummer.setLayout(null);
By setting the layouts to null, you can move any panels over any panel. But its not recommended as you will not be using the power of layouts (form, border, box etc.,)
Also you would need to the location of the panels properly.
paneel.setLocation(x2,y2);
nummer.setLocation(x1,y1);