I added a simple statusBar
to the application. It works normally, adjusts its size depending on the resolution.
Only that by adding this status bar, suddenly other elements in the application, such as text fields or table, lost this ability to "adjust elements".
If we remove these three lines in the code, I will lose the status bar, but the other elements will adapt as I want.
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(statusBar, BorderLayout.SOUTH);
How can I make both statusBar
and the other elements adjust to size?
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.sql.SQLException;
public class Menu {
static void MenuBar() throws SQLException, IOException {
JFrame frame = new JFrame("frame");
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
frame.setSize(1600, 1000);
frame.setVisible(true); //If I delete any more, all the content will disappear
frame.setContentPane(new Recipe().Main);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
JStatusBar statusBar = new JStatusBar();
JLabel leftLabel = new JLabel("App");
statusBar.setLeftComponent(leftLabel);
final JLabel timeLabel = new JLabel();
timeLabel.setHorizontalAlignment(JLabel.CENTER);
statusBar.addRightComponent(timeLabel);
contentPane.add(statusBar, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
As a proof of concept, I modified your code slightly to show you what I meant:
public class Menu {
void MenuBar() throws SQLException, IOException {
JFrame frame = new JFrame("frame");
JMenuBar menuBar = new JMenuBar();
menuBar.add(new JMenu("Main Menu"));
frame.setJMenuBar(menuBar);
frame.setSize(600, 400);
JPanel center = new JPanel();
center.add(new JLabel("CENTER"));
Container contentPane = frame.getContentPane();
contentPane.add(center, BorderLayout.CENTER);
JPanel south = new JPanel();
south.add(new JLabel("SOUTH"));
south.setBackground(Color.green);
JLabel leftLabel = new JLabel("App");
// statusBar.setLeftComponent(leftLabel);
final JLabel timeLabel = new JLabel();
timeLabel.setHorizontalAlignment(JLabel.CENTER);
// statusBar.addRightComponent(timeLabel);
contentPane.add(south, BorderLayout.SOUTH);
JPanel east = new JPanel();
east.add(new JLabel("EAST"));
east.setBackground(Color.cyan);
contentPane.add(east, BorderLayout.EAST);
JPanel west = new JPanel();
west.add(new JLabel("WEST"));
west.setBackground(Color.yellow);
contentPane.add(west, BorderLayout.WEST);
JPanel north = new JPanel();
north.add(new JLabel("NORTH"));
north.setBackground(Color.orange);
contentPane.add(north, BorderLayout.NORTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Menu menu = new Menu();
try {
menu.MenuBar();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
The code above produces the following result (not calling pack()
to respect the set size of the frame)
As you can see from the code above, I am not adding a new BorderLayout
to the frame's content pane because it already contains one by default when you instantiate the content pane via the JFrame
. I am simply using it and setting the components in the different regions designated by this layout manager.
Different layout managers enforce different behaviors during a resize event. It all depends on the layout manager. For instance, JPanel
uses FlowLayout
by default. Depending on the size when the panel renders, you will see components inside a JPanel
arranged from left to right. When there is no more space (defined by the bounds of the panel), you will see components arranged on a "row" below the first components. This means that, if you reduce the panel's width during a resize, you should see components wrapped and stacked one on top of others inside this panel. In contrast, if you use a GridLayout
and resize the panel, the behavior is totally different. You can even have restrictions to set a minimum and/or maximum sizes to constraint much much or how little a component should resize and a preferred size attribute which is different to the "size" attribute of a container when "no layout manager" is preferred. This is called "Absolute Positioning" and it is done when you want full control of the actual (x, y) coordinates where the components should be placed and the layout manager is set to null. Of course, this is not preferable. It is always better (in my opinion) to delegate this responsibility to the various layout managers that comes with Java Swing, or write one of your own (writing one might be easier said than done). I said all that to say the same thing I posted on the comments section:
Spend some time reading the Oracle Tutorials on Layout Managers to get a glimpse of what Layout Managers come by default with different Swing components.
This will also help you understand what behavior to expect when (for instance) a resize event occurs and the things you need to do in the code to adjust this behavior to suit your needs. For example, if you need to create a checkers or chess application, it is obvious you will need a container with a GridLayout
manager. But it is up to you to tweak it to define min and max size, preferred size, etc.
Also, something very important mentioned by Andrew Thompson... you need to know WHEN to make calls to certain methods. He specifically mentioned when to call pack()
and setVisible()
. Little things like that (are not really little) can make a difference.