Java Swing CardLayout:多张卡似乎同时显示

时间:2015-02-11 12:45:50

标签: java swing cardlayout

我目前正在使用Eclipse(Luna,Win 8.1)开发一个简短的Java Swing项目。目的是显示包含菜单的框架。菜单有不同的页面(主页,选项等),由JPanels通过按钮,标签等实现。这些JPanel由CardLayout组织,调用CardLayout.show(..) - 方法之间切换不同的菜单页面。当我两天前停止编程时,一切都运转良好。然而,当我想在昨天早上继续时,我的代码似乎完全忽略了CardLayout:当将鼠标光标移动到其位置时,位于其他卡中的按钮会弹出第一张卡的背景。我试图解决这个问题(研究,使用备份等)连续17个小时。问题仍然存在,我现在非常绝望= /。以下SSCCE显示相同的行为(将鼠标移动到左下角以查看“选项”卡的“后退”按钮弹出)。

package sscce;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainFrame extends JFrame {
    private CardLayout mainWindowLayout;
    // mainPanel will be used as the MainFrame's main unit to manage Components
    private JPanel mainPanel;

    // Constructor
    public MainFrame() {
        setTitle("sscce");
        setPreferredSize(new Dimension(800, 600));
        setResizable(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setLayout(new BorderLayout());

        mainPanel = new JPanel();
        mainPanel.setPreferredSize(getSize());
        mainWindowLayout = new CardLayout();
        mainPanel.setLayout(mainWindowLayout);

        buildMainMenu();
        buildOptions();

        getContentPane().add(mainPanel);
        mainPanel.setVisible(true);
        // starting application it will "show" (container,
        // contentIdentifier(String))
        mainWindowLayout.show(mainPanel, "2");
        pack();
        setVisible(true);
    }// Constructor

    private void buildMainMenu() {
        JPanel panelMainMenu = new JPanel(new GridBagLayout());
        panelMainMenu.setBackground(Color.orange);

        // 1 Button (centered) to go to Options-Card
        JButton bnOptions = new JButton("Options");
        // Button Functionality
        bnOptions.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                mainWindowLayout.show(mainPanel, "2");
            }
        });
        panelMainMenu.add(bnOptions);
        panelMainMenu.setOpaque(true);
        // container content identifier(String)
        mainPanel.add(panelMainMenu, "1");
        panelMainMenu.setVisible(true);
    }// buildMainMenu

    private void buildOptions() {
        JPanel panelOptions = new JPanel();
        panelOptions.setLayout(new GridBagLayout());
        // standardized margins for all Elements:
        final Insets gbcInsets = new Insets(5, 5, 5, 5);
        panelOptions.setBackground(Color.white);

        JPanel fillerRight = new JPanel();
        JPanel fillerTop = new JPanel();
        JButton bnOptBack = new JButton("Back");

        bnOptBack.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                mainWindowLayout.show(mainPanel, "1");
            }
        });

        // add filler panels to keep button in position
        fillerRight.setBackground(Color.red);
        fillerRight.setOpaque(true);
        panelOptions.add(fillerRight, new GridBagConstraints(1, 1, 1, 2, 1, 0,
                GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
                0, 0));
        fillerRight.setVisible(true);

        fillerTop.setBackground(Color.pink);
        fillerTop.setOpaque(true);
        panelOptions.add(fillerTop, new GridBagConstraints(0, 0, 2, 1, 0, 1,
                GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
                0, 0));
        fillerTop.setVisible(true);

        // 1 Button in lower left hand corner, sends you back to MainMenu-card 
        panelOptions.add(bnOptBack, new GridBagConstraints(0, 1, 1, 1, 0, 0,
                GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
                0, 0));
        bnOptBack.setVisible(true);

        panelOptions.setOpaque(true);
        // container content identifier(String)
        mainPanel.add(panelOptions, "2");
        panelOptions.setVisible(true);
    }// buildOptions

    public static void main(String[] args) {
        MainFrame m = new MainFrame();
    }// main
}// MainFrame

非常感谢任何帮助。 提前致谢 :) 编辑:我想您不需要过于仔细地查看“buildMainMenu”和“buildOptions”方法,单个菜单页面的设置似乎工作正常。

1 个答案:

答案 0 :(得分:5)

当我注释掉以下两行时,它在我的机器上按预期工作

panelOptions.setVisible(true);

panelMainMenu.setVisible(true);

使用CardLayout时,您只需添加组件并使用CardLayout#show来决定展示哪一个。首先调用setVisible似乎会导致问题(无论出于何种原因)。

确保在EDT上触发Swing代码也是一个好主意:

public static void main(String[] args) {

    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        MainFrame m = new MainFrame();
      }
    });