当添加第二个 JPanel 时,Java CardLayout JPanel 向上移动

发布于 2024-11-02 02:37:34 字数 2721 浏览 7 评论 0原文

我是 Java 新手,主要是 CardLayout。我想简单地切换 JPanel 代表的“窗口”。我在某处读到了 CardLayout 的工作。但我的问题是,当 add chatPanelmainPanel (这是 CardLayout 的)时,它会将 connectPanel 的内容移动到顶部几个像素,远离其中心位置。我是否跳过代码 createChatPanel(), 它应该在的位置。

我有这段代码:

package App;

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import Validators.*;



public class GUI {

private JFrame mainFrame = null;
private JPanel mainPanel = null;
private CardLayout cl = new CardLayout();

public GUI(){


    try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
         } 
         catch (UnsupportedLookAndFeelException e) {
         }
         catch (ClassNotFoundException e) {
         }
         catch (InstantiationException e) {
         }
         catch (IllegalAccessException e) {
         }

    mainFrame = new JFrame("MainChat");
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setSize(640,480);
    mainFrame.setLocationRelativeTo(null);
    mainFrame.setResizable(false);
    mainFrame.setLayout(new GridBagLayout());

    JMenuBar menuBar = new JMenuBar();

    JMenu menuFile = new JMenu("Soubor");
    JMenu menuHelp = new JMenu("Nápověda");

    menuBar.add(menuFile);
    menuBar.add(menuHelp);

    menuFile.add(new JMenuItem("Nové Připojení"));
    menuFile.add(new JSeparator());
    menuFile.add(new JMenuItem("Konec"));
    menuHelp.add(new JMenuItem("O programu"));
    mainFrame.setJMenuBar(menuBar);


    createMainPanel();
    createConnectPanel();
    createChatPanel();

    mainFrame.setVisible(true);
}

public void createMainPanel() {

    mainPanel = new JPanel(cl);
    mainFrame.add(mainPanel);

}

public void createConnectPanel() {

    JPanel connectPanel = new JPanel();
    mainPanel.add(connectPanel,"connectPanel");

    JTextField ip = new JTextField();
    ip.setDocument(new JTextFieldLimit(15));
    ip.setColumns(11);

    JLabel iplabel = new JLabel("IP:");
    connectPanel.add(iplabel);
    connectPanel.add(ip);

    JButton connect = new JButton("Connect");
    connect.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {

            cl.show(mainPanel,"chatPanel");

        }
    });
    connectPanel.add(connect);

}

public void createChatPanel(){

    JPanel chatPanel = new JPanel();
    mainPanel.add(chatPanel,"chatPanel");

    JTextArea chatbox = new JTextArea();
    chatbox.setPreferredSize(new Dimension(200,200));
    chatPanel.add(chatbox);

}
}

请问我搞砸了什么?谢谢。

I am new to Java and mostly CardLayout. I want to simply switch "windows" represented by JPanels. I read somewhere that job for CardLayout. But my problem is, when add chatPanel to mainPanel (this is the CardLayout one), it shifts the content of connectPanel several pixels to the top, away from its centered position. Is I skip in my code createChatPanel(), its where it should be.

I have this code:

package App;

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import Validators.*;



public class GUI {

private JFrame mainFrame = null;
private JPanel mainPanel = null;
private CardLayout cl = new CardLayout();

public GUI(){


    try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
         } 
         catch (UnsupportedLookAndFeelException e) {
         }
         catch (ClassNotFoundException e) {
         }
         catch (InstantiationException e) {
         }
         catch (IllegalAccessException e) {
         }

    mainFrame = new JFrame("MainChat");
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setSize(640,480);
    mainFrame.setLocationRelativeTo(null);
    mainFrame.setResizable(false);
    mainFrame.setLayout(new GridBagLayout());

    JMenuBar menuBar = new JMenuBar();

    JMenu menuFile = new JMenu("Soubor");
    JMenu menuHelp = new JMenu("Nápověda");

    menuBar.add(menuFile);
    menuBar.add(menuHelp);

    menuFile.add(new JMenuItem("Nové Připojení"));
    menuFile.add(new JSeparator());
    menuFile.add(new JMenuItem("Konec"));
    menuHelp.add(new JMenuItem("O programu"));
    mainFrame.setJMenuBar(menuBar);


    createMainPanel();
    createConnectPanel();
    createChatPanel();

    mainFrame.setVisible(true);
}

public void createMainPanel() {

    mainPanel = new JPanel(cl);
    mainFrame.add(mainPanel);

}

