I'm trying to make a login page for an idea I'm working on and am trying to center two buttons. When I get the screen dimensions and divide them by 2 it is not centered. Here's my code:
import javax.swing.*;
import java.awt.*;
public class ChatWindow extends JFrame {
public ChatWindow() {
JFrame frame = new JFrame("EasyChat");
JButton login = new JButton("Login");
JButton signup = new JButton("Don't have an account? Sign Up");
JPanel mainPanel = new JPanel();
Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
frame.setVisible(true);
frame.setLayout(null);
frame.setSize(800,450);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.getContentPane().add(login);
frame.getContentPane().add(signup);
login.setPreferredSize(new Dimension(25,60));
login.setFont(new Font("HelveticaNeue", Font.BOLD, 20));
signup.setBounds(ss.width / 2, ss.height / 2 125, 200, 100);
login.setBounds(ss.width / 2, ss.height / 2, 200, 100);
mainPanel.setLayout(new BorderLayout());
mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
}
}
I also want to know how to make the buttons stayed centered if the user exits fullscreen mode.
Thank you.
CodePudding user response:
Make use of the available layout managers. See
And you get resisability for free
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBorder(new EmptyBorder(16, 16, 16, 16));
setLayout(new GridBagLayout());
add(new JButton("Login"));
add(new JButton("Sign Up"));
}
}
}
Now, if you want the buttons to be the same, you might be able to get it to work using something like GridLayout
,
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
JPanel buttonPane = new JPanel(new GridLayout(1, -1));
buttonPane.add(new JButton("This is a long button"));
buttonPane.add(new JButton("Sign Up"));
add(buttonPane);
}
}
}
Or you could use a custom layout manager, for example...
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.LayoutManager2;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new ButtonLayoutManager());
add(new JButton("This is a long button"));
add(new JButton("Sign Up"));
}
}
public class ButtonLayoutManager implements LayoutManager2 {
private int horizontalPadding = 0;
@Override
public void addLayoutComponent(Component comp, Object constraints) {
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public void invalidateLayout(Container target) {
}
@Override
public Dimension maximumLayoutSize(Container target) {
return preferredLayoutSize(target);
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
@Override
public Dimension preferredLayoutSize(Container parent) {
int height = 0;
int width = 0;
for (Component comp : parent.getComponents()) {
height = Math.max(comp.getPreferredSize().height, height);
width = Math.max(comp.getPreferredSize().width, width);
}
width = (width * parent.getComponentCount()) (horizontalPadding * parent.getComponentCount() - 1);
Insets insets = parent.getInsets();
width = insets.left insets.right;
height = insets.top insets.bottom;
return new Dimension(width, height);
}
@Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
@Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
@Override
public void layoutContainer(Container parent) {
int width = parent.getWidth();
int height = parent.getHeight();
Insets insets = parent.getInsets();
int maxWidth = 0;
int maxHeight = 0;
for (Component comp : parent.getComponents()) {
maxWidth = Math.max(comp.getPreferredSize().width, maxWidth);
maxHeight = Math.max(comp.getPreferredSize().height, maxHeight);
}
int padding = (horizontalPadding * parent.getComponentCount() - 1);
int totalWidth = padding (maxWidth * parent.getComponentCount());
int yOffset = (height - maxHeight) / 2;
int xOffset = (width - totalWidth) / 2;
for (Component comp : parent.getComponents()) {
comp.setBounds(xOffset, yOffset, maxWidth, maxHeight);
xOffset = horizontalPadding maxWidth;
}
}
}
}
nb: I've not done extensive testing on this and is only meant for demonstration purposes
CodePudding user response:
This answer seems to use the (first) approach detailed by MadProgrammer, but since I have it ready.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class CenteredButtons {
public CenteredButtons() {
JFrame f = new JFrame("Centered Buttons");
// A FlowLayout might also be used here
// Doing so would allow each button to be its natural size
JPanel buttonPanel = new JPanel(new GridLayout(1,0,20,20));
buttonPanel.add(new JButton("Yes"));
buttonPanel.add(new JButton("No"));
buttonPanel.setBorder(new EmptyBorder(30,75,30,75));
// a component (e.g. buttonPanel) added with no constraints will be centered
JPanel centerPanel = new JPanel(new GridBagLayout());
centerPanel.add(buttonPanel);
f.setContentPane(centerPanel);
f.pack(); // validates the layout and sets a size for the frame
f.setLocationRelativeTo(null); // centers the window on the screen
f.setExtendedState(JFrame.MAXIMIZED_BOTH); // maximizes the window
f.setVisible(true);
}
public static void main(String[] args) {
Runnable r = () -> new CenteredButtons();
SwingUtilities.invokeLater(r);
}
}
CodePudding user response:
given that you are using a border layout, I would take advantage of addNorth, addSouth, addCenter etc.
once mainPanel is a borderlayout you can say addSouth
(the bottom) either a new layout manager (ie another border layout where you can add east west north sout etc) or simply addSouth (component to add). Should have it centered.
Of all the layouts, border layout is what I tend to use the most.
CodePudding user response:
You need to subtract half the width and half the height of each of the buttons from the screen dimensions to center the two widgets.
Change the code where you set the bounds on the buttons to the following:
signup.setBounds(ss.width / 2 - 200 / 2, ss.height / 2 125 - 100 / 2, 200, 100);
login.setBounds(ss.width / 2 - 200 / 2, ss.height / 2 - 100 / 2, 200, 100);
To be notified when the user exits full screen mode, add a WindowStateListener
to the frame and reset the bounds on the buttons.
Here's the complete code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
public class ChatWindow extends JFrame implements WindowStateListener{
Dimension ss;
JButton login;
JButton signup;
JFrame frame;
public ChatWindow() {
frame = new JFrame("EasyChat");
frame.addWindowStateListener(this);
login = new JButton("Login");
signup = new JButton("Don't have an account? Sign Up");
JPanel mainPanel = new JPanel();
ss = Toolkit.getDefaultToolkit().getScreenSize();
frame.setVisible(true);
frame.setLayout(null);
frame.setSize(800,450);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.getContentPane().add(login);
frame.getContentPane().add(signup);
login.setPreferredSize(new Dimension(25,60));
login.setFont(new Font("HelveticaNeue", Font.BOLD, 20));
signup.setBounds(ss.width / 2 - 200 / 2, ss.height / 2 125 - 100 / 2, 200, 100);
login.setBounds(ss.width / 2 - 200 / 2, ss.height / 2 - 100 / 2, 200, 100);
mainPanel.setLayout(new BorderLayout());
mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
}
public static void main(String[] args) {
new ChatWindow();
}
@Override
public void windowStateChanged(WindowEvent e) {
Dimension ss = frame.getSize();
signup.setBounds(ss.width / 2 - 200 / 2, ss.height / 2 125 - 100 / 2, 200, 100);
login.setBounds(ss.width / 2 - 200 / 2, ss.height / 2 - 100 / 2, 200, 100);
}
}