Java CardLayout JPanel перемещается вверх, когда добавлен второй JPanel - PullRequest
2 голосов
/ 17 апреля 2011

Я новичок в Java и в основном CardLayout.Я хочу просто переключать «окна», представленные JPanels.Я где-то читал эту работу для CardLayout.Но моя проблема в том, что когда add chatPanel до mainPanel (это 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);

}
}

Пожалуйста, что я испортил?Благодаря.

Ответы [ 2 ]

2 голосов
/ 17 апреля 2011

Если вы хотите, чтобы JPanel центрировался в другом, поместите вашу ConnectPanel в другую JPanel, которая действует как тупой контейнер, и пусть этот контейнер использует GridBagLayout.Затем, если вы добавите connectPanel в контейнер без каких-либо GridBagConstraints, он будет добавлен в положение по умолчанию для GridBagLayout, которое центрируется.Затем вы можете добавить этот контейнер JPanel в вашу mainPanel, используя ту же константу, которую вы использовали бы для вашего connectPanel.

Я бы хотел, чтобы макеты определяли размер компонентов и избегали использования setSize и даже setPreferredSize, иопределенно вызовет pack () на моем JFrame перед установкой его видимым.Вы определенно не хотите установить размер или предпочитаемый размер вашего JTextField, а скорее установите его столбцы и строки и поместите его в JScrollPane, а затем добавьте этот JScrollPane в представление.

Редактировать:
Вот пример, который показывает размещение чего-то вроде вашей панели подключения в верхней, средней и нижней части небольшого графического интерфейса.Просто нажмите кнопку «Далее», чтобы понять, что я имею в виду:

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);
    }
}
2 голосов
/ 17 апреля 2011

Поскольку вы добавляете две 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 Layout для всего вашего дизайна GUI.Это сэкономит вам много времени, если вы потратите час на его изучение.Это также избавит вас от необходимости устанавливать размеры вручную (и, следовательно, избавит вас от необходимости переписывать половину кода GUI при каждом изменении дизайна).

...