Alignment of JPanels - java

I'm fairly new to Java and I'm at a complete loss. I'm trying to create a simple program that draws a circle and outputs it's properties on the screen. Functionally, the program works fine, but the layout of the JPanels is off. For some reason, there is a gap between the JPanel that holds the 'Draw Me' button and the JPanel that holds the circle. Even if I resize the height of the program, the gap doesn't disappear. Likewise, the labels within the program aren't aligning to the left, they kind of sit off-center for some weird reason, removing the border doesn't seem to help. I'm stuck...
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
public class MainPanel extends JPanel {
private JPanel userHelpSubPanel;
private JPanel inputSubPanel;
private JPanel buttonSubPanel;
private JPanel drawSubPanel;
private JPanel resultsSubPanel;
private JLabel userHelpLabel;
private JLabel diameterLabel;
private JLabel circumferenceLabel;
private JLabel areaLabel;
private JButton drawButton;
private JTextField inputTextField;
private float radius;
public MainPanel() {
radius = 0;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
userHelpSubPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
inputSubPanel = new JPanel();
inputSubPanel.setLayout(new BoxLayout(inputSubPanel, BoxLayout.Y_AXIS));
drawSubPanel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.draw(new Ellipse2D.Double(150, 20, radius * 2, radius * 2));
}
};
resultsSubPanel = new JPanel();
resultsSubPanel.setLayout(new BoxLayout(resultsSubPanel, BoxLayout.Y_AXIS));
buttonSubPanel = new JPanel();
userHelpLabel = new JLabel();
userHelpLabel.setText("Enter the radius of the ellipse: ");
inputTextField = new JTextField();
inputTextField.setMaximumSize(new Dimension(Integer.MAX_VALUE, inputTextField.getPreferredSize().height));
drawButton = new JButton("Draw Me");
drawButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
MainPanel.this.radius = Float.parseFloat(inputTextField.getText());
diameterLabel.setText(String.format("Diameter: %.1f", 2 * radius));
circumferenceLabel.setText(String.format("Circumference: %.1f", 2 * Math.PI * radius));
areaLabel.setText(String.format("Area: %.1f", Math.PI * Math.pow(radius, 2)));
drawSubPanel.repaint();
}
});
circumferenceLabel = new JLabel("Circumference: N/A");
diameterLabel = new JLabel("Diameter: N/A");
areaLabel = new JLabel("Area: N/A");
userHelpSubPanel.add(userHelpLabel);
inputSubPanel.add(inputTextField);
buttonSubPanel.add(drawButton);
resultsSubPanel.add(diameterLabel);
resultsSubPanel.add(circumferenceLabel);
resultsSubPanel.add(areaLabel);
add(userHelpLabel);
add(inputSubPanel);
add(buttonSubPanel);
add(drawSubPanel);
add(resultsSubPanel);
}
}
And here is what it looks like....

BoxLayout will respect the minimum and maximum sizes of a component. So if there is extra space in the frame then the panels will be given more space.
The solution is to override the getMaximumSize() method of the custom panel to return the preferred size of the panel.
Every Swing component is responsibile for determiningin its own preferred size. So this would mean you also need to override the getPreferredSize() of the panel where you do the custom painting. The preferred size would be based on the size/location of the oval that you are drawing.

A simple fix for these issues is to give your panels (relevant ones) an empty border and then reduce the specific direction that is too large:
// this example reduces the top of your circle panel.
drawSubPanel.setBorder(new EmptyBorder(-100, 0, 0, 0));
Obviously this isn't the root of the problem and isn't the most optimal but it should do the trick.

Related

How to put a JPanel with 2DGraphics on a JFrame (same class)

