Java 将JFrame容器对象居中

Java 将JFrame容器对象居中,java,swing,jframe,containers,centering,Java,Swing,Jframe,Containers,Centering,每次创建新的JFrame对象时,该帧都会显示在0,0位置。我曾尝试使用setLocationRelativeTo()查找如何将窗口居中,但我尝试在容器上调用的所有内容都显示为不可编译代码。下面是我正在使用的一个类: package Ginfo; import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; public class EditUsers extends JFrame im

每次创建新的JFrame对象时,该帧都会显示在0,0位置。我曾尝试使用setLocationRelativeTo()查找如何将窗口居中,但我尝试在容器上调用的所有内容都显示为不可编译代码。下面是我正在使用的一个类:

package Ginfo;

import java.awt.*;
import java.awt.event.*;
import java.io.*;

import javax.swing.*;

public class EditUsers extends JFrame implements ActionListener
{
    Container EU;

    JPanel modUsers, button, output;
    JLabel user, password;
    JTextField tuser, tpassword;
    JTextArea toutput;
    JButton addAdmin, addStand, editPass, removeUser, exit;

    ObjectOutputStream oout;
    ObjectInputStream oin;

    Message m;
    ConnectInfo c;

public EditUsers (ObjectOutputStream oout2, ObjectInputStream oin2, Message m2, ConnectInfo a)
{
    super("User Modifications");
    EU = getContentPane();
    oout = oout2;
    try 
    {
        oout.reset();
    } 
    catch (IOException e)
    {
        e.printStackTrace();
    }
    oin = oin2;
    m = m2;
    c = a;

    buildUserInfoPanel();
    buildOutputPanel();
    buildButtonPanel();
    EU.add(modUsers, BorderLayout.NORTH);
    EU.add(output, BorderLayout.CENTER);
    EU.add(button, BorderLayout.SOUTH);
    pack();
    setVisible(true);

}

private void buildUserInfoPanel()
{
    modUsers = new JPanel();
    modUsers.setLayout(new GridLayout (2,2));
    user = new JLabel ("Enter the username you wish to edit: ");
    tuser = new JTextField (15);
    password = new JLabel("Enter their new password: ");
    tpassword = new JTextField(15);

    modUsers.add(user);
    modUsers.add(tuser);
    modUsers.add(password);
    modUsers.add(tpassword);
}

private void buildOutputPanel()
{
    output = new JPanel();
    toutput = new JTextArea();
    toutput.setPreferredSize(new Dimension (400,100));

    output.add(toutput);
}

private void buildButtonPanel()
{
    button = new JPanel();
    addAdmin = new JButton ("Add user as administrator");
    addStand = new JButton ("Add user as standard");
    editPass = new JButton ("Change password");
    removeUser = new JButton ("Remove user");
    exit = new JButton ("Back");

    button.add(addAdmin);
    button.add(addStand);
    button.add(editPass);
    button.add(removeUser);
    button.add(exit);

    addAdmin.addActionListener(this);
    addStand.addActionListener(this);
    editPass.addActionListener(this);
    removeUser.addActionListener(this);
    exit.addActionListener(this);
}

public void actionPerformed(ActionEvent e) 
{
    if (e.getSource() == addAdmin)
    {
        m.type = Message.ADDADMIN;
        m.main = tuser.getText();
        m.setPassword = tpassword.getText();
        m.setPermission = 1;
    }
    else if (e.getSource() == addStand)
    {
        m.type = Message.ADDSTANDARD;
        m.main = tuser.getText();
        m.setPassword = tpassword.getText();
        m.setPermission = 2;
    }
    else if (e.getSource() == editPass)
    {
        m.type = Message.CHANGEPASSWORD;
        m.main = tuser.getText();
        m.setPassword = tpassword.getText();
    }
    else if (e.getSource() == removeUser)
    {
        m.type = Message.REMOVEUSER;
        m.main = tuser.getText();
    }
    else if (e.getSource() == exit)
    {
        new WhatToDo (oout, oin, m, c);
        dispose();
        return;
    }
    try 
    {
        oout.writeObject(m);
        m = (Message)oin.readObject();
        toutput.setText(m.response);
    } 
    catch (IOException e1) 
    {
        e1.printStackTrace();
    } 
    catch (ClassNotFoundException e1) 
    {
        e1.printStackTrace();
    }
}
}
当我运行此代码时,窗口从(0,0)位置开始。我想做的是,将窗口的大小重新调整为运行它的计算机分辨率的1/4,并重置窗口的位置,使窗口的中心位于屏幕的中心。如果分辨率为1000x1000,则窗口应为250x250,并位于(500-250/2)X,(500-250/2)Y(左上角)乘以(500+250/2)X,(500+250/2)Y(右下角)

