【问题标题】:Java Swing: Trying to get a button to centerJava Swing:试图让按钮居中
【发布时间】:2022-01-18 05:59:37
【问题描述】:

我正在尝试为我正在研究的一个想法创建一个登录页面,并尝试将两个按钮居中。当我获得屏幕尺寸并将它们除以 2 时,它没有居中。这是我的代码:

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));
    }
    
    
}

我还想知道如果用户退出全屏模式,如何使按钮保持居中。

谢谢。

【问题讨论】:

标签: java swing jbutton layout-manager null-layout-manager


【解决方案1】:

利用可用的布局管理器。详情请见Laying Out Components Within a Container

为简单起见,我只使用了GridBagLayout,因为默认情况下这会使容器内的组件居中

而且你可以免费获得可抗性

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"));
        }

    }
}

现在,如果您希望按钮相同,则可以使用 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);
        }

    }

}

或者您可以使用自定义布局管理器,例如...

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:我没有对此进行广泛的测试,仅用于演示目的

【讨论】:

  • 好吧,你的帖子之前发布过,但我的班级有一个更好的名字。 ? 为什么要扩展面板?
  • @AndrewThompson 因为这样你就可以将所有相关的逻辑直接放到面板中......而且我有 IDE 模板可以这样构建源代码?
【解决方案2】:

这个答案似乎使用了MadProgrammer详述的(第一种)方法,但既然我已经准备好了。

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);
    }
}

【讨论】:

    【解决方案3】:

    您需要从屏幕尺寸中减去每个按钮的一半宽度和一半高度,以使两个小部件居中。

    将设置按钮边界的代码更改为以下内容:

            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);
    

    要在用户退出全屏模式时收到通知,请将WindowStateListener 添加到框架并重置按钮的边界。 完整代码如下:

    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);
    
        }
    }
    

    【讨论】:

    • (1-) 不要使用空布局。 Swing 旨在与布局管理器一起使用。布局管理器的工作是确定每个组件的大小/位置。
    猜你喜欢
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    • 2016-02-20
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多