I have a class that extends JFrame and I would like to add two JPanels to that JFrame: a text panel and a graphics panel. My text panel is a panel containing a label with text. My graphics panel will contain a graph (created using 2DGraphics). I'm adding the graphic panel to the left side (0,0) and the text panel to right side (1,0) using a gridbaglayout method. However, the graphic panel won't show up in the frame. I have tried numerous methods to try to get the panel to show up with no success.
import java.awt.*;
import javax.swing.*;
public class GraphicsTest extends JFrame {
private final JPanel textPanel;
private final JLabel textLabel;
public GraphicsTest() {
textPanel = new JPanel(new BorderLayout());
textLabel = new JLabel("Home label");
this.setBounds(180, 112, 1080, 675);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new GridBagLayout());
textPanel.add(textLabel, BorderLayout.NORTH);
addComponent(this, new GraphicPanel(), 0, 0, 1, 1, GridBagConstraints.CENTER);
addComponent(this, textPanel, 1, 0, 1, 1, GridBagConstraints.CENTER);
this.setVisible(true);
}
public class GraphicPanel extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void paintComponents(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
// drawing lots of shapes and lines, removed for readibility
}
}
public void addComponent(JFrame frame, JComponent component, int x, int y, int width, int height, int align) {
GridBagConstraints c = new GridBagConstraints();
c.gridx = x;
c.gridy = y;
c.gridwidth = width;
c.gridheight = height;
c.weightx = 100.0;
c.weighty = 100.0;
c.insets = new Insets(5, 0, 5, 0);
c.anchor = align;
c.fill = GridBagConstraints.NONE;
frame.add(component, c);
}
public static void main(String[] args) {
GraphicsTest gui = new GraphicsTest();
}
}
Works fine for me when I use a size like (200, 200).
GridbagLayout works such that if a component can't be displayed at its preferred size, then it will be displayed at its minimum size, which would be (0, 0).
So whether (700, 700) works will depend on your screen resolution. It also works at (700, 600) for my screen.
I question if you want to use a GridBadLayout. Maybe just use a BorderLayout. The custom painting panel would go in the CENTER so it will grow/shrink as the frame size changes. The other panel would go to the LINE_END, so it will remain at a fixed size.

Java Applet Using Radio Buttons to Switch Between Classes

