在Java中,如何结合CardLayout和GridBagLayout,仍然能够切换面板?

在Java中,如何结合CardLayout和GridBagLayout,仍然能够切换面板?,java,swing,user-interface,Java,Swing,User Interface,Java新手,Java GUI类新手。我正在制作一个GUI来展示一些游戏,但在切换面板时遇到了困难。我读过关于CardLayout的文章,但是我在实现它时遇到了一个问题,因为我无法让持有不同游戏GUI的JPanel将它们的事件发送回使用CardLayout的类。(这可能是我出错的地方——我不知道该如何正确地构造它。) 这是我的主菜单(称为mainContainer): 这是GUI驱动程序的总体结构: public class CasinoDriverGUI { //CardLayout is

Java新手,Java GUI类新手。我正在制作一个GUI来展示一些游戏,但在切换面板时遇到了困难。我读过关于CardLayout的文章,但是我在实现它时遇到了一个问题,因为我无法让持有不同游戏GUI的JPanel将它们的事件发送回使用CardLayout的类。(这可能是我出错的地方——我不知道该如何正确地构造它。)

这是我的主菜单(称为mainContainer):

这是GUI驱动程序的总体结构:

public class CasinoDriverGUI {

//CardLayout is here in the main method Container contentPane.add(cardLayout)
public static void main(String[] args) throws IOException 

//MainContainer is MenuScreen: GridBagLayout for nice button placement
static class MainContainer extends JPanel implements ActionListener{...}
static class CrapsContainer extends JPanel implements ActionListener{...}
static class PokerContainer extends JPanel implements ActionListener{...}

//Button with custom look
class CButton extends JButton

}//end CasinoDriverGUI
这里是主要的方法:它从网站抓取一个图像,然后将菜单屏幕(mainContainer)添加到contentPane。菜单屏幕使用GridBagLayout,但它是添加按钮组件的地方。因此,我不知道如何让contentPane的CardLayout听菜单屏幕的按钮。我尝试使用ContainerListener,但那似乎是一条死胡同

   public class CasinoDriverGUI {

public static void main(String[] args) throws IOException {

    // load the texture resource image
    System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
    MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
    System.out.println("Loading finished. Starting the Casino!");

    MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);

    // Starting the Swing GUI in the EDT
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {


            final CardLayout cardLayout = new CardLayout();
            JFrame frame = new JFrame("Midnight Casino");
            // frame about the size of background src image
            frame.setPreferredSize(new Dimension(580, 329)); 
            final Container contentPane = frame.getContentPane();
            contentPane.setLayout(cardLayout);

            MainContainer mainContainer = new MainContainer();
            mainContainer.setPreferredSize( frame.getPreferredSize() );
            contentPane.add(mainContainer, "mainContainer");

            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setResizable(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);


        }
    });
}
到目前为止,我已经尝试使用“菜单屏幕”(mainContainer)来实例化所有游戏的面板,并在一些按钮上使用ActionListener来简单地调用
thisGame.setVisible(true)
。但这会迫使窗口最小化并重新打开,以便检测到任何更改。编辑:修复此问题

关于如何重新构造此代码,以便能够将面板从菜单屏幕切换到不同游戏的面板,有什么建议吗?(代码如下,但骰子和扑克GUI不完整..仅将代码用作占位符

public class CasinoDriverGUI {

     public static void main(String[] args) throws IOException {

    // load the texture resource image
    System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
    MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
    System.out.println("Loading finished. Starting the Casino!");

    MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);

    // Starting the Swing GUI in the EDT
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {


            final CardLayout cardLayout = new CardLayout();
            JFrame frame = new JFrame("Midnight Casino");
            // frame about the size of background src image
            frame.setPreferredSize(new Dimension(580, 329)); 
            final Container contentPane = frame.getContentPane();
            contentPane.setLayout(cardLayout);

            MainContainer mainContainer = new MainContainer();
            mainContainer.setPreferredSize( frame.getPreferredSize() );
            contentPane.add(mainContainer, "mainContainer");

            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setResizable(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);


        }
    });
}

static class MainContainer extends JPanel implements ActionListener
{
    public BufferedImage gradientImage = null;
    public static BufferedImage textureImg; // static for ease
    public static boolean loadingFinished = false;
    protected JButton pokerJBtn;
    protected JButton crapsJBtn;
    CrapsContainer crapsContainer;
    PokerContainer pokerContainer;

