当按下 JButton 时,JPanel 在 JFrame 中改变 shape/position。为什么?
JPanel changes shape/position within JFrame when JButton is pressed. Why?
基本上,我已将 JPanel 添加到 JFrame,每当我按下 JPanel 中的按钮(这会更改 JPanel 中组件的可见性)时,JPanel 的大小和组件的位置都会发生变化.我一辈子都弄不明白为什么会出现这个问题。非常感谢任何帮助。
Google 搜索次数
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Main {
private JFrame window;
private JPanel loginPanel;
private JButton loginButton;
private JTextField usernameField;
private JPasswordField passwordField;
private JLabel usernameLabel, passwordLabel, errorMessage;
public static void main(String[] args) {
Main program = new Main();
}
public Main() {
createWindow();
runProgram();
}
private void createWindow() {
window = new JFrame("Dentist Program");
window.setSize(1450, 900);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loginPanel = new JPanel();
loginPanel.setSize(300, 400);
loginPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
usernameLabel = new JLabel("Username");
usernameLabel.setSize(125, 20);
usernameLabel.setLocation(loginPanel.getWidth()/2 - usernameLabel.getWidth()/2, 100);
usernameField = new JTextField();
usernameField.setSize(125, 25);
usernameField.setLocation(loginPanel.getWidth()/2 - usernameField.getWidth()/2, usernameLabel.getY() + usernameLabel.getHeight());
passwordLabel = new JLabel("Password");
passwordLabel.setSize(125, 20);
passwordLabel.setLocation(loginPanel.getWidth()/2 - passwordLabel.getWidth()/2, usernameField.getY() + usernameField.getHeight() + 10);
passwordField = new JPasswordField();
passwordField.setSize(125, 25);
passwordField.setLocation(loginPanel.getWidth()/2 - passwordField.getWidth()/2, passwordLabel.getY() + passwordLabel.getHeight());
loginButton = new JButton("Log In");
loginButton.setSize(80, 25);
loginButton.setLocation(passwordField.getX(), passwordField.getY() + passwordField.getHeight() + 15);
loginButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent arg0) {
errorMessage.setText("");
loginPanel.repaint();
}
});
errorMessage = new JLabel("Username and/or password is incorrect");
errorMessage.setSize(250, 25);
errorMessage.setLocation(loginPanel.getWidth()/2 - errorMessage.getWidth()/2, loginButton.getY() + loginButton.getHeight() + 25);
errorMessage.setForeground(Color.RED);
loginPanel.add(usernameLabel);
loginPanel.add(usernameField);
loginPanel.add(passwordLabel);
loginPanel.add(passwordField);
loginPanel.add(loginButton);
loginPanel.add(errorMessage);
window.getContentPane().add(loginPanel);
window.repaint();
}
private void runProgram() {
}
}
你的UI改变的原因是因为你认为正确的外观(初始外观)实际上是错误的,调整后的版本是"correct"版本。
通常,您会在将组件添加到容器后调用 pack()
,这会尝试以其首选大小显示该容器的内容。要在按下按钮前后查看正确的 UI,请在调用 repaint()
后添加:
window.pack();
您可能认为这看起来很糟糕(确实如此),但这正是您的代码所要求的,因此是 "correct" 版本。
请注意,您正在尝试通过显式调用 setSize()
来设置大小,这在 Swing 中是一种不好的做法。至多,您应该设置首选尺寸并让布局管理器处理细节。当您尝试对组件大小和位置进行微观管理时,您通常可以让它在一个平台上看起来不错,但在其他平台上却变得无可挽回。请记住,Java 应该是 "write once, run anywhere" 语言。
当您想要更好地控制布局时,您应该明确指定并使用布局管理器,而不是仅仅接受默认布局。在几乎所有重要的 UI 中,GridBagLayout 是您最好的选择。
最后,当某些内容发生变化时,您无需在 UI 上显式调用 repaint()
。通常,您在处理图形时会调用 paint()
和 repaint()
。让 Swing 自动处理绘画。
基本上,我已将 JPanel 添加到 JFrame,每当我按下 JPanel 中的按钮(这会更改 JPanel 中组件的可见性)时,JPanel 的大小和组件的位置都会发生变化.我一辈子都弄不明白为什么会出现这个问题。非常感谢任何帮助。
Google 搜索次数
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Main {
private JFrame window;
private JPanel loginPanel;
private JButton loginButton;
private JTextField usernameField;
private JPasswordField passwordField;
private JLabel usernameLabel, passwordLabel, errorMessage;
public static void main(String[] args) {
Main program = new Main();
}
public Main() {
createWindow();
runProgram();
}
private void createWindow() {
window = new JFrame("Dentist Program");
window.setSize(1450, 900);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loginPanel = new JPanel();
loginPanel.setSize(300, 400);
loginPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
usernameLabel = new JLabel("Username");
usernameLabel.setSize(125, 20);
usernameLabel.setLocation(loginPanel.getWidth()/2 - usernameLabel.getWidth()/2, 100);
usernameField = new JTextField();
usernameField.setSize(125, 25);
usernameField.setLocation(loginPanel.getWidth()/2 - usernameField.getWidth()/2, usernameLabel.getY() + usernameLabel.getHeight());
passwordLabel = new JLabel("Password");
passwordLabel.setSize(125, 20);
passwordLabel.setLocation(loginPanel.getWidth()/2 - passwordLabel.getWidth()/2, usernameField.getY() + usernameField.getHeight() + 10);
passwordField = new JPasswordField();
passwordField.setSize(125, 25);
passwordField.setLocation(loginPanel.getWidth()/2 - passwordField.getWidth()/2, passwordLabel.getY() + passwordLabel.getHeight());
loginButton = new JButton("Log In");
loginButton.setSize(80, 25);
loginButton.setLocation(passwordField.getX(), passwordField.getY() + passwordField.getHeight() + 15);
loginButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent arg0) {
errorMessage.setText("");
loginPanel.repaint();
}
});
errorMessage = new JLabel("Username and/or password is incorrect");
errorMessage.setSize(250, 25);
errorMessage.setLocation(loginPanel.getWidth()/2 - errorMessage.getWidth()/2, loginButton.getY() + loginButton.getHeight() + 25);
errorMessage.setForeground(Color.RED);
loginPanel.add(usernameLabel);
loginPanel.add(usernameField);
loginPanel.add(passwordLabel);
loginPanel.add(passwordField);
loginPanel.add(loginButton);
loginPanel.add(errorMessage);
window.getContentPane().add(loginPanel);
window.repaint();
}
private void runProgram() {
}
}
你的UI改变的原因是因为你认为正确的外观(初始外观)实际上是错误的,调整后的版本是"correct"版本。
通常,您会在将组件添加到容器后调用 pack()
,这会尝试以其首选大小显示该容器的内容。要在按下按钮前后查看正确的 UI,请在调用 repaint()
后添加:
window.pack();
您可能认为这看起来很糟糕(确实如此),但这正是您的代码所要求的,因此是 "correct" 版本。
请注意,您正在尝试通过显式调用 setSize()
来设置大小,这在 Swing 中是一种不好的做法。至多,您应该设置首选尺寸并让布局管理器处理细节。当您尝试对组件大小和位置进行微观管理时,您通常可以让它在一个平台上看起来不错,但在其他平台上却变得无可挽回。请记住,Java 应该是 "write once, run anywhere" 语言。
当您想要更好地控制布局时,您应该明确指定并使用布局管理器,而不是仅仅接受默认布局。在几乎所有重要的 UI 中,GridBagLayout 是您最好的选择。
最后,当某些内容发生变化时,您无需在 UI 上显式调用 repaint()
。通常,您在处理图形时会调用 paint()
和 repaint()
。让 Swing 自动处理绘画。