JavaSwing Layout Confusion/Difficullties - java

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!

Related

Setting component sizes inside Jpanels with Borderlayout

I have a project to copy the google sign-in GUI here . So far I'm still searching on what I'm gonna start with, but after some research I think it is possible on BorderLayout to do this. Im getting how it works by readjusting everything through borders, and I kind of like it because it is quite responsive compared to having null layout and coding every setBounds for each component.
I've been imagining using a background panel, a panel for the fill up form,
and creating panels for each pair of label and textfields to properly create the space and stacking (or nesting) them on top of the other. Our teacher just told us to snip out the image, she just wants if we know how to design something out of scratch. That and also saving the input into a text file.
However, I can't seem to grasp the concept of increasing the component size inside the borders to imitate the gaps between the text fields, like some sort of a padding between components? Using setSize doesnt work and so far my search only results into resizing borders, or perhaps I still have not entered the right searachable term for it?
Also, Ive been looking for another way and I think this project will also work using GridBaglayout. However many people say GridBagLayout is too complicated. What do you think would be easier?
In my experience almost every (99%) of the panels using GridBagLayout can be designed by using all other layouts. So, someone could say that GridBagLayout is optional
In your situation, avoiding the use of a GridBagLayout is easy. Take a look at the following code:
public class NoGridBagLayout extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new NoGridBagLayout().setVisible(true));
}
public NoGridBagLayout() {
super();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setExtendedState(MAXIMIZED_BOTH);
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.setBorder(new TitledBorder("borderPanel - BorderLayout"));
JLabel label = new JLabel("Create a google account.");
label.setHorizontalAlignment(JLabel.CENTER);
label.setFont(label.getFont().deriveFont(25f));
borderPanel.add(label, BorderLayout.PAGE_START);
setContentPane(borderPanel);
JPanel gridPanel = new JPanel(new GridLayout(1, 2));
gridPanel.setBorder(new TitledBorder("gridPanel - GridLayout"));
getContentPane().add(gridPanel, BorderLayout.CENTER);
JPanel leftBoxedPanel = new JPanel(); // Fill it with panels using BoxLayout.X_AXIS
leftBoxedPanel.setLayout(new BoxLayout(leftBoxedPanel, BoxLayout.Y_AXIS));
leftBoxedPanel.setBorder(new TitledBorder("leftBoxedPanel - BoxLayout.Y_AXIS"));
gridPanel.add(leftBoxedPanel);
JPanel rightBoxedPanel = new JPanel(); // Fill it with panels using BoxLayout.X_AXIS
rightBoxedPanel.setLayout(new BoxLayout(rightBoxedPanel, BoxLayout.Y_AXIS));
rightBoxedPanel.setBorder(new TitledBorder("rightBoxedPanel - BoxLayout.Y_AXIS"));
gridPanel.add(rightBoxedPanel);
}
}
Preview:

Java setOpaque method not working to add panels over the top of others

I am attempting to place two panels over the top of another two panels, so the positions match exactly. This will allow me to then paint over the top of the previous(bottom) panels. The reason for doing this, is that I have implemented a "drag a rectangle" zoom function, so on the panel the user will drag the mouse to draw a rectangle, and then the panel will become filled with the contents of that rectangle. However, I have now decided I would like include a visual representation of the rectangle as the user drags it.
Since I (assume) I cannot draw the rectangle on the bottom panel, since it already has a complicated paint on it anyway, I figured I would be able to draw it onto another panel that I would place on top. (If there is any easier way please shout!)
I am happy I have been able to get the panels into the correct position, using a BorderLayout/GridLayout combo, without the need for absolute positing, however the setOpaque method is not working on any of the three panels I have added. Does anyone know why this is?
Many thanks in advance, code below:
public void initiate() {
JPanel panel1 = new JPanel();
mandPanel mandDisplay = new mandPanel();
juliaPanel juliaDisplay = new juliaPanel();
JPanel detailsPanel = new JPanel();
JPanel bottomDetails = new JPanel();
JPanel panelForDisplays = new JPanel();
JPanel listenerPanelHolder = new JPanel();
JPanel listenerPanel = new JPanel();
JPanel blankPanel = new JPanel();
panelForDisplays.setLayout(new GridLayout(1,2));
detailsPanel.setLayout(new FlowLayout());
bottomDetails.setLayout(new FlowLayout());
panel1.setLayout(new BorderLayout());
panelForDisplays.add(mandDisplay);
panelForDisplays.add(juliaDisplay);
listenerPanelHolder.setOpaque(false);
listenerPanel.setOpaque(false);
blankPanel.setOpaque(false);
listenerPanelHolder.setLayout(new GridLayout(1,2));
listenerPanelHolder.add(listenerPanel);
listenerPanelHolder.add(blankPanel);
panel1.add(detailsPanel,BorderLayout.NORTH);
panel1.add(panelForDisplays,BorderLayout.CENTER);
panel1.add(listenerPanel,BorderLayout.CENTER);
panel1.add(bottomDetails, BorderLayout.SOUTH);
setContentPane(panel1);
setSize(width*2, height);
setResizable(false);
this.addWindowListener(new onClose(savedJulias));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
PS: A lot of code is omitted to avoid mess, but if anyone thinks they could solve with more code please say! Thanks :)
First off, adding two components at the BorderLayout.CENTER position replaces the first component with the 2nd, and so the 2nd doesn't cover the 1st, it displaces it. As per the BorderLayout API:
Each region may contain no more than one component,...
But having said that, as I understand your problem in greater detail, I think that your best solution is not to use JLayeredPane or to overlay two JPanels. The best solution is in fact to draw directly on the image-displaying JPanel. This is not hard to do, and shouldn't over complicate your code. For example.
You can use JLayeredPane to place one component to the top of the other. You can check this

