0

New to Java and very new to Java's GUI classes. I'm making a GUI to showcase a few games, but am having difficulties switching panels. I read about CardLayout but I'm having an issue implementing it because I can't get the JPanels that hold the different games' GUIs to send their events back to the class that uses the CardLayout. (This is probably where I'm going wrong -- I can't get my head around how to structure this properly.)

This is my main menu (called mainContainer):

Midnight Casino

This is the overall structure of the GUI driver:

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

Here is the main method: It grabs an image from a website and then adds the menu screen (mainContainer) to the contentPane. The menu screen uses GridBagLayout, but it's where the button components are added. Because of this, I can't figure out how to get the CardLayout of the contentPane to listen to the menu screen's buttons. I tried using ContainerListener but that seemed to be a dead end.

   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);


        }
    });
}

As I have it so far, I have just tried using the "menu screen" (mainContainer) to instantiate all the games' panels and use an ActionListener on some buttons to simply call thisGame.setVisible(true). but this is forcing the window to be minimized and re-opened for any change to be detectable.Edit: fixed this.

Any advice on how I can restructure this code to be able to switch the panels from the menu screen to the different game's panels? (Code is below, but the craps and poker GUIs are incomplete.. just using the code as placeholders.

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
{...}

}

Elfen Dew
  • 114
  • 1
  • 9
  • 1
    `I can't get the JPanels that hold the different games' GUIs to send their events back to the class that uses the CardLayout` - the events should NOT go back to the class using the card layout. Each game should be self contained in its own panel. – camickr Apr 18 '16 at 18:50
  • @camickr So, the way to go might be _nesting_ the games' panels inside the panel with the CardLayout? And keeping buttons that control the CardLayout always in view? – Elfen Dew Apr 18 '16 at 18:52
  • Sure. If the buttons are specific to the game they belong on the game panel. If they are specific to all games in the app then then belong on the frame. You might add the panel with the CardLayout to the CENTER of the frame. Then the buttons panel can go to the NORTH or SOUTH of the frame. Or maybe you use a JMenuBar to swap games. – camickr Apr 18 '16 at 18:56
  • One major obstacle right now is that my menu screen is itself a panel that uses GridBag Layout. I'm going to restructure this right now. I think I need to "merge" this main menu screen concept into the main method somehow. I want to keep the design as in the picture in the link. – Elfen Dew Apr 18 '16 at 19:14
  • Each "screen" or "view" should be an independent component, where possible, even a independent class. You can use a controller of some kind to deal with navigation requests from the various views and then switch between the using the `CardLayout`. For [example](http://stackoverflow.com/questions/36637989/i-need-a-jpanel-to-be-displayed-when-i-click-on-a-jtogglebutton/36638261#36638261), [example](http://stackoverflow.com/questions/31602113/listener-placement-adhering-to-the-traditional-non-mediator-mvc-pattern/31604919#31604919) – MadProgrammer Apr 18 '16 at 19:51
  • and [example](http://stackoverflow.com/questions/36657082/uploading-multiple-images-with-jfilechooser/36658101#36658101) – MadProgrammer Apr 18 '16 at 19:51
  • @MadProgrammer and [example](http://stackoverflow.com/questions/24296505/how-to-effectively-use-cardlayout-in-java-in-order-to-switch-from-panel-using-bu?rq=1). Thanks, MadProgrammer! I was just reading an answer you posted a year ago (see link)and realized it was the approach needed for this. – Elfen Dew Apr 18 '16 at 20:10
  • @ElfenDew, why did you remove the image? Your question was edited to include the image in the forum. There was no need for you to replace the image with a link. – camickr Apr 19 '16 at 02:18
  • @camickr I'm not sure how that happened. I was editing the post when I got a notification that someone else had edited it at the same time. I think when I finished editing, the image was removed. I didn't even know it was added until you mentioned just now. But either way, I'm sorry that happened.. I had originally wanted the image in the above post itself rather than a link. – Elfen Dew Apr 19 '16 at 05:25

0 Answers0