Background Information:
This is a Java project for Undergraduate Research at my school. I will be presenting this program on Sunday 4/23/2017. I am stuck on a specific part of my program. This program is not located in any textbook and was made from scratch.
Programmed using Eclipse Neon.2 on Windows 10.
Description:
This program is an animation window using JApplet. Displayed will be a single window which uses the border layout to organize my panels. I have 5 panels (2 sliders on the east and west, 1 radio button on the south, one title on the north, and the center is animation).
The problem area is the center panel, which is where the animation window is located. I have three classes that each create an animation of 16 balls. One class creates balls bouncing vertically, another the balls bounce horizontally, and finally the balls will bounce in random directions.
I am using a radio button panel to completely change the center panel, to display each different class upon clicking. It starts in the vertical class by default. I can get each class to display individually by commenting out one class and trying it with another.
The problem:
My action listener for the radio buttons IS properly communicating with the radio button being clicked. But the class is not changing and the panel is not being updated. With the way I have it set up now, the center panel is empty.
In the end i want to have my center panel able to display any of the three animation classes by clicking a radio button.
Disclaimer:
I have not properly programmed the logic for the horizontal or random class, but the vertical class works. The sliders are not functional.
Here is the code:
package NEWbounceBallPackage;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class NEWbounceBallClass extends JApplet{
private DrawingPanelRandom ballBounce3; //Center panel, if random bounce
private DrawingPanelHorizontal ballBounce2; //Center panel, if horizontal
//bounce
private DrawingPanelVertical ballBounce; //Center panel, if vertical bounce
private JPanel title; //North
private JPanel selectionButtons; //South
private JPanel ballSize; //West
private JPanel numberOfBalls; //East
private JSlider ballSizeSlider; //Component of ballSize panel
private JSlider numberOfBallsSlider; //Componenet of
private JRadioButton vertical; //button for DrawingPanelVertical
private JRadioButton horizontal; //button for DrawingPanelHorizontal
private JRadioButton random; //button for DrawingPanelRandom
public void init()
{
resize(1150,600); //resize main window
setLayout(new BorderLayout());
buildTitlePanel(); //builds north panel
buildBallBouncePanel(); //calls buildSelectionButtonsPanel()(radio
//buttons panel)
//buildSelectionButtonsPanel(); //being called in
//buildBallBouncePanel()
buildBallSizeSlider(); //builds west panel
buildNumberOfBallsSlider(); //builds east panel
add(title, BorderLayout.NORTH); //adds north panel to
//main window
//add(ballBounce, BorderLayout.CENTER); //will be called in
//buildSelectionButtonsPanel() inside of action listener
add(selectionButtons, BorderLayout.SOUTH); //adds south panel to
//main window
add(ballSize, BorderLayout.WEST); //adds west panel to
//main window
add(numberOfBalls, BorderLayout.EAST); //adds east panel to
//main window
}
private void buildTitlePanel() //creates north panel
{
title = new JPanel();
Font titleFont = new Font("Serrif", Font.BOLD, 17);
JLabel titleText = new JLabel("Bounce Ball Window");
titleText.setFont(titleFont);
title.add(titleText);
}
private void buildBallBouncePanel() //creates center panel by calling radio
//buttons
{
buildSelectionButtonsPanel();
}
public void buildSelectionButtonsPanel() //creates south panel (called by
buildBallBouncePanel()
{
selectionButtons = new JPanel();
vertical = new JRadioButton("Vertical Bounce");
horizontal = new JRadioButton("Horizontal Bounce");
random = new JRadioButton("Random Bounce");
ButtonGroup group = new ButtonGroup(); //groups buttons allowing
//only one to be selected
group.add(vertical);
group.add(horizontal);
group.add(random);
vertical.setSelected(true); //vertical button selected by default
selectionButtons.add(vertical);
selectionButtons.add(horizontal);
selectionButtons.add(random);
//ballBounce = new DrawingPanelVertical(); //(TEST) if you want to see
//animation work, uncomment line 76 and 77,
//add(ballBounce, BorderLayout.CENTER); //(TEST) this will only show
//the vertical bounce
vertical.addActionListener(new ActionListener() //action listener for
//vertical class
{
public void actionPerformed(ActionEvent event)
{
ballBounce = new DrawingPanelVertical(); //calls vertical
//class then adds to center panel
add(ballBounce, BorderLayout.CENTER);
System.out.print("Vertical Test");
}
}
);
horizontal.addActionListener(new ActionListener() //action listener for
//horizontal class
{
public void actionPerformed(ActionEvent event)
{
ballBounce2 = new DrawingPanelHorizontal(); //calls horizontal
//class then adds to center panel
add(ballBounce2, BorderLayout.CENTER);
System.out.print("Horizontal Test");
}
}
);
random.addActionListener(new ActionListener() //action listener for
//random class
{
public void actionPerformed(ActionEvent event)
{
ballBounce3 = new DrawingPanelRandom(); //calls random class
//then adds to center panel
add(ballBounce3, BorderLayout.CENTER);
System.out.print("Random Test");
}
}
);
}
private void buildBallSizeSlider() //creates west slider panel
{
ballSize = new JPanel();
ballSize.setLayout(new BorderLayout());
ballSizeSlider = new JSlider(JSlider.VERTICAL, 1, 8, 1);
JLabel title = new JLabel("Change Size of Ball");
ballSizeSlider.setPreferredSize(new Dimension(50,500));
ballSizeSlider.setMajorTickSpacing(1);
ballSizeSlider.setMinorTickSpacing(1);
ballSizeSlider.setPaintTicks(true);
ballSizeSlider.setPaintLabels(true);
//ballSizeSlider.addChangeListener(new SliderListener());
ballSize.add(title, BorderLayout.NORTH);
ballSize.add(ballSizeSlider, BorderLayout.CENTER);
}
//private class SliderListener implements ChangeListener
//{
// public void stateChanged(ChangeEvent e)
// {
// int sliderChoice;
// sliderChoice = ballSizeSlider.getValue();
// if(sliderChoice = )
//}
//}
private void buildNumberOfBallsSlider() //creates east slider panel
{
numberOfBalls = new JPanel();
numberOfBalls.setLayout(new BorderLayout());
numberOfBallsSlider = new JSlider(JSlider.VERTICAL, 0, 16, 8);
JLabel title = new JLabel("Adjust Number of Balls");
numberOfBallsSlider.setPreferredSize(new Dimension(50,500));
numberOfBallsSlider.setMajorTickSpacing(1);
numberOfBallsSlider.setMinorTickSpacing(1);
numberOfBallsSlider.setPaintTicks(true);
numberOfBallsSlider.setPaintLabels(true);
numberOfBalls.add(title, BorderLayout.NORTH);
numberOfBalls.add(numberOfBallsSlider, BorderLayout.CENTER);
}
}
package NEWbounceBallPackage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class DrawingPanelVertical extends JPanel{
private final int X = 135; //starting position of first ball (all other ball
//starting positions are based from first ball)
private final int WIDTH = 40; //width of balls
private final int HEIGHT = 40; //height of balls
private final int TIME_DELAY = 40; //delays animation (increase to slow
//down)
private final int MOVE = 20; //dictates how quickly the ball moves during
//animation
private final int MINIMUM_Y = 50; //bottom limit of bounce
private final int MAXIMUM_Y = 400; //top limit of bounce
private int y = 400; //starting position of first ball (all other ball
//starting positions are based from first ball)
private boolean goingUp = true;
private Timer timer;
public DrawingPanelVertical()
{
setPreferredSize(new Dimension(800,500));
timer = new Timer(TIME_DELAY, new TimerListener());
timer.start();
}
public void paint(Graphics g)
{
super.paint(g);
g.drawRect(80, 0, 750, 500);
g.setColor(getBackground());
g.setColor(Color.black);
g.fillOval(X, y, WIDTH, HEIGHT);
g.setColor(Color.blue);
g.fillOval(X+50, y, WIDTH, HEIGHT);
g.setColor(Color.cyan);
g.fillOval(X+100, y, WIDTH, HEIGHT);
g.setColor(Color.darkGray);
g.fillOval(X+150, y, WIDTH, HEIGHT);
g.setColor(Color.gray);
g.fillOval(X+200, y, WIDTH, HEIGHT);
g.setColor(Color.green);
g.fillOval(X+250, y, WIDTH, HEIGHT);
g.setColor(Color.lightGray);
g.fillOval(X+300, y, WIDTH, HEIGHT);
g.setColor(Color.magenta);
g.fillOval(X+350, y, WIDTH, HEIGHT);
g.setColor(Color.orange);
g.fillOval(X+400, y, WIDTH, HEIGHT);
g.setColor(Color.pink);
g.fillOval(X+450, y, WIDTH, HEIGHT);
g.setColor(Color.red);
g.fillOval(X+500, y, WIDTH, HEIGHT);
g.setColor(Color.white);
g.fillOval(X+550, y, WIDTH, HEIGHT);
g.setColor(Color.yellow);
g.fillOval(X+600, y, WIDTH, HEIGHT);
}
private class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(goingUp)
{
if(y > MINIMUM_Y)
y = y - MOVE;
else
goingUp = false;
}
else
{
if(y < MAXIMUM_Y)
y = y + MOVE;
else
goingUp = true;
}
//resize(1300,600);
repaint();
//resize(1302,600);
}
}
}
But the class is not changing and the panel is not being updated.
Swing components by default have a size of (0, 0) so there is nothing to paint. You need to invoke the layout manager so the component can be given a size and location based on the rules of the layout manager.
So, when you add a component to a visible GUI the basic logic is:
panel.add(...);
panel.revalidate(); // invokes the layout manager
panel.repaint();
In the end i want to have my center panel able to display any of the three animation classes by clicking a radio button.
The better solution is to use a CardLayout and let the layout manager manage the visible panel. Read the section from the Swing tutorial on How to Use CardLayout for more information and working examples.