Java add more than one JPanel objects into JFrame

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.

How can I make JFrame resize automatically to display all buttons

I have a simple swing application which consists of a JLabel and three buttons. The three buttons are in their own JPanel which is in a JFrame along with the JLabel. The JPanel uses flowlayout manager to arrange the buttons horizontally and the JFrame uses the BorderLayout manager to arrange the JLabel and JPanel vertically.
My problem is when I launch the application, during the course of use the text on one of the buttons changes which increases its width. However, the window doesn't resize to accomdate this and one of the buttons disappears. I thought about calling pack() again, but the JFrame is a local variable in my constructor, also, I shouldn't have to tell my program to resize, right? I haven't been able to find anything on google or here to help me but there must be a simple solution, what am I missing? Code is below.
playButton = new JButton("Play");
pauseButton = new JButton("Pause");
stopButton = new JButton("Stop");
curTrackLabel = new JLabel("No Track Selected");
JFrame myFrame = new JFrame("MediaPlayer");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setTitle("MediaPlayer");
myFrame.setLocation(400,300);
JPanel topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
myFrame.add(topPanel);
JPanel buttonPanel = new JPanel(new FlowLayout());
buttonPanel.add(playButton);
buttonPanel.add(pauseButton);
buttonPanel.add(stopButton);
topPanel.add(buttonPanel, BorderLayout.CENTER);
topPanel.add(curTrackLabel, BorderLayout.NORTH);
playButton.addActionListener(new playButtonHandler());
pauseButton.addActionListener(new pauseButtonHandler());
stopButton.addActionListener(new stopButtonHandler());
myFrame.pack();
myFrame.setVisible(true);
Maybe try
((JFrame)myButton.getTopLevelAncestor()).pack();
Where myButton is the button whose text is modified during execution.
As with learning any GUI software, experimentation is best. Try messing with BorderLayouts with nested JPanels.
Ultimately, you use JPanel with a BorderLayout (Flow Layout is OK but really when resizing the window, it epically fails). See http://download.oracle.com/javase/tutorial/uiswing/layout/border.html to learn more about BorderLayouts.
Now for your layout scheme it should be something along the lines of:
Top Level Container: JFrame
JFrame contains a JPanel (Call this
JPanel 1) with a BorderLayout.
The three buttons should be in a
SEPARATE jPanel (JPanel 2). JPanel
1 should add the three buttons as
BorderLayout.CENTER. In this way,
the window will resize if the button
changes its width and/or hright.
The JLabel should be added as
BorderLayout.LINE_START.
The tutorial at: http://download.oracle.com/javase/tutorial/uiswing/layout/border.html should help you with this. But in general, use the following:
Use JPanel and nest JPanels as necessary
BorderLayout.CENTER will accomodate size changes---this is the key! (Experiment with this)
JFrame should only be used as a top level container (for more complex GUIs, this is true).
If you require more flexibility, check out JGoodies: http://www.jgoodies.com/ . This is more along the lines of creating forms.

Using different layouts in GUIs

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.

Categories

Resources