(请注意,我正在为每个窗口使用一个不同的类,在进程完成时打开和关闭它,因此如果没有其他类,这将无法完全编译。我正在传递我的ObjectOutputStream、ObjectInputStream、一个我调用Message的对象和另一个我调用ConnectionInfo的对象。输出和输入流将保持连接。)n对于服务器来说是活动的,消息是来回发送的序列化信息,ConnectionInfo主要保存cookie信息(已连接的用户、会话信息、权限级别等)

好的,现在我有了

package Ginfo;

import java.awt.*;
import java.awt.event.*;
import java.io.*;

import javax.swing.*;

public class EditUsers implements ActionListener
{

Container EU;

JFrame myJFrame;

JPanel modUsers, button, output;
JLabel user, password;
JTextField tuser, tpassword;
JTextArea toutput;
JButton addAdmin, addStand, editPass, removeUser, exit;

ObjectOutputStream oout;
ObjectInputStream oin;

Message m;
ConnectInfo c;

public EditUsers (ObjectOutputStream oout2, ObjectInputStream oin2, Message m2, ConnectInfo a)
{
    myJFrame = new JFrame("User Modifications");
    EU = myJFrame.getContentPane();
    oout = oout2;
    try 
    {
        oout.reset();
    } 
    catch (IOException e)
    {
        e.printStackTrace();
    }
    oin = oin2;
    m = m2;
    c = a;

    buildUserInfoPanel();
    buildOutputPanel();
    buildButtonPanel();
    EU.add(modUsers, BorderLayout.NORTH);
    EU.add(output, BorderLayout.CENTER);
    EU.add(button, BorderLayout.SOUTH);
    myJFrame.add(EU);
    myJFrame.pack();
    myJFrame.setVisible(true);

}

private void buildUserInfoPanel()
{
    modUsers = new JPanel();
    modUsers.setLayout(new GridLayout (2,2));
    user = new JLabel ("Enter the username you wish to edit: ");
    tuser = new JTextField (15);
    password = new JLabel("Enter their new password: ");
    tpassword = new JTextField(15);

    modUsers.add(user);
    modUsers.add(tuser);
    modUsers.add(password);
    modUsers.add(tpassword);
}

private void buildOutputPanel()
{
    output = new JPanel();
    toutput = new JTextArea();
    toutput.setPreferredSize(new Dimension (200,100));

    output.add(toutput);
}

private void buildButtonPanel()
{
    button = new JPanel();
    addAdmin = new JButton ("Add user as administrator");
    addStand = new JButton ("Add user as standard");
    editPass = new JButton ("Change password");
    removeUser = new JButton ("Remove user");
    exit = new JButton ("Back");

    button.add(addAdmin);
    button.add(addStand);
    button.add(editPass);
    button.add(removeUser);
    button.add(exit);

    addAdmin.addActionListener(this);
    addStand.addActionListener(this);
    editPass.addActionListener(this);
    removeUser.addActionListener(this);
    exit.addActionListener(this);
}

public void actionPerformed(ActionEvent e) 
{
    if (e.getSource() == addAdmin)
    {
        m.type = Message.ADDADMIN;
        m.main = tuser.getText();
        m.setPassword = tpassword.getText();
        m.setPermission = 1;
    }
    else if (e.getSource() == addStand)
    {
        m.type = Message.ADDSTANDARD;
        m.main = tuser.getText();
        m.setPassword = tpassword.getText();
        m.setPermission = 2;
    }
    else if (e.getSource() == editPass)
    {
        m.type = Message.CHANGEPASSWORD;
        m.main = tuser.getText();
        m.setPassword = tpassword.getText();
    }
    else if (e.getSource() == removeUser)
    {
        m.type = Message.REMOVEUSER;
        m.main = tuser.getText();
    }
    else if (e.getSource() == exit)
    {
        new WhatToDo (oout, oin, m, c);
        myJFrame.dispose();
        return;
    }
    try 
    {
        oout.writeObject(m);
        m = (Message)oin.readObject();
        toutput.setText(m.response);
    } 
    catch (IOException e1) 
    {
        e1.printStackTrace();
    } 
    catch (ClassNotFoundException e1) 
    {
        e1.printStackTrace();
    }
}
}

现在问题出在myJFrame.add(EU)上,它说“java.lang.IllegalArgumentException:将容器的父级添加到自身”。感谢您提前提供的帮助。

您必须作为GUI构造函数中的最后一行代码进行调用

JFrame#pack();
JFrame#setLocationRelativeTo(null); // Windows OS
//or JFrame#setLocationByPlatform(true); //depends of Native OS
JFrame#setVisible(true);
另一项建议

  • 不要扩展JFrame,创建一个局部变量,例如

  • 不要为设置首选大小

  • 可能要为
    按钮=new JPanel();
    设置
    GridLayout
    JPanel
    默认具有
    FlowLayout

编辑

将代码行
EditUsers eu=new EditUsers();
放在主类中,使用
JFrame
返回新的GUI实例,将代码包装到创建GUI的,希望没有其他内容:-)

