Java:切换面板时,JPanel组件向侧面倾斜

时间:2018-05-03 11:51:23

标签: java swing jframe jpanel jcomponent

我想使用BorderLayout制作登录应用程序的最基本示例(即使我可以尝试CardLayout,如果有必要)并修复组件位置以供将来个人参考。

在我的例子中,我创建了三个面板:

  • login_page
  • home_page
  • exit_page

如果登录信息正确,程序将切换到home_page

如果登录信息不正确,程序将切换到exit_page

我测试了所有可能的面板序列。当我试图从第一个面板到下一个面板时,下一个面板的组件似乎被拖到一边,如下所示:

enter image description here enter image description here

我相信当我尝试在actionPerformed方法的末尾再次设置布局时,我会遗漏一些内容,但我在网上找到的几个例子都使用了这种方法。

如何将下一个面板的组件放到正确的位置?

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class LoginForm extends JFrame implements ActionListener
{
    private JFrame frame;                               //main frame

    private JPanel login_page;                          //3 different panels/pages/states
    private JPanel home_page;
    private JPanel exit_page;

    private JLabel login_label;                         //login form components
    private JLabel username_label;
    private JLabel password_label;
    private JTextField username_text;
    private JPasswordField password_text;
    private JButton login_button;

    private JLabel home_label;                          //homepage components
    private JButton logout_button;

    private JLabel locked_label;                        //exit page components
    private JButton exit_button;

    LoginForm()                                         //initialization for the components and panels
    {                                                   
       frame = new JFrame("Login Form frame");
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


       //////////////////////////////////////////////////////
       /////////login form components initialization/////////
       //////////////////////////////////////////////////////
       login_page = new JPanel();

        login_label = new JLabel("Login label");

        username_label = new JLabel("Username");
        password_label = new JLabel("Password");

        username_text = new JTextField();
        password_text = new JPasswordField();

        login_button = new JButton("Login");
        login_button.addActionListener(this);


        login_label.setBounds(100,30,400,30);
        username_label.setBounds(80,70,200,30);
        username_text.setBounds(300,70,200,30);
        password_label.setBounds(80,110,200,30);
        password_text.setBounds(300,110,200,30);
        login_button.setBounds(150,160,100,30);


        login_page.add(login_label);
        login_page.add(username_label);
        login_page.add(username_text);
        login_page.add(password_label);
        login_page.add(password_text);
        login_page.add(login_button);
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////


       //////////////////////////////////////////////////////
       //////////home page components initialization/////////
       //////////////////////////////////////////////////////
       home_page = new JPanel();


        home_label = new JLabel("Home label");

        logout_button = new JButton("Logout");
        logout_button.addActionListener(this);

        home_label.setBounds(100,30,400,30);
        logout_button.setBounds(150,160,100,30);

        home_page.add(home_label);
        home_page.add(logout_button);

       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////

       //////////////////////////////////////////////////////
       //////////exit page components initialization/////////
       ////////////////////////////////////////////////////// 
       exit_page = new JPanel();

        locked_label = new JLabel("You are now locked from the database");

        exit_button = new JButton("Exit");
        exit_button.addActionListener(this);

        locked_label.setBounds(100,30,400,30);
        exit_button.setBounds(150,160,100,30);

        exit_page.add(locked_label);
        exit_page.add(exit_button);
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////
       //////////////////////////////////////////////////////



       frame.setContentPane(login_page);        //first page to get seen
       frame.setSize(550,250);                  //size of the window
       frame.setLayout(new BorderLayout());
       frame.setVisible(true);  
       frame.setResizable(false);
    }

    @Override
    public void actionPerformed(ActionEvent listener)
    {

        JButton button = (JButton) listener.getSource();

        if(button == login_button)
        {
            String name = username_text.getText();
            String password = new String(password_text.getPassword());

                if(name.equals("x") && password.equals("x"))
            {
                frame.remove(login_page);
                frame.setContentPane(home_page);
            }
            else
            {
                frame.remove(login_page);
                frame.setContentPane(exit_page);
            }
        }
        else if(button == logout_button)
        {
            frame.remove(home_page);
            frame.setContentPane(login_page);
        }
        else if (button == exit_button)
        {
            frame.dispose();
        }

        frame.setLayout(new BorderLayout());
        frame.validate();
        frame.repaint();  
    }

    public static void main(String args[])
    {
        LoginForm login = new LoginForm();
    }
}