public void createConnectPanel() {

    JPanel connectPanel = new JPanel();
    mainPanel.add(connectPanel,"connectPanel");

    JTextField ip = new JTextField();
    ip.setDocument(new JTextFieldLimit(15));
    ip.setColumns(11);

    JLabel iplabel = new JLabel("IP:");
    connectPanel.add(iplabel);
    connectPanel.add(ip);

    JButton connect = new JButton("Connect");
    connect.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {

            cl.show(mainPanel,"chatPanel");

        }
    });
    connectPanel.add(connect);

}

public void createChatPanel(){

    JPanel chatPanel = new JPanel();
    mainPanel.add(chatPanel,"chatPanel");

    JTextArea chatbox = new JTextArea();
    chatbox.setPreferredSize(new Dimension(200,200));
    chatPanel.add(chatbox);

}
}

Please, what I messed up? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

玩心态 2024-11-09 02:37:34

由于您要向主 JPanel 添加两个 JPanel,
这两个面板都需要安装在主面板内。

如果其中一块内板比另一块大得多,
主面板将进行调整以适应较大的面板。

例如,评论这一行:

chatbox.setPreferredSize(new Dimension(200,200));

将导致您的文本字段保持不变。这是因为
聊天框不会导致容器调整大小。

另请注意,主面板最初的尺寸与您的尺寸不同
主框架,因为您尚未设置主面板的大小。

如果您将 connectPanel 的大小设置为相同的大小
作为您的主框架, connectPanel 不会
添加 chatPanel 时自动调整大小(作为
mainPanel 大小被调整的结果)

所以你可以做的就是在: 中添加中间行

JPanel connectPanel = new JPanel();
connectPanel.setSize(640, 480);
mainPanel.add(connectPanel, "connectPanel");

,这可能会解决你的问题。

虽然这可行,但我绝对推荐使用
MIG 布局
您所有的 GUI 设计。它将为您节省大量时间,如果
你需要一个小时来学习它。它还将使您免于
必须手动设置尺寸(从而使您免于
每次设计更改都必须重写一半的 GUI 代码)。

Since you are adding two JPanels to your main JPanel,
these two panels both need to fit within the main panel.

If one of the inner panels is much larger than the other one,
the main panel will adjust to fit the larger one.

E.g. commenting this line:

chatbox.setPreferredSize(new Dimension(200,200));

would cause your text field to stay put. This is because the
chatbox would not cause the container to resize.

Also note that the main panel is not initially the same size as your
main frame, since you have not set the size of the main panel.

If you would set the size of the connectPanel to the same size
as your main frame, the connectPanel would not
be automatically resized when adding the chatPanel (as a
consequence of the mainPanel being resized)

So what you could do is add the middle line in:

JPanel connectPanel = new JPanel();
connectPanel.setSize(640, 480);
mainPanel.add(connectPanel, "connectPanel");

, which probably would solve your problem.

Although this would work, I definitely recommend using
MIG Layout for
all your GUI designing. It will save you plenty of time if
you take an hour to learn it. It will also save you from
having to set sizes manually (and thereby saving you from
having to rewrite half your GUI code with every design change).

醉城メ夜风 2024-11-09 02:37:34

如果您希望 JPanel 位于另一个 JPanel 的中心,请将 connectPanel 放置在另一个充当哑容器的 JPanel 中,并让该容器使用 GridBagLayout。然后,如果您将 connectPanel 添加到没有任何 GridBagConstraints 的容器中,它将添加到 GridBagLayout 的默认居中位置。然后,您可以使用与 connectPanel 相同的常量将此容器 JPanel 添加到 mainPanel 中。

我倾向于让布局确定组件的大小,并避免使用 setSize 甚至 setPreferredSize,并且肯定会在将其设置为可见之前在 JFrame 上调用 pack() 。您绝对不想设置 JTextField 的大小或 PreferredSize,而是设置其列和行并将其放置在 JScrollPane 中,然后将该 JScrollPane 添加到视图中。

编辑:
下面是一个示例,显示了将连接面板之类的内容放置在小 GUI 的顶部、中间和底部。只需按“下一步”按钮即可明白我的意思:

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

@SuppressWarnings("serial")
public class GUI2 extends JPanel {
    public static final String CONNECT_NORTH = "connect north";
    public static final String CONNECT_CENTER = "connect center";
    private static final String CONNECT_SOUTH = "connect south";
    private static final String CHAT_PANEL = "chat panel";
    private CardLayout cardlayout = new CardLayout();