JPanel not showing up in a JFrame using BorderLayout

I have a JPanel using GridLayout which contains 6 JLabels. If i add only this JPanel to a JFrame everything works fine, but when I add it on BorderLayout.WEST (along with 3 other panels on EAST, CENTER and SOUTH) it just won't show up.
Here's the code I'm using:
public class SwingView extends JFrame {
private DeckLabel[] terrains={
new DeckLabel(new ImageIcon("assets/graphics/mountains.png"),0),
new DeckLabel(new ImageIcon("assets/graphics/planes.png"),1),
new DeckLabel(new ImageIcon("assets/graphics/forest.png"),2),
new DeckLabel(new ImageIcon("assets/graphics/fields.png"),3),
new DeckLabel(new ImageIcon("assets/graphics/swamp.png"),4),
new DeckLabel(new ImageIcon("assets/graphics/desert.png"),5)};
public SwingView() {
super("Frame");
this.setSize(680, 740);
this.setLayout(new BorderLayout());
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
Utilities.center(this);
// panels
//terrains
JPanel terrainsPanel = new JPanel();
terrainsPanel.setSize(100, 640);
terrainsPanel.setLayout(new GridLayout(6, 1));
//map
JPanel mapPanel = new JPanel();
mapPanel.setSize(480, 640);
//info
JPanel infoPanel = new JPanel();
infoPanel.setSize(100, 640);
//chat
JPanel chatPanel = new JPanel();
chatPanel.setSize(680, 100);
chatView.setEditable(false);
txtChat.addKeyListener(this);
chatPanel.add(txtChat, BorderLayout.SOUTH);
chatPanel.add(chatView);
// terrains
for (int i = 0; i < 6; i++) {
terrainsPanel.add(terrains[i]);
}
this.add(mapPanel,BorderLayout.CENTER);
this.add(terrainsPanel, BorderLayout.WEST);
this.add(infoPanel, BorderLayout.EAST);
this.add(chatPanel, BorderLayout.SOUTH);
}
}
public class DeckLabel extends JLabel{
private Image image;
private int index;
public DeckLabel(ImageIcon icon,int index){
this.image=icon.getImage();
this.index=index;
}
#Override
public void paint(Graphics g){
BufferedImage bi = new BufferedImage(85, 78,
BufferedImage.TYPE_INT_RGB);
Graphics2D tg = bi.createGraphics();
tg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// draw basic tile
tg.drawImage(image, 0, 0, null);
g.drawImage(bi,0,0,null);
}
}
Thank you
plenty issues
use JPanel instead of JLabel,
override paintComponent instead of paint for JLabel/JPanel/Swing JComponents
1st. code line should be super.pain(Component), or for JPanel to stop repainting (mouse and key events)
or to use JLabel.setIcon for Image
something wrong came from Utilities.center(this);, did you tried to layout container
FlowLayout is default LayoutManager for JPanel, then chatPanel.add(txtChat, BorderLayout.SOUTH); is ignored without missing code line chatPanel.setLayout(new BorderLayout)
txtChat.addKeyListener(this); I'm hope that isn't some of JTextComponents, if yes then to use DocumentListener/Filter instead
As your DeckLabel class sets no text for the JLabel, the component has no minimum and preferred size. So the border layout will assume a size of 0 -> component not visible. The same happens when you use a JPanel.
Call setPreferredSize(), setMinimumSize() or override getMinimumSize()/getPreferredSize().

