我想使用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();
}
}
答案 0 :(得分:0)
您的问题可能是frame.setSize(550,250);
使用布局时,最好在添加所有组件和面板后使用pack()
答案 1 :(得分:0)
但我在网上找到的几个例子都是这样使用的。
我对此表示怀疑,因为代码存在很多问题,只能偶然发挥作用。
让我们从如何使用Swing开始:
每个面板都应使用布局管理器。布局管理器将设置添加到面板的每个组件的大小和位置。框架内容窗格的默认布局管理器是BorderLayout
。 JPanel的默认布局管理器是FlowLayout
。
正常的编码顺序是创建面板并设置布局管理器。然后将组件添加到面板中。然后将面板添加到框架中。
接下来,您在框架上调用pack()和setVisible()。这将调用添加到框架中的所有面板的布局管理器,并且将根据每个布局管理器的规则逻辑显示组件。
现在,随着框架调整大小,组件将根据布局管理器的规则增长/缩小,并且您已经创建了一个很好的动态GUI。
现在你在做什么:
您正在尝试使用setBounds()来设置每个组件的大小和位置。大小只是随机猜测。你不知道适当的大小应该是多少。如果您想将字体更改为更大的尺寸怎么办?现在您将开始截断文本。不要尝试设置Swing组件的边界。每个组件都有逻辑来确定自己的首选大小。
接下来设置框架的内容窗格(这很好),然后调用setLayout()和validate()。你甚至知道那些陈述是做什么的吗?
使用setLayout()的目的是告诉面板在向框架添加组件时要使用的布局管理器,但是从不向框架添加任何面板。
接下来使用validate()(使用Swing时应该是revalidate())。该方法的目的是调用布局管理器。因此,布局管理器将重置所有组件的大小/位置,并完全忽略您使用的setBounds()语句。
您的代码只能偶然使用,因为您在将面板添加到框架后将布局更改为BorderLayout。由于在使用BorderLayout时从未向框架添加任何组件,因此布局管理器无需执行任何操作。
请勿使用setBounds()。
为3个面板中的每个面板使用适当的布局管理器。
在框架上使用CardLayout
。然后您可以根据需要交换上面的每个面板。不要试图重新发明轮子。
阅读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
,因为它更灵活。