Centering a JLabel on a JPanel - java

I'm using the NetBeans GUI builder to handle my layout (I'm terrible with LayoutManagers) and am trying to place a simple JLabel so that it is always centered (horizontally) inside its parent JPanel. Ideally, this would maintain true even if the JPanel was resized, but if that's a crazy amount of coding than it is sufficient to just be centered when the JPanel is first created.
I'm bad enough trying to handle layouts myself, but since the NetBeans GUI Builder autogenerates immutable code, it's been impossible for me to figure out how to do this centering, and I haven't been able to find anything online to help me.
Thanks to anybody who can steer me in the right direction!

Here are four ways to center a component:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
class CenterComponent {
public static JLabel getLabel(String text) {
return getLabel(text, SwingConstants.LEFT);
}
public static JLabel getLabel(String text, int alignment) {
JLabel l = new JLabel(text, alignment);
l.setBorder(new LineBorder(Color.RED, 2));
return l;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel p = new JPanel(new GridLayout(2,2,4,4));
p.setBackground(Color.black);
p.setBorder(new EmptyBorder(4,4,4,4));
JPanel border = new JPanel(new BorderLayout());
border.add(getLabel(
"Border", SwingConstants.CENTER), BorderLayout.CENTER);
p.add(border);
JPanel gridbag = new JPanel(new GridBagLayout());
gridbag.add(getLabel("GridBag"));
p.add(gridbag);
JPanel grid = new JPanel(new GridLayout());
grid.add(getLabel("Grid", SwingConstants.CENTER));
p.add(grid);
// from #0verbose
JPanel box = new JPanel();
box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS ));
box.add(Box.createHorizontalGlue());
box.add(getLabel("Box"));
box.add(Box.createHorizontalGlue());
p.add(box);
JFrame f = new JFrame("Streeeetch me..");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(p);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
});
}
}

By using Borderlayout, you can put any of JComponents to the CENTER area. For an example, see an answer to Stack Overflow question Get rid of the gap between JPanels. This should work.

Even with BoxLayout you can achieve that:
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS ));
JLabel label = new JLabel();
listPane.add(Box.createHorizontalGlue());
listPane.add(label);
listPane.add(Box.createHorizontalGlue());
mKorbel's solution is perfect for your goal. Anyway I always like to suggest BoxLayout because it's very flexible.

Mara: "thanks for your response, however the NetBeans GUI Build uses GroupLayout and this is not overridable."
Not true! Right click anywhere inside JFrame (or any other GUI container) in NetBeans GUI builder and select "Set Layout". By default is selected "Free Design", which is Group layout, but you can select any other layout including Border layout as advised by mKorbel.

There's many ways to do this, depending on the layout manager(s) you use. I suggest you read the Laying Out Components Within a Container tutorial.
I believe the following will work, regardless of layout manager:
JLabel.setHorizontalAlignment(SwingConstants.CENTER)

Related

Layout Problem in Java - set a 20%opaque Panel on Bottom of JFrame