3 个答案:

答案 0 :(得分:0)

您的问题可能是frame.setSize(550,250);

使用布局时,最好在添加所有组件和面板后使用pack()

答案 1 :(得分:0)

  

但我在网上找到的几个例子都是这样使用的。

我对此表示怀疑,因为代码存在很多问题,只能偶然发挥作用。

让我们从如何使用Swing开始:

  1. 每个面板都应使用布局管理器。布局管理器将设置添加到面板的每个组件的大小和位置。框架内容窗格的默认布局管理器是BorderLayout。 JPanel的默认布局管理器是FlowLayout

  2. 正常的编码顺序是创建面板并设置布局管理器。然后将组件添加到面板中。然后将面板添加到框架中。

  3. 接下来,您在框架上调用pack()和setVisible()。这将调用添加到框架中的所有面板的布局管理器,并且将根据每个布局管理器的规则逻辑显示组件。

  4. 现在,随着框架调整大小,组件将根据布局管理器的规则增长/缩小,并且您已经创建了一个很好的动态GUI。

  5. 现在你在做什么:

    1. 您正在尝试使用setBounds()来设置每个组件的大小和位置。大小只是随机猜测。你不知道适当的大小应该是多少。如果您想将字体更改为更大的尺寸怎么办?现在您将开始截断文本。不要尝试设置Swing组件的边界。每个组件都有逻辑来确定自己的首选大小。

    2. 接下来设置框架的内容窗格(这很好),然后调用setLayout()和validate()。你甚至知道那些陈述是做什么的吗?

    3. 使用setLayout()的目的是告诉面板在向框架添加组件时要使用的布局管理器,但是从不向框架添加任何面板。

    4. 接下来使用validate()(使用Swing时应该是revalidate())。该方法的目的是调用布局管理器。因此,布局管理器将重置所有组件的大小/位置,并完全忽略您使用的setBounds()语句。

    5. 您的代码只能偶然使用,因为您在将面板添加到框架后将布局更改为BorderLayout。由于在使用BorderLayout时从未向框架添加任何组件,因此布局管理器无需执行任何操作。

    6. 所以解决方案是:

      1. 请勿使用setBounds()。

      2. 为3个面板中的每个面板使用适当的布局管理器。

      3. 在框架上使用CardLayout。然后您可以根据需要交换上面的每个面板。不要试图重新发明轮子。

      4. 阅读Layout Mangers上的Swing教程,了解更多信息和工作示例。

答案 2 :(得分:-1)

将所有JPanels的布局设置为null。默认情况下,将设置FlowLayout,这会导致问题。

初始化后,

添加login_page.setLayout(null)

初始化后,

添加home_page.setLayout(null)

初始化后,

添加exit_page.setLayout(null)

这应该可以解决您的问题。虽然这是解决问题的快速方法,但这不是一个合适的解决方案。

在java swings中设置空布局不是首选,因为:

  

布局管理器可以更轻松地根据外观进行调整   组件外观,不同字体大小,容器的外观   改变大小和不同的语言环境。布局管理员也可以   其他容器以及其他程序可以轻松地重复使用

所以总是使用布局管理器。因此,不要使用setBounds()语句手动设置组件的位置,而是使用布局管理器来定位组件。有关如何使用各种布局管理器的更多信息,请参阅here。我希望在这里GridBagLayout,因为它更灵活。