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

我是Java新手,主要是CardLayout。 我想简单地切换由JPanels代表的“windows”。 我在CardLayout上找到了那份工作。 但我的问题是,当add chatPanelmainPanel (这是CardLayout)时,它会将connectPanel几个像素的内容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); } } 

拜托,我搞砸了什么? 谢谢。

由于您要向主JPanel添加两个JPanel,因此这两个面板都需要适合主面板。

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

例如评论这一行:

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

会导致你的文本字段保持不变。 这是因为聊天框不会导致容器resize。

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

如果要将connectPanel的大小设置为与主框架相同的大小,则在添加chatPanel时不会自动调整connectPanel的大小(因为mainPanel的大小已调整)

所以你可以做的是添加中间线:

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

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

虽然这可行,但我绝对建议您使用MIG Layout进行所有GUI设计。 如果花一个小时来学习,它将为您节省大量时间。 它还可以使您不必手动设置大小(从而使您无需在每次设计更改时重写一半GUI代码)。

如果您希望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); } }