    public MainContainer() {
        setBorder(new EmptyBorder(50, 50, 50, 50)); // setting the insets 
        setLayout(new GridBagLayout()); 

        // working with GridBagConstraints
        GridBagConstraints labCnst = new GridBagConstraints();
        GridBagConstraints txtCnst = new GridBagConstraints();

        labCnst.ipady = txtCnst.ipady = 10;
        labCnst.fill = GridBagConstraints.HORIZONTAL;
        labCnst.gridwidth = 1;
        labCnst.weightx = 0.3;

        labCnst.gridx = 2;
        labCnst.gridy = 2;
        labCnst.ipady = 13;
        labCnst.insets = new Insets(0, 0, 0, 150);
        pokerJBtn = new CButton("5-Card Poker");
        add(pokerJBtn, labCnst);

        labCnst.gridx = 2;
        labCnst.gridy = 20;
        labCnst.ipady = 13;
        labCnst.insets = new Insets(0, 0, 0, 150);
        crapsJBtn = new CButton("Craps");
        add(crapsJBtn, labCnst);


        crapsContainer = new CrapsContainer();
        pokerContainer = new PokerContainer();

        add(crapsContainer); 
        add(pokerContainer);

        crapsContainer.setVisible(false);
        pokerContainer.setVisible(false);

        //Add Action Listeners
        crapsJBtn.addActionListener(this);
        pokerJBtn.addActionListener(this);


    }

    public void changeCompFont(JComponent comp)
    {
        comp.setForeground(Color.WHITE);
        comp.setFont(getFont().deriveFont(Font.BOLD, 13));
    }

    // To PAINT THE TEXTURE ABOVE THE COMPONENTS
    @Override
    public void paint(Graphics g)
    {
        super.paint(g);
        Graphics2D g2d = (Graphics2D)g.create(); // cloning
        Rectangle2D txRect = new Rectangle2D.Double(0, 0, textureImg.getWidth(), textureImg.getHeight());
        TexturePaint txPaint = new TexturePaint(textureImg, txRect);
        g2d.setPaint(txPaint);
        //make the texture transparent
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.233f));
        g2d.fillRect(0, 0, getWidth(), getHeight());
        g2d.dispose();// disposing the graphics object 
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); 
        Graphics2D g2d = (Graphics2D) g.create();

        if(gradientImage==null || gradientImage.getHeight() != getHeight() )
        {
            gradientImage = createGradientImg();
        }

        g2d.drawImage(gradientImage, 0, 0, getWidth(), getHeight(), this);
        g2d.dispose();
    }

    public BufferedImage createGradientImg()
    {
        BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
        //  background gradient paint, linear gradient paint for the background
        //  Gradient paint rendering could be made more optimized
        LinearGradientPaint lgrPaint =  new LinearGradientPaint(0.0f, 0.0f, getWidth(), getHeight(),
                new float[] { 0.0f, 0.5f, 0.6f, 1.0f },
                new Color[] { new Color(0x0530E),// new Color[] { new Color(0x002AFF),
                        new Color(0x0A31B),
                        new Color(0x0A31B),
                        new Color(0x0530E ) });


        Graphics2D g2d = (Graphics2D) image.getGraphics();
        g2d.setPaint(lgrPaint);
        //g2d.shear(0.2, 0);
        g2d.fillRect(0, 0, getWidth(), getHeight());

        g2d.dispose();
        g2d.drawImage(textureImg, 0, 0, getWidth(), getHeight(), null);
        return image;
    }

    @Override
    public void actionPerformed(ActionEvent e) 
    {
        if (e.getSource() == pokerJBtn) 
        {
            pokerContainer.setVisible(true);
        } 
        else if (e.getSource() == crapsJBtn){
            this.setVisible(false);
            invalidate();
            crapsContainer.setVisible(true);
            revalidate();
            repaint();

        }
    }

}

 //Either Flow, Border, or GridBag Layout
static class CrapsContainer extends JPanel implements ActionListener
{...}  

 //Either Flow, Border, or GridBag Layout
static class PokerContainer extends JPanel implements ActionListener
{...}  

//Custom Button to change aesthetic look
class CButton extends JButton
{...}

}

我无法让持有不同游戏GUI的JPanel将其事件发送回使用CardLayout的类中
-事件不应返回到使用CardLayout的类中。每个游戏都应包含在自己的面板中。@camickr因此,方法可能是将游戏面板嵌套在面板中CardLayout?并始终保持控制CardLayout的按钮在视图中?当然。如果按钮特定于游戏,则它们属于游戏面板。如果它们特定于应用程序中的所有游戏,则它们属于框架。您可以将带有CardLayout的面板添加到框架的中心。然后按钮面板可以转到北or在画面的南部。或者你可以使用一个JMenuBar来交换游戏。现在的一个主要障碍是,我的菜单屏幕本身就是一个使用GridBag布局的面板。我现在要重新构造它。我想我需要以某种方式将这个主菜单屏幕概念“合并”到主方法中。我想保持链接中图片的设计。每个“屏幕”或“视图”应该是一个独立的组件,如果可能的话,甚至是一个独立的类。您可以使用某种控制器来处理来自各种视图的导航请求,然后使用
CardLayout
在两者之间切换,