编辑2

修改代码返回

源代码

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;

public class EditUsers implements ActionListener {

    private JFrame myJFrame;
    private JPanel modUsers, button, output;
    private JLabel user, password;
    private JTextField tuser, tpassword;
    private JTextArea toutput;
    private JButton addAdmin, addStand, editPass, removeUser, exit;
    private ObjectOutputStream oout;
    private ObjectInputStream oin;
    //private Message m;
    //private ConnectInfo c;

    public static void main(String[] a_args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                EditUsers eu = new EditUsers();
            }
        });
    }

    public EditUsers() {
        //editUsers(oout2, oin2, m2, a);
        buildUserInfoPanel();
        buildOutputPanel();
        buildButtonPanel();
        myJFrame = new JFrame("User Modifications");
        myJrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myJFrame.add(modUsers, BorderLayout.NORTH);
        myJFrame.add(output, BorderLayout.CENTER);
        myJFrame.add(button, BorderLayout.SOUTH);
        myJFrame.pack();
        myJFrame.setLocationRelativeTo(null);
        myJFrame.setVisible(true);
    }

    /*private void editUsers(ObjectOutputStream oout2, 
          ObjectInputStream oin2, Message m2, ConnectInfo a) {
        oout = oout2;
        try {
            oout.reset();
        } catch (IOException e) {
            e.printStackTrace();
        }
        oin = oin2;
        m = m2;
        c = a;
    }*/
编辑3


应该在,

Try
myJFrameObject.setLocationRelativeTo(null);

来自JavaDoc

  • 如果组件为null,或者与此组件关联的GraphicsConfiguration为null,则窗口将位于屏幕的中心。可以使用GraphicsEnvironment.getCenterPoint方法获取中心点
  • 如果该组件不为null,但当前未显示,则该窗口将位于由与该组件关联的图形配置定义的目标屏幕的中心
  • 如果组件不为空且显示在屏幕上,则窗口的位置应确保窗口中心与组件中心重合
编辑 我刚刚在这个(不太高级的)构造函数上测试了你的代码,它看起来像你想要的那样工作(至少我希望如此)。我将
setLocationRelativeTo(null)
放在
setVisible(true)
之前,以确保框架将包含所有元素,并知道居中时使用的大小

public EditUsers() {
    super("User Modifications");
    //I removed some not GUI operations

    EU = getContentPane();

    buildUserInfoPanel();
    buildOutputPanel();
    buildButtonPanel();
    EU.add(modUsers, BorderLayout.NORTH);
    EU.add(output, BorderLayout.CENTER);
    EU.add(button, BorderLayout.SOUTH);
    pack();
    //put setLocationRelativeTo before setVisible() 
    setLocationRelativeTo(null);
    setVisible(true);
}

在窗口的维度中或多或少初始化后,应调用
setLocationRelativeTo


关于命令后的直接示例。
pack()
命令可能会重新排列您的帧。

我说我已经尝试过该命令。告诉我使用它,而不是放在哪里对我没有任何帮助。如果我只是将按钮放在窗格底部,制作按钮GridLayout(1,5)会做什么(除了能够在按钮之间留出空间外)?例如,刚刚更新了我的示例以不扩展JFrame,但是我想我对内容窗格如何工作的理解是不正确的。当我尝试将内容窗格添加到新的JFrame对象(myJFrame)时,我收到一个父级添加自身错误。我不需要添加myJFrame.add(EU)?如果是这种情况,那么是JFrame对象还是myJFrame?我不知道在EditUsers实例中生成一个新的EditUsers()对任何事情都有帮助。您的这一行是错误的
myJFrame=new JFrame(“用户修改”);
,您不应该重新初始化它,更好的是,如果您没有以任何方式增强类的行为或功能,就不要继承该类。尽管快速的补救方法是删除这一行,只需为其他组件编写
getContentPane().add(modUsers,BorderLayout.NORTH);等等
then
pack();setLocationRelativeTo(null);setVisible(true);
。当您编写
frame.add(component)
时,实际上是在
JFrame
中心向其内容窗格添加一个组件
给您一个错误,因为EU是所讨论的
JFrame
ContentPane
,您在编写
EU=myJFrame.getContentPane()时得到了它
在这里尝试一下,这扩展了
JFrame
,可能会给你一个想法,如何去做。这里还有一个解决方法谢谢你非常欢迎,保持微笑:-)
public EditUsers() {
    super("User Modifications");
    //I removed some not GUI operations

    EU = getContentPane();

    buildUserInfoPanel();
    buildOutputPanel();
    buildButtonPanel();
    EU.add(modUsers, BorderLayout.NORTH);
    EU.add(output, BorderLayout.CENTER);
    EU.add(button, BorderLayout.SOUTH);
    pack();
    //put setLocationRelativeTo before setVisible() 
    setLocationRelativeTo(null);
    setVisible(true);
}