This is what my program should look like and I'm a bit confused on where I should use different layouts.
I have a Window class which calls the Panel class and the Panel class calls the InputPanel and DisplayPanel classes. My InputPanel class calls my DetailsPanel, CrimePanel and ButtonPanel classes so they make up what is seen under the Input tab. I was told to use a BorderLayout for the whole window, and that the DetailsPanel (left panel) and CrimePanel should be GridLayout.
Does this mean I should:
Put the BorderLayout code in Panel and the GridLayout code in CrimePanel and DetailsPanel or
Put the BorderLayout code in Window and the GridLayout code in Panel?
alt text http://img137.imageshack.us/img137/6422/93381955.jpg
Okay, your description is a little bit confusing (or I'm still too tired today or didn't have enough caffeine yet). Your notion of "calling" panel classes from others is also a little weird.
But as far as I can see it, your first option is the correct one.
In general you just nest the objects at runtime, so it might look a little like the following:
InputPanel (has BorderLayout)
+--DetailsPanel (put in BorderLayout.WEST; has GridLayout)
| +--nameLabel
| +--nameTextField
| +--...
+--CrimePanel (put in BorderLayout.NORTH; has GridLayout)
| +--murderRadioButton
| +--arsonRadioButton
| +--...
+--ButtonPanel (put in BorderLayout.CENTER; has GridLayout)
+--button
You usually do this in the constructor of the appropriate class:
public class InputPanel {
public InputPanel() {
this.setLayout(new BorderLayout());
this.add(new DetailsPanel(), BorderLayout.WEST);
this.add(new CrimePanel(), BorderLayout.NORTH);
this.add(new ButtonPanel(), BorderLayout.CENTER);
}
}
public class DetailsPanel {
JLabel nameLabel;
JTextField nameField;
// ...
public DetailsPanel() {
this.setLayout(new GridLayout(5, 1));
nameLabel = new JLabel("Name");
nameField = new JTextField();
// ...
this.add(nameLabel);
this.add(nameField);
// ...
}
}
...
However, I see a small problem here: Since GridLayout doesn't allow components to span multiple columns you may need to nest other panels in the DetailsPanel on the left as well. You can get away with a single GridBagLayout which has the needed capabilities, or you nest other panels there:
DetailsPanel (has BorderLayout)
+--panel1 (has GridLayout with 2 rows, 1 column; put in BorderLayout.NORTH)
| +--nameLabel
| +--nameField
+--panel2 (has GridLayout with 3 rows, 2 columns; put in BorderLayout.CENTER)
+--dayField
+--dayLabel
+--monthField
+--...
From your description, option 1 should work. Give the Input JPanel a BorderLayout, with the Details, Crime and Button JPanels (at the west, north and south, respectively) having GridLayouts.
First of all you will need to put a JTabbedPane into the Window to contain your two tabs (input and display), each consisting of a JPanel.
The input panel could be subdivided using a BorderLayout as Joannes describes; another alternative is the GroupLayout introduced in Java 6, which is very powerful, but hard to wrap your mind around. It could be used to layout the entire tab in one panel.
Related
I am a beginer and I dont know how to add more objects into JFrame.
How could I add more than one JPanel objects into JFrame?
Below is what I have tried.
Thanks for your help.
public class Init extends JFrame{
public Init(){
super("Ball");
Buttons t = new Buttons();
JumpingBall b1 = new JumpingBall();
JumpingBall b2 = new JumpingBall();
t.addBall(b1);
t.addBall(b2);
add(b1);
add(b2);
setSize(500,500);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
}
Assuming that JumpingBall extends JPanel, you might want to have a look at the java layout managers here: Link.
The default Layout for a JFrame is the BorderLayout and if you didn't specify where you want to add your component, The BorderLayout will put it in the center by default. In BorderLayout, you cannot have more that one component in the same area. So, in your example you will end up having only the second JumpingBall panel in your frame. If you want to have more than one component at the center, then you will have to create a JPanel and add those components to it using different Layout. The common three Layouts are the BorderLayout, FlowLayout and GridLayout Please have a look at the provided link above to see how the components are arranged.
You can add a number of JPanel objects in a JFrame, using the add method. If only one is displayed, you might need to change your Layout options or use a Layout Manager (Look here for more).
You are seeing only one because it overlapping each other. Just provide setbound(x,y,x1,y1) for you panel component and you will see your panel at location.
or use setLayout(new FlowLayout()); which is going to order your component in respective to other so you will not override each-other.
I have a JPanel with a BoxLayout manager that contains subpanels. I want the components inside these subpanels to have a left alignment, but they always appear centered.
It looks like BoxLayout correctly aligns components that are inserted directly, but fails to do that when they are inside a subpanel.
I have modified the example found in http://www.java2s.com/Tutorial/Java/0240__Swing/YAxisAlignment.htm so each button is placed inside a subpanel, and then the subpanel is placed inside the main panel with the BoxLayout manager:
public class YAxisAlignX {
private static Container makeIt(String title, float alignment) {
String labels[] = { "--", "----", "--------", "------------" };
JPanel container = new JPanel();
container.setBorder(BorderFactory.createTitledBorder(title));
BoxLayout layout = new BoxLayout(container, BoxLayout.Y_AXIS);
container.setLayout(layout);
// modified loop. the original version does not create JPanel pan.
// adds the buttons directly the the JPanel container with the
// BoxLayout
for (int i = 0, n = labels.length; i < n; i++) {
JPanel pan = new JPanel();
JButton button = new JButton(labels[i]);
pan.add(button);
button.setAlignmentX(alignment);
pan.setAlignmentX(alignment);
container.add(pan);
}
return container;
}
public static void main(String args[]) {
JFrame frame = new JFrame("Alignment Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container panel1 = makeIt("Left", Component.LEFT_ALIGNMENT);
Container panel2 = makeIt("Center", Component.CENTER_ALIGNMENT);
Container panel3 = makeIt("Right", Component.RIGHT_ALIGNMENT);
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(panel1);
contentPane.add(panel2);
contentPane.add(panel3);
frame.pack();
frame.setVisible(true);
}
}
If you execute this version, you can see that the buttons are all centered, despite the alignment set. Why is this happening? Is there any solution? In my case, every subpanel contains several components, and I do not want to add then directly to the main panel.
Thank you very much.
But they are aligned!
First of all, setAlignmentX changes a property at a JComponent level, the layout in which these components are placed may or may not use this information. For example, BoxLayout uses it but FlowLayout and BorderLayout don't.
In your case you are placing some panels with a vertical BoxLayout and you are aligning them in various ways, and it works! It just so happens that the the panels stretch themselves to fit the whole column so actually aligning doesn't change their appearance. You can see this by setting a Border around the panels:
pan.setBorder(BorderFactory.createLineBorder(Color.red));
See:
The fact that the panels contain a button or anything else is mostly irrelevant (it only influences the size that the panel wants to take, and not definitely), the BoxLayout is aligning panels not what is there inside the panels, that's the work of each panel's layout. That's why the buttons wouldn't have its alignment affected by the BoxLayout.
Now how are those buttons deciding its alignment? Well that's up to the layout they are in. The buttons are inside the pan panel that is using the default LayoutManager FlowLayout. Now, as I said, FlowLayout doesn't care for the alignmentX/Y property so the line:
button.setAlignmentX(alignment);
Doesn't accomplish anything. To align in a FlowLayout you need to change its alignment field through FlowLayout.setAligment(int) (docs), you can also do this in the constructor, so If we change the pan declaration to:
JPanel pan = new JPanel(new FlowLayout(FlowLayout.LEFT));
You'll also have the buttons aligned to the left inside their panels:
Of course, all the columns are aligned to the left since the parameter float alignment of makeIt does not influence the FlowLayout's alignment just the BoxLayout's one (and it doesn't matter). You might want to change that argument to an int and call the function with the different FlowLayout constants.
All in all, in the original version the line button.setAlignmentX(alignment); made sense because the buttons were added directly to the container panel and the BoxLayout aligned them properly:
However once you put the buttons inside other panels, the BoxLayout starts aligning the panels (which because of how panels works inside a BoxLayout they were being stretched to fill the whole width) not the buttons, and the buttons alignment is up to the panels layout. That's how it has to work so we can make consistent nested layouts.
I hope that's clear.
my question is could be very basic in terms of understanding this simple code. I wrote this code myself grabbing bits of code from here and there to understand. I would like to actually follow this code line by line as to what each line means?
I have added my understanding as comments above the line of code, it could be wrong or some of them marked as **** means I just dont know what it means. If you could help me out here, it will be great.
Thanks
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.text.ParseException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class TestingSwingComponents {
public TestingSwingComponents() {
//Create a frame which is the window that pops up
JFrame myframe = new JFrame();
//*****
myframe.getContentPane().setLayout(new BorderLayout());
//set the frame size to be 600 X 600 size
myframe.setSize(600, 600);
// create Pane1
JPanel myPanel = new JPanel();
//set the Layout component of Panel, as how you would like it to be
//here it is 2 rows and 15 columns
myPanel.setLayout(new GridLayout(2, 15));
//create a button with text in it
JButton letterButton = new JButton("click Me");
//add the created button component to the panel
myPanel.add(letterButton);
//******
myframe.getContentPane().add(myPanel, BorderLayout.SOUTH);
// create another panel
JPanel panelFormat = new JPanel();
//create a textfield
JTextField txtfield = new JTextField();
//create a label for the textfield
JLabel label = new JLabel("Guesss");
//set the layout type for this panel
panelFormat.setLayout(new BorderLayout());
//add label to panel
panelFormat.add(label);
//add textfield to panel
panelFormat.add(txtfield);
//I dont know the difference between the below two
//BorderLayout.CENTER still does not center the panel in the frame, I dont know why
myframe.getContentPane().add(panelFormat, BorderLayout.CENTER);
myframe.add(panelFormat);
// default settings
myframe.setTitle("Get buttons");
myframe.setVisible(true);
myframe.setLocationRelativeTo(null);
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) throws ParseException {
new TestingSwingComponents();
}
}
myframe.getContentPane().setLayout(new BorderLayout());
To answer this, you need to understand the structure of a Swing window. A JFrame (in fact any Swing window) is made up a series of components which generate the view of the window.
(Picture from How to use Root Panes)
A JRootPane makes up the base of view, on-top of which is a JLayeredPane and what is know as the "glass pane". The JLayeredPane is responsible for managing the JMenuBar and the "content pane".
The content pane is where you components reside on the window.
So, what this line is saying is, "get the frame's content pane and set it's layout to use a BorderLayout"
The layouts API is an entire question on it's own and it would be use to you to have a read through Laying out components within a container for a more indeepth description, but basically, layout managers remove the need for you to care (a greate deal) about differences in rendering techniques employeed by different systems...
//******
myframe.getContentPane().add(myPanel, BorderLayout.SOUTH);
This comes back to the layout manager. Because you can have any number of layout managers, Swing allows you to pass a "constraint" to the layout manager when you add the component, giving the layout manager some idea of how you might like this component to be added.
If you take a closer look at BorderLayout you will see that it has five positions in which components can be added.
The line is basically saying, "please add myPanel to the SOUTH position within the frame/content pane"
Update from comments
If you have a look at this snippet...
panelFormat.setLayout(new BorderLayout());
//add label to panel
panelFormat.add(label);
//add textfield to panel
panelFormat.add(txtfield);
It sets the layout manager for panelFormat to BorderLayout. BorderLayout can only have a single component in any of it's five available positions. When you use add(Component) without passing it a layout constraint, BorderLayout use CENTER as the default position, this means you are trying to add two components to the CENTER position, this is not possible, so BorderLayout simply uses the last component that was added.
why not borderlayout fix the size of textfield instead of stretching
it all window
Because this is how BorderLayout works and no, GridLayout would probably do something simular.
You could try FlowLayout or GridBagLayout
Updated from comments
You seriously need to take the time to read through the linked (and other suggested) tutorials...but basically, you can use a GridBagLayout just like any other layout, you create an instance of it and apply it to the container...
// create another panel
JPanel panelFormat = new JPanel();
//create a textfield
JTextField txtfield = new JTextField(10);
//create a label for the textfield
JLabel label = new JLabel("Guesss");
//set the layout type for this panel
panelFormat.setLayout(new GridBagLayout());
//add label to panel
panelFormat.add(label);
//add textfield to panel
panelFormat.add(txtfield);
//I dont know the difference between the below two
//BorderLayout.CENTER still does not center the panel in the frame, I dont know why
myframe.getContentPane().add(panelFormat, BorderLayout.CENTER);
myframe.add(panelFormat);
A Swing top-level container, including a JFrame, JDialog is composed of several components all held together including a JRootPane which holds all together, a JLayeredPane, and a contentPane the latter of which holds most of the GUI excepting the top window bar. You can read more about the details in this tutorial here: Top Level Containers:
So when you add a component to a JFrame in a default way, you're actually adding it to its contentPane. In other words, this:
myJFrame.add(myComponent);
is functionally the same as this:
myJFrame.getContentPane().add(myComponent);
For learning Swing, I used this great tutorial which goes over everything you have, and explains it pretty clearly in depth.
The tutorial also goes over the elements that you are having trouble understanding.
Here is said tutorial.
I already have a panel made (its a row of buttons), and have it located at the bottom of a frame (SOUTH), but I would like to add two rows (panels/ subpanels) beneath it (a text input line and output line if it matters). Right now the only thing I know to do is declare and add more panels, which would be fine, but when I specify .SOUTH they go over top of the previous panel.
EDIT: The solution I used
As suggested by Ted Hopp, I added my original panel (now called subPanel1), as well as the two new panels which were going on top of the original (subPanel2 & subPanel3), to a fourth "container panel" (bottomCotainerPanel). Since I only had three subPanels, this allowed me to specify where in the containerPanel each subPanel would go (using NORTH, CENTER, SOUTH, might have to do something slightly different if you had more than 3...), and then specify where the contianerPanel would go in the frame (SOUTH).
subPanel1.setLayout(new GridLayout(1,6)); //Layout of subPanel1
subPanel1.add(clearButton);
subPanel1.add(customerNameLabel);
subPanel1.add(customerNameTextField);
subPanel1.add(showByNameButton);
subPanel1.add(openNewSavingsButton);
subPanel1.add(openNewCheckingButton);
subPanel2.add(sendChatTextField);
subPanel2.add(sendButton);
subPanel2.add(clearButton2);
subPanel3.add(receiveChatTextField);
subPanel3.add(nextButton);
subPanel3.add(previousButton);
bottomContainerPanel.setLayout(new GridLayout(3,1)); //Layout of Container Panel
bottomContainerPanel.add(subPanel1, BorderLayout.NORTH);
bottomContainerPanel.add(subPanel2, BorderLayout.CENTER);
bottomContainerPanel.add(subPanel3, BorderLayout.SOUTH);
tellerWindow.getContentPane().add(bottomContainerPanel, BorderLayout.SOUTH);
You need to add a single container panel as the SOUTH panel of the frame. The container itself should have the layout that you want for everything that goes at the bottom.
If you just want to split panel onto 2 equal parts at south and north use GridLayout. If you want something in the middle you can use BorderLayout.
If you want to give your user ability to change the sub-panels size use JSplitPane.
I had a similar problem trying to put several rows of buttons into a panel borrowed from the ListDemo example. Well, the first thing to do is to read about BorderLayout: How to Use BorderLayout, or at least see the image shown there:
You cannot have multiple bottom rows in a BorderLayout. But you can use a nested layout. What we need is a BoxLayout, see How to Use BoxLayout:
.
We just have to replace the buttons shown on the above image by rows of buttons.
public class MyStuff extends JPanel {
...
public MyStuff() {
super(new BorderLayout());
...
JPanel buttonArea = new JPanel();
buttonArea.setLayout(new BoxLayout(buttonArea, BoxLayout.PAGE_AXIS));
add(buttonArea, BorderLayout.PAGE_END);
...
//if you dislike the default center alignment:
//panelWithButtons1.setAlignmentX(Component.LEFT_ALIGNMENT);
buttonArea.add(...);// add the 1st panel with buttons
buttonArea.add(...);// add the 2nd panel with buttons
buttonArea.add(...);// add the 3rd panel with buttons
I'm still trying to figure out BorderLayout in JavaSwing, and it's really frustrating.
I want to be able to split a pane into 3 contained sub-panels, but I'm not entirely sure how to contain it.
Here is my class Game, which contains panels ControlPanel, StatePanel, and Board (really just an extension of JPanel). I want to split the panel into those three sections like this:
Here is my code so far:
public class Game extends JPanel {
private int panespace=2;
private JPanel ControlPanel;
private JPanel StatePanel;
private Board board;
public Game()
{
setLayout(new BorderLayout(panespace, panespace));
ControlPanel=new JPanel();
ControlPanel.setLayout(new BorderLayout(panespace, panespace));
ControlPanel.setBorder(new LineBorder(Color.red, 10));
ControlPanel.setSize(100,100);
super.add(ControlPanel, BorderLayout.EAST);
StatePanel=new JPanel();
StatePanel.setLayout(new BorderLayout(panespace, panespace));
StatePanel.setBorder(new LineBorder(Color.green, 10));
StatePanel.setSize(200, 200);
super.add(StatePanel, BorderLayout.EAST);
board = new Board();
board.setLayout(new BorderLayout(panespace, panespace));
board.setBorder(new LineBorder(Color.yellow, 10));
board.setSize(300, 300);
super.add(board, BorderLayout.NORTH);
setVisible(true);
}
}
Preferably, this would use BorderLayout, but I seem to be doing it incorrectly. I've tried reading the materials that Oracle provides, but they haven't been particularly helpful. At this point, I am at the point where I want to hard code values in, but I know that I should be able to split it to have each panel take up as much of the larger Game panel as possible.
As mkhelif said, you can't have two things in the same slot. What you want is board to go into CENTER, then create another JPanel in SOUTH which contains ControlPanel and StatePanel in a FlowLayout.
You are adding ControlPanel and StatePanel on EAST both. Try adding ControlPanel on WEST.
Besides the East/East thing, you also extend JPanel instead of JFrame. ie, where you have
public class Game extends JPanel
You probably want
public class Game extends JFrame
You also set up borders, but put nothing in the panels, so the borders surround an empty space, making them look like thick lines instead of actual borders. You might try adding a JTextArea in each panel.
Also, when you change size by dragging the border, the CENTER section (which you don't use) is what grows larger. If you want the result I think you want, you'll have to use a different Layout.
Good luck!