JPanel positions and sizes changes according to screensize

The program runs with its size according to screen resolution or size of the computer. When I run it in a computer with specific size of its monitor it will change accordingly. My problem is the positioning and size of a JPanel, or any object inside the frame, to adopt on the change of screen size.
So whenever I will present my program on any monitor with different sizes the components will still be organized and placed as what I've originally designed it. But here I'm testing it with one JPanel named displayMenu. In which it displays a panel colored in green.
package saves.project;
import com.sun.awt.AWTUtilities;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.BorderFactory;
import javax.imageio.ImageIO;
public class Homepage extends JFrame{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Border grayline = BorderFactory.createLineBorder(Color.GRAY);;
int width = screenSize.width, height = screenSize.height;
public Homepage() throws IOException{
super("Homepage");
displayMenu();
displayBackground();
}
public static BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(image, 0, 0, width, height, null);
g2d.dispose();
return bi;
}
public void displayBackground() throws IOException{
JPanel pBackground = new JPanel();
pBackground.setSize(screenSize);
pBackground.setLayout(new FlowLayout());
add(pBackground);
BufferedImage header = ImageIO.read(new File("res\\bg.jpg"));
BufferedImage resizedImage = resize(header,width,height);
ImageIcon image = new ImageIcon(resizedImage);
JLabel lblheader = new JLabel(image, JLabel.CENTER);
pBackground.add(lblheader);
}
public void displayMenu() {
JPanel pTitle = new JPanel();
pTitle.setLayout(null);
pTitle.setBounds(width/3, (height/2)+20, width/2, height/2);
pTitle.setBackground(Color.GREEN);
add(pTitle);
}
public void CreateAndShowGUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setUndecorated(true);
setVisible(true);
}
}
Also, it looks like my background was not totally spread throughout the frame. There is a white line on the top but the rest is the background. What should I gonna do? Thanks for help!
Following up with #MadProgrammer comment:
You really need to learn how to use Layout Mangers. Setting sizes is not the way to go, as they will perform different on different machines.
One important thing to know about Layout Managers are which layouts respect the preferred sizes of its internal components. The ones that do not respect the sizes, will stretch the components. Some layouts may not stretch their components, but will position them in a default location within the open space, when the main container is stretched.
To get desired results, it is also sometimes necessary to nest containers with different layouts, this taking advantage of two or more layouts.
I know this isn't really much of an answer to your question, but I thought you may still gain some insight to your problem, and how you can achieve what you are trying to, with the use of Layout Managers.
Below I just made up a quick example of the different natures of some of the main Layout Managers. You can play around with it. Note the main JFrame is using the default BorderLayout. I only explicitly set the layout as BorderLayout so you can see which layout causes the effect.
Also have a look at Laying out Components Withing a Container to learn more about how to use different Layout Managers. Avoid using the null layouts and trying to position everything yourself. Let the layouts do it for you, as Swing was built to used with Layout Managers.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
public class TestingLayoutManagers {
private JPanel northFlowLayoutPanel;
private JPanel southBorderLayoutPanel;
private JPanel centerGridBagLayoutPanel;
private JPanel westBoxLayoutPanel;
private JPanel eastGridLayoutPanel;
private final JButton northButton = new JButton("North Button");
private final JButton southButton = new JButton("South Button");
private final JButton centerButton = new JButton("Center Button");
private final JButton eastButton = new JButton("East Button");
private final JButton menuButton1 = new JButton("Menu Item 1");
private final JButton menuButton2 = new JButton("Menu Item 2");
private final JButton menuButton3 = new JButton("Menu Item 3");
private final JButton menuButton4 = new JButton("Menu Item 4");
private final JButton menuButton5 = new JButton("Menu Item 5");
public TestingLayoutManagers() {
northFlowLayoutPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
southBorderLayoutPanel = new JPanel(new BorderLayout());
centerGridBagLayoutPanel = new JPanel(new GridBagLayout());
eastGridLayoutPanel = new JPanel(new GridLayout(1, 1));
Box box = Box.createVerticalBox();
westBoxLayoutPanel = new JPanel();
northFlowLayoutPanel.add(northButton);
northFlowLayoutPanel.setBorder(BorderFactory.createTitledBorder("Flow Layout"));
southBorderLayoutPanel.add(southButton);
southBorderLayoutPanel.setBorder(BorderFactory.createTitledBorder("Border Layout"));
centerGridBagLayoutPanel.add(centerButton);
centerGridBagLayoutPanel.setBorder(BorderFactory.createTitledBorder("GridBag Layout"));
eastGridLayoutPanel.add(eastButton);
eastGridLayoutPanel.setBorder(BorderFactory.createTitledBorder("Grid Layout"));
box.add(menuButton1);
box.add(menuButton2);
box.add(menuButton3);
box.add(menuButton4);
box.add(menuButton5);
westBoxLayoutPanel.add(box);
westBoxLayoutPanel.setBorder(BorderFactory.createTitledBorder("Box Layout"));
JFrame frame = new JFrame("Test Layout Managers");
frame.setLayout(new BorderLayout()); // This is the deafault layout
frame.add(northFlowLayoutPanel, BorderLayout.PAGE_START);
frame.add(southBorderLayoutPanel, BorderLayout.PAGE_END);
frame.add(centerGridBagLayoutPanel, BorderLayout.CENTER);
frame.add(eastGridLayoutPanel, BorderLayout.LINE_END);
frame.add(westBoxLayoutPanel, BorderLayout.LINE_START);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException
| InstantiationException
| IllegalAccessException
| UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
new TestingLayoutManagers();
});
}
}

