【问题标题】:Java: JPanel components tilt to the side when switching panelsJava:切换面板时 JPanel 组件向一侧倾斜
【发布时间】:2018-05-03 11:51:23
【问题描述】:

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

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

  • login_page
  • home_page
  • exit_page

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

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

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

当我尝试在 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();
    }
}

【问题讨论】:

    标签: java swing jframe jpanel jcomponent


    【解决方案1】:

    但是我在网上找到的几个例子都使用了这种方式。

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

    让我们从 Swing 的设计用途开始:

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

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

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

    4. 现在,随着框架的大小调整,组件将根据布局管理器的规则扩大/缩小,您已经为自己创建了一个不错的动态 GUI。

    现在你在做什么:

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

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

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

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

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

    所以解决办法是:

    1. 不要使用 setBounds()。

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

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

    4. 阅读 Layout Mangers 上的 Swing 教程以获取更多信息和工作示例。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 一开始我也是这样。但是我使用了 pack(),它只是将组件压缩到一行,下一个面板的问题仍然存在。
      • 好吧,我主要使用gridbag布局,你可以给它最小宽度和高度,并使用胶水填充空间。
      【解决方案3】:

      将所有JPanels 的布局设置为空。默认情况下,FlowLayout 将被设置,这是导致问题的原因。

      在初始化之后添加login_page.setLayout(null)

      在初始化后添加home_page.setLayout(null)

      在初始化之后添加exit_page.setLayout(null)

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

      在 java swings 中设置空布局是不可取的,因为:

      布局管理器可以更轻松地适应外观和感觉 组件外观,不同的字体大小,容器的 改变大小,以及不同的语言环境。布局管理器也可以 容易被其他容器以及其他程序重用

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

      【讨论】:

      • (1-) 不要使用空布局。 Swing 被设计为与布局管理器一起使用(这里列出的原因太多)。为所需的布局使用适当的布局管理器(或嵌套布局管理器的组合)。 By default, FlowLayout will be set, which is causing the problem. - 这不会导致问题。 FlowLayout 在同一行显示所有组件。它们不会像多行那样被压扁。
      • @camickr 因为他使用setBounds() 单独定位组件,所以FlowLayout 在这里不起作用。 FlowLayoutsetBounds() 不能一起使用,并且由于 FlowLayout 而发生挤压。更多信息在这里:stackoverflow.com/questions/25258318/… 所以,虽然空布局不是可取的,但这是一个快速的解决方案问题。
      • 正如我在回答中所建议的那样,代码存在很多问题,您不能真正说存在一个问题。您看到的结果不是因为面板上的 FlowLayout。例如,如果您只是从 ActionListener 中注释掉 frame.setLayout(new BorderLayout());,那么您将看到该组件显示在 FlowLayout 中。布局管理器覆盖 setBounds()。但是,发生了一些奇怪的事情,因为在设置布局管理器之前将组件添加到框架中。同样,唯一正确的答案是使用布局管理器,不要试图找到破解解决方案。
      猜你喜欢
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      • 2020-09-25
      • 1970-01-01
      • 2023-03-23
      相关资源
      最近更新 更多