Well, actually I have a Layout problem in java Swing. I simply want to add a JPanel on the bottom of a Frame - a coding snipplet that might be done with every web based language in about 5 Minutes. Not so in Java. I tried to add a jPanel to a jFrame, that Contains a jContentPane, set the size of the jPanel to what I need and to repaint and revalidate the jFrame, as well as setting the LayOutManager to null.
Java shows me in this case a full-width jPanel, that fills my whole jFrame.
Therefore I tried another approach: I divided my jPanel in a fully transparent jPanel on top and a 20%opaque jPanel on the bottom. Still it didn't work out as expected.
Since then I tried to resize the child jPanels of my new Panel and the Panel as well and tried to repaint and revalidate the jFrame. Without any effect.
Despite of my efforts, java still shows me a full sized 20%opaque jPanel on the whole jFrame, that now contains another 20%opaque jPanel on Top.
I know that this whole problem is caused by the LayoutManager, Java useless per Default. However, it is not an option to set the LayoutManager to null or even change the LayoutManager of our jFrame, because that would lead us to refactor the whole functionality of our tiny app we worked on for several weeks.
public void showUndoPanel() {
System .out.println("Show Undo Panel");
JPanel myPanel = new JPanel(null);
JPanel glassPanel = new JPanel();
JPanel ContentPanel = new JPanel();
JLabel myJLabel = new JLabel("Great Job!");
myPanel.setBackground(new Color(255,122,122,100));
glassPanel.setSize(650, 550);
glassPanel.setBackground(new Color(255,122,122,100));
myPanel.add(glassPanel);
ContentPanel.setSize(650, 30);
ContentPanel.setBackground(new Color(255,122,122,20));
ContentPanel.add(myJLabel);
myPanel.revalidate();
myPanel.repaint();
undoPanel = myPanel;
myJFrame.add(undoPanel);
myJFrame.revalidate();
}
What I expected:
What it actually does:
Well, I solved the problem by using a BoxLayoutManager and a RigidArea. In case if anyone else may encounter that problem again in the future, I decided to provide the code for this simple solution.
public void showUndoPanel() {
System .out.println("Show Undo Panel");
JPanel myPanel = new JPanel(null);
JPanel glassPanel = new JPanel();
JPanel ContentPanel = new JPanel();
JLabel myJLabel = new JLabel("Great Job!");
myPanel.setBackground(new Color(255,255,255,0));
myPanel.setLayout(new BoxLayout(myPanel, BoxLayout.PAGE_AXIS));
glassPanel.setSize(650, 650);
glassPanel.setBounds(0,0,650,550);
glassPanel.setBackground(new Color(255,122,122,0));
myPanel.add(glassPanel);
myPanel.add(Box.createRigidArea(new Dimension(0,450)));
ContentPanel.setSize(650, 30);
ContentPanel.setBounds(0,750,650,30);
ContentPanel.setBackground(new Color(255,122,122,20));
ContentPanel.add(myJLabel);
myPanel.add(ContentPanel);
myPanel.revalidate();
myPanel.repaint();
undoPanel = myPanel;
myJFrame.add(undoPanel);
myJFrame.revalidate();
}
Now it behaves as expected:
BorderLyout would make it easier to implement.
Note the comments in the following mre:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
private static JFrame myJFrame;
public static void main(String[] args) {
myJFrame = new JFrame();
myJFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
myJFrame.setLocationRelativeTo(null);
showUndoPanel();
myJFrame.pack();
myJFrame.setVisible(true);
}
public static void showUndoPanel() {
JPanel myPanel = new JPanel();
myPanel.setBackground(new Color(255,255,255,0));
myPanel.setLayout(new BorderLayout());
JPanel glassPanel = new JPanel(); //uses FlowLayout by default
//glassPanel.setSize(650, 650); //use preferred size
glassPanel.setPreferredSize(new Dimension(650, 650));
//glassPanel.setBounds(0,0,650,550); //no need to set bounds. bounds are set by the layout manager
glassPanel.setBackground(new Color(255,122,122,0));
myPanel.add(glassPanel, BorderLayout.CENTER);
JPanel contentPanel = new JPanel(); //uses FlowLayout by default
//contentPanel.setSize(650, 30);//use preferred size
contentPanel.setPreferredSize(new Dimension(650, 30));
//contentPanel.setBounds(0,750,650,30); //no need to set bounds. bounds are set by the layout manager
contentPanel.setBackground(new Color(255,122,122,20));
JLabel myJLabel = new JLabel("Great Job!");
contentPanel.add(myJLabel);
myPanel.add(contentPanel, BorderLayout.SOUTH);
myJFrame.add(myPanel);
}
}

How do I put a JPanel in center of a JFrame irrespective the size of JFrame (of course its size is greater than jpanel)? [duplicate]