How returns XxxSize from JComponent(s) added to the JLabel

how can I correctly returns XxxSize from JComponent(s) added to the JLabel
1st. figure >> lets LayoutManager works like as for JPanel, JLabel returns Size(0, 0)
2nd. figure >> added some PreferredSize to the JLabel
3rd. figure >> calculated PreferredSize from JComponent(s) added to the JLabel
4th. figure >> lets LayoutManager works changed JLabel to JPanel, now LayoutManager correctly calculated Dimension without using any XxxSize
notice sice there is used Nimbus L&F, same output is there for all accesible L&F
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;
import java.util.Queue;
import javax.swing.*;
public class NimbusBorderPainterDemo extends JFrame {
private static final long serialVersionUID = 1L;
private JFrame frame = new JFrame();
private JPanel fatherPanel = new JPanel(), titlePanel = new JPanel();
private JLabel buttonPanel = new JLabel();
//figure ---> 4th. switch JLabel with JPanel
//private JPanel buttonPanel = new JPanel();
private Queue<Icon> iconQueue = new LinkedList<Icon>();
public NimbusBorderPainterDemo() {
iconQueue.add(UIManager.getIcon("OptionPane.errorIcon"));
iconQueue.add(UIManager.getIcon("OptionPane.informationIcon"));
iconQueue.add(UIManager.getIcon("OptionPane.warningIcon"));
JButton button0 = createButton();
JButton button1 = createButton();
JButton button2 = createButton();
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(1);
}
});
int gap = 5;
buttonPanel.setLayout(new GridLayout(0, 3, gap, 0));
buttonPanel.add(button0);
buttonPanel.add(button1);
buttonPanel.add(button2);
// figure 1st. ---> without PreferredSize
// figure 2nd. --->
//buttonPanel.setPreferredSize(new Dimension(160, 30));
// figure 3rd. --->
/*Dimension dim = button0.getPreferredSize();
int w = dim.width;
int h = dim.height;
w = (w + 5) * 3;
h += 4;
dim = new Dimension(w, h);
buttonPanel.setPreferredSize(dim);*/
titlePanel.setLayout(new BorderLayout());
titlePanel.add(new JLabel(nextIcon()), BorderLayout.WEST);
titlePanel.add(new JLabel("My Frame"), BorderLayout.CENTER);
titlePanel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
titlePanel.add(buttonPanel, BorderLayout.EAST);
fatherPanel.setLayout(new BorderLayout());
fatherPanel.add(titlePanel, BorderLayout.CENTER);
frame.setUndecorated(true);
frame.add(fatherPanel);
frame.setLocation(50, 50);
frame.pack();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setVisible(true);
}
private JButton createButton() {
JButton button = new JButton();
button.setBorderPainted(false);
button.setBorder(null);
button.setFocusable(false);
button.setMargin(new Insets(0, 0, 0, 0));
button.setContentAreaFilled(false);
button.setIcon(nextIcon());
//button.setRolloverIcon(nextIcon());
//button.setPressedIcon(nextIcon());
//button.setDisabledIcon(nextIcon());
nextIcon();
return button;
}
private Icon nextIcon() {
Icon icon = iconQueue.peek();
iconQueue.add(iconQueue.remove());
return icon;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception fail) {
}
UIManager.getLookAndFeelDefaults().put("nimbusFocus", Color.RED);
NimbusBorderPainterDemo nimbusBorderPainterDemo = new NimbusBorderPainterDemo();
}
});
}
}
The default preferred size calculation is to use the layout manager to determine the preferred size of a component. This means the layout manager iterates through all the child components to determine the preferred size of each. For a JPanel, which is meant to be used as a Container this calculation is used.
However, for other Swing components, the getPreferredSize() method is always overridden to provide a reasonable size for the given component.
In the case of a JLabel, the preferred size calculation takes into account the text and the icon used. Since you didn't provide either the preferred size is zero. Of course if you manually override this calculation by using the setPreferredSize() method then the component will have a preferred size.
So even though Swing allows you to add components to any component and use a layout manager to layout the child components, these child components are not used in the preferred size calculation.
This is not just a Nimbus issue.

Categories