    public GUI2() {
        setLayout(cardlayout);
        add(createConnectPanel(BorderLayout.NORTH), CONNECT_NORTH);
        add(createConnectPanel(BorderLayout.CENTER), CONNECT_CENTER);
        add(createConnectPanel(BorderLayout.SOUTH), CONNECT_SOUTH);
        add(createChatPanel(), CHAT_PANEL);
    }

    public void nextPanel() {
        cardlayout.next(this);
    }


    private JPanel createConnectPanel(String borderlayoutLocation) {
        JPanel innerPanel = new JPanel();
        innerPanel.add(new JLabel("IP:"));
        innerPanel.add(Box.createHorizontalStrut(5));
        innerPanel.add(new JTextField(11));
        innerPanel.add(Box.createHorizontalStrut(5));
        innerPanel.add(new JButton(new AbstractAction("Next") {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                GUI2.this.nextPanel();
            }
        }));

        JPanel innerPanel2 = new JPanel(new GridBagLayout());
        innerPanel2.add(innerPanel);
        JPanel connectPanel = new JPanel(new BorderLayout());
        connectPanel.add(innerPanel2, borderlayoutLocation);
        return connectPanel;
    }

    private JPanel createChatPanel() {
        JPanel chatPanel = new JPanel(new BorderLayout(5, 5));
        chatPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        chatPanel.add(new JScrollPane(new JTextArea(15, 30)), BorderLayout.CENTER);
        chatPanel.add(new JTextField(), BorderLayout.SOUTH);

        return chatPanel;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createGui();
            }
        });
    }

    private static void createGui() {
        JFrame frame = new JFrame("App");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new GUI2());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

If you want a JPanel centered in another, place your connectPanel in another JPanel that acts as a dumb container, and have this container use GridBagLayout. Then if you add the connectPanel to the container without any GridBagConstraints, it will be added to the default position for GridBagLayout which is centered. You can then add this container JPanel to your mainPanel using the same constant that you would have used for your connectPanel.

I would tend to let the layouts determine the size of components and avoid using setSize and even setPreferredSize, and would definitely call pack() on my JFrame prior to setting it visible. You definitely don't want to set the size or preferredSize of your JTextField, but rather set its columns and rows and place it in a JScrollPane, and then add that JScrollPane to the view.

Edit:
Here's an example that shows placement of something like your connect panel at the top, middle and bottom of a small gui. Just press the "Next" button to see what I mean:

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

@SuppressWarnings("serial")
public class GUI2 extends JPanel {
    public static final String CONNECT_NORTH = "connect north";
    public static final String CONNECT_CENTER = "connect center";
    private static final String CONNECT_SOUTH = "connect south";
    private static final String CHAT_PANEL = "chat panel";
    private CardLayout cardlayout = new CardLayout();

    public GUI2() {
        setLayout(cardlayout);
        add(createConnectPanel(BorderLayout.NORTH), CONNECT_NORTH);
        add(createConnectPanel(BorderLayout.CENTER), CONNECT_CENTER);
        add(createConnectPanel(BorderLayout.SOUTH), CONNECT_SOUTH);
        add(createChatPanel(), CHAT_PANEL);
    }

    public void nextPanel() {
        cardlayout.next(this);
    }


    private JPanel createConnectPanel(String borderlayoutLocation) {
        JPanel innerPanel = new JPanel();
        innerPanel.add(new JLabel("IP:"));
        innerPanel.add(Box.createHorizontalStrut(5));
        innerPanel.add(new JTextField(11));
        innerPanel.add(Box.createHorizontalStrut(5));
        innerPanel.add(new JButton(new AbstractAction("Next") {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                GUI2.this.nextPanel();
            }
        }));

        JPanel innerPanel2 = new JPanel(new GridBagLayout());
        innerPanel2.add(innerPanel);
        JPanel connectPanel = new JPanel(new BorderLayout());
        connectPanel.add(innerPanel2, borderlayoutLocation);
        return connectPanel;
    }

    private JPanel createChatPanel() {
        JPanel chatPanel = new JPanel(new BorderLayout(5, 5));
        chatPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        chatPanel.add(new JScrollPane(new JTextArea(15, 30)), BorderLayout.CENTER);
        chatPanel.add(new JTextField(), BorderLayout.SOUTH);

        return chatPanel;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createGui();
            }
        });
    }

    private static void createGui() {
        JFrame frame = new JFrame("App");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new GUI2());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文