I'm using the NetBeans GUI builder to handle my layout (I'm terrible with LayoutManagers) and am trying to place a simple JLabel so that it is always centered (horizontally) inside its parent JPanel. Ideally, this would maintain true even if the JPanel was resized, but if that's a crazy amount of coding than it is sufficient to just be centered when the JPanel is first created.
I'm bad enough trying to handle layouts myself, but since the NetBeans GUI Builder autogenerates immutable code, it's been impossible for me to figure out how to do this centering, and I haven't been able to find anything online to help me.
Thanks to anybody who can steer me in the right direction!
Here are four ways to center a component:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
class CenterComponent {
public static JLabel getLabel(String text) {
return getLabel(text, SwingConstants.LEFT);
}
public static JLabel getLabel(String text, int alignment) {
JLabel l = new JLabel(text, alignment);
l.setBorder(new LineBorder(Color.RED, 2));
return l;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel p = new JPanel(new GridLayout(2,2,4,4));
p.setBackground(Color.black);
p.setBorder(new EmptyBorder(4,4,4,4));
JPanel border = new JPanel(new BorderLayout());
border.add(getLabel(
"Border", SwingConstants.CENTER), BorderLayout.CENTER);
p.add(border);
JPanel gridbag = new JPanel(new GridBagLayout());
gridbag.add(getLabel("GridBag"));
p.add(gridbag);
JPanel grid = new JPanel(new GridLayout());
grid.add(getLabel("Grid", SwingConstants.CENTER));
p.add(grid);
// from #0verbose
JPanel box = new JPanel();
box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS ));
box.add(Box.createHorizontalGlue());
box.add(getLabel("Box"));
box.add(Box.createHorizontalGlue());
p.add(box);
JFrame f = new JFrame("Streeeetch me..");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(p);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
});
}
}
By using Borderlayout, you can put any of JComponents to the CENTER area. For an example, see an answer to Stack Overflow question Get rid of the gap between JPanels. This should work.
Even with BoxLayout you can achieve that:
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS ));
JLabel label = new JLabel();
listPane.add(Box.createHorizontalGlue());
listPane.add(label);
listPane.add(Box.createHorizontalGlue());
mKorbel's solution is perfect for your goal. Anyway I always like to suggest BoxLayout because it's very flexible.
Mara: "thanks for your response, however the NetBeans GUI Build uses GroupLayout and this is not overridable."
Not true! Right click anywhere inside JFrame (or any other GUI container) in NetBeans GUI builder and select "Set Layout". By default is selected "Free Design", which is Group layout, but you can select any other layout including Border layout as advised by mKorbel.
There's many ways to do this, depending on the layout manager(s) you use. I suggest you read the Laying Out Components Within a Container tutorial.
I believe the following will work, regardless of layout manager:
JLabel.setHorizontalAlignment(SwingConstants.CENTER)

Best practice to resize JScrollPane

I read some answered questions in this forum (this one for example) where it is strictly recommended to avoid the use of setXXXSize() methods to resize components in swing applications.
So, coming to my problem, i would like to know how to best resize a JScrollPane in order to avoid its parent panel to increase its size without any control.
Before writing some code, i want to describe the real situation, since i will post a "toy example".
In my JFrame i'm currently using a border layout for my content pane. At BorderLayout.CENTER there is a JPanel where i do some custom painting.
At BorderLayout.EAST there is a JPanel (say eastPanel) containing some components inside another panel (this panel will be added to eastPanel at BorderLayout.NORTH), and a JScrollPane which contains a JTable (added to eastPanel at BorderLayout.CENTER). This table will have a lot of rows.
Since i want eastPanel's height to be the same as centerPanel's height, i need some way to avoid the JScrollPane to increase its size in order to try to display as much rows as possible.
For now i wasn't be able to find another solution apart from calling setPreferredSize on the eastPanel containing the scrollpane, but i have to admit that i hate this kind of solution.
Sample Code
In this code sample i added some random labels at the north of eastPanel and inside the JScrollPane, since my purpose was to post a short sample of code.
However, the situation is very similar to the one i have described above.
I wasn't be able to solve my problem without using this "terrible" line of code :
eastPanel.setPreferredSize(new Dimension(eastPanel.getPreferredSize().width, centerPanel.getPreferredSize().height));
I would like to avoid a more complex layout for a simple situation like this. Am i missing something ? Also, is setting that empty border an acceptable way to set the size of the panel where i will do some custom painting?
Code :
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class Test
{
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new TestFrame().setVisible(true);
}
catch(Exception exception) {
JOptionPane.showMessageDialog(null, "Fatal error while initialiing application", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
}
}
class TestFrame extends JFrame
{
public TestFrame() {
super("Test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel pane = new JPanel(new BorderLayout(20, 0));
pane.setBorder(new EmptyBorder(20, 20, 20, 20));
JPanel centerPanel = new JPanel();
centerPanel.setBackground(Color.WHITE);
centerPanel.setBorder(new EmptyBorder(400, 400, 0, 0));
// centerPanel.setPreferredSize(new Dimension(400, 400));
JPanel eastPanel = new JPanel(new BorderLayout(0, 20));
JPanel labelsContainer = new JPanel(new GridLayout(0, 1));
for(int i=0;i<7;i++) labelsContainer.add(new JLabel(String.valueOf(i)));
eastPanel.add(labelsContainer, BorderLayout.NORTH);
JPanel moreLabelsContainer = new JPanel(new GridLayout(0, 1));
for(int i=7;i<70;i++) moreLabelsContainer.add(new JLabel(String.valueOf(i)));
JScrollPane scroll = new JScrollPane(moreLabelsContainer, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
eastPanel.add(scroll, BorderLayout.CENTER);
eastPanel.setPreferredSize(new Dimension(eastPanel.getPreferredSize().width, centerPanel.getPreferredSize().height));
pane.add(centerPanel, BorderLayout.CENTER);
pane.add(eastPanel, BorderLayout.EAST);
setContentPane(pane);
pack();
setLocationRelativeTo(null);
}
}
Thanks for your help !
I am not aware of a layout manager that restricts the height of the panel based on the height of a specific component in the panel.
One way is to customize the behaviour of the parent panel that contains the two child components.
The code might be something like:
#Override
public Dimension getPreferredSize()
{
Dimension d = super.getPreferredSize();
BorderLayout layout = (BorderLayout)getLayout();
Component center = layout.getLayoutComponent(BorderLayout.CENTER);
int centerHeight = center.getPreferreidSize().height;
if (d.height > centerHeight)
d.height = centerHeight;
return d;
}
This approach will allow for dynamic calculation of the height based on the component in the center.
Another option is to write you own layout manager. Then you can control this type of logic from within the layout manager.
Also, is setting that empty border an acceptable way to set the size of the panel where i will do some custom painting?
I override the getPreferredSize() to return the appropriate dimension.
By using the EmptyBorder you lose the ability to add a true Border to the panel, so I wouldn't recommend it.

Multiple panels in JFrame

The useless Layout Manager guy is back again, I just can't seem to get my head around these darn layouts and make them work the way I want.
Anyway, I want to have a JFrame which has one large panel at the top (I call it a header) which runs from the left to right side of the frame at the north part of the frame, then four panels below it, two just below the header and two below those, and finally a "footer" panel, basically the same as the header panel, only at the south part of the frame.
Like this:
I had code which had the four middle panels working fine, but the header panel just messed everything up, and I have since been testing with the demo layout manager code for GridBagLayout, GridLayout again and BoxLayout. I can't getting any to work as I want.
For the aware of you here, you will probably notice I've already had a question related to this, and if having two similar questions are not allowed, please make me aware and I will move this to my previous question and this can be closed.
public Shop() {
shopUI = new JFrame("Shop Menu");
shopUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shopUI.setBounds(100, 100, 700, 500);
shopUI.setResizable(false);
allPanels = new JPanel();
headerPanel = new JPanel();
headerPanel.setLayout(new BorderLayout());
headerPanel.setBackground(Color.cyan);
mainPanel = new JPanel();
mainPanel.setLayout(new GridLayout(2,2));
topLeft = new JPanel();
topLeft.setBackground(Color.pink);
topRight = new JPanel();
topRight.setBackground(Color.black);
bottomLeft = new JPanel();
bottomLeft.setBackground(Color.green);
bottomRight = new JPanel();
bottomRight.setBackground(Color.blue);
footerPanel = new JPanel();
footerPanel.setLayout(new BorderLayout());
footerPanel.setBackground(Color.magenta);
mainPanel.add(topLeft);
mainPanel.add(topRight);
mainPanel.add(bottomLeft);
mainPanel.add(bottomRight);
allPanels.add(headerPanel, BorderLayout.NORTH);
allPanels.add(footerPanel, BorderLayout.SOUTH);
allPanels.add(mainPanel);
shopUI.add(allPanels);
shopUI.setVisible(true);
}
I suggest learning about border layout.
for what you want, put the header in the NORTH of the border panel, and the footer in the SOUTH. How you do your other panels depends a bit on what you want them to do; if you always want them to be the same size as each other, you can use a gridlayout for them; if not, you can use boxlayout to lay either the two pairs horizontally or the two pairs vertically, again depending on what you want them to do when the frame resizes.
I think using layout managers is simplified by deciding what you want to happen in the first place, including what happens when the frame is resized. That's a large part of what layouts are all about, anyway -- what stretches, what lines up, etc.
Anyway. what you have there looks like classic BorderLayout to me. Let us know if you need further help. Incidentally, BorderLayout is default for JFrame...
edit...
this will get more interesting when you put something in the panels...
package simpleborderlayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main
{
public static void main(String[] args)
{
Main main = new Main(args);
main.go();
}
public Main(String ... args)
{}
public void go()
{
JPanel headerPanel = getPanel(Color.RED);
JPanel footerPanel = getPanel(Color.BLUE);
JPanel p1 = getPanel(Color.GRAY);
JPanel p2 = getPanel(Color.GRAY);
JPanel p3 = getPanel(Color.GRAY);
JPanel p4 = getPanel(Color.GRAY);
GridLayout gridLayout = new GridLayout(2,2);
JPanel middlePanel = new JPanel(gridLayout);
middlePanel.add(p1);
middlePanel.add(p2);
middlePanel.add(p3);
middlePanel.add(p4);
JFrame mainFrame = new JFrame();
mainFrame.add(headerPanel, BorderLayout.NORTH);
mainFrame.add(middlePanel, BorderLayout.CENTER);
mainFrame.add(footerPanel, BorderLayout.SOUTH);
mainFrame.pack();
mainFrame.setVisible(true);
}
private JPanel getPanel(Color c)
{
JPanel result = new JPanel();
result.setBorder(BorderFactory.createLineBorder(c));
return result;
}
}

Setting up JFrame with leftPanel, topPanel and bottomPanel

First time posting here, and let me first say that I'm a bit of a Java noob, I've only started learning it in uni this year.
So anyway, I have to create a UI for a Tamagotchi project, and I'm trying to create it using JFrame etc.
This is what I'm trying to create:
This is my code so far:
import javax.swing.*;
import java.awt.*;
public class DogUI {
private JFrame DogUI;
private JPanel leftPanel, topPanel, bottomPanel, rightPanels;
private JButton jb;
private JLabel lb, lb1, lb2;
public DogUI() {
GUI();
}
public void GUI() {
DogUI = new JFrame("Dog UI");
DogUI.setSize(800, 600);
DogUI.setResizable(false);
leftPanel = new JPanel();
leftPanel.setBackground(Color.green);
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
topPanel = new JPanel();
topPanel.setBackground(Color.white);
bottomPanel = new JPanel();
bottomPanel.setBackground(Color.red);
rightPanels = new JPanel();
rightPanels.setLayout(new BoxLayout(rightPanels, BoxLayout.X_AXIS));
DogUI.setVisible(true);
lb = new JLabel("Name: ");
leftPanel.add(lb);
lb1 = new JLabel("Image");
topPanel.add(lb1);
lb2 = new JLabel("Buttons");
bottomPanel.add(lb2);
rightPanels.add(topPanel);
rightPanels.add(bottomPanel);
DogUI.add(rightPanels);
}
public static void main(String [] args) {
new DogUI();
}
}
This is what I end up with:
I'm sure it's something simple, or perhaps I am going the complete wrong way about doing it, but please try explain it in layman's terms if possible.
Thanks.
Chris.
You are only adding the rightPanels to the frame, you never add leftPanel
The rightPanel is using X_AXIS which is horizontal. You want Y_AXIS
When you do add the leftPanel, you're going to want to set your frame's layout to GridLayout(1, 2). See GridLayout
setVisible after adding all your components.
Follow Java namingConvention. variables begin with lower case, using camel casing. DogUI → dogUI
Swing apps should be run from the Event Dispatch Thread (EDT). You can do this by wrapping the code in the main in a SwingUtilities.invokeLater(...). See more at Initial Threads
Try using a GridLayout instead.
public void GUI() {
DogUI = new JFrame("Dog UI");
DogUI.setSize(800, 600);
DogUI.setResizable(false);
DogUI.setLayout(new GridLayout(1,2));//1row 2col
leftPanel = new JPanel();
leftPanel.setBackground(Color.green);
topPanel = new JPanel();
topPanel.setBackground(Color.white);
bottomPanel = new JPanel();
bottomPanel.setBackground(Color.red);
rightPanels = new JPanel();
rightPanels.setLayout(new GridLayout(2,1));//2row 1col
lb = new JLabel("Name: ");
leftPanel.add(lb);
lb1 = new JLabel("Image");
topPanel.add(lb1);
lb2 = new JLabel("Buttons");
bottomPanel.add(lb2);
rightPanels.add(topPanel);
rightPanels.add(bottomPanel);
DogUI.add(leftPanel);
DogUI.add(rightPanels);
DogUI.setVisible(true);
}
It sounds like you want a parent JPanel with a BorderLayout. That parent JPanel contains two other panels, on the east and west side of it. The west side can contain your progress panel, and the east side contains another JPanel, which has a GridLayout of 1 column and 2 rows, or alternatively, a BorderLayout. From there you can add the other two JPanels to that last JPanel which represent whatever that right hand side of the picture shows.
The overall parent JPanel could also be a GridLayout with 2 columns and 1 row, but a BorderLayout might look better as you might find one side of the application might not need as much space and might limit how much space it takes up. Perhaps the east panel should be a BorderLayout too as your image might not take up that much space on the north side giving the components on the south side the rest of the container's available space.

Categories