Home > Enterprise >  JLabel is not visible when JButton is clicked whilst JPanel is loading
JLabel is not visible when JButton is clicked whilst JPanel is loading

Time:09-02

When I click background selector on my main panel, it takes a while to load the JPanel and I wanted to show a loading JLabel whilst the background selector panel is loading, then disappear when the panel finally shows up. I tried to implement this in my buttons action listener. But for some reason when I remove the backgroundPanel() method from the action listener (aka panel is not being loaded when JButton is clicked but rather just the JLabel showing up), the label shows up when the button is clicked, but normally the label does not appear. I cannot understand why.

Window class:

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;

/**
 *
 */
public class Window {

public static JFrame frame;
GameWindow game;
BackgroundSelector background;
static DifficultySelector difficulty;
public static MainBackgroundImage main; // start window
JProgressBar progressBar = new JProgressBar();
private boolean loaded = false;

public Window() throws IOException {

    frame = new JFrame("Brick Builder Game"); // creates JFrame

    game = new GameWindow(); // creates new GAME window
    main = new MainBackgroundImage(); // creates MAIN screen
    background = new BackgroundSelector(); // creates BACKGROUND SELECTOR window
    difficulty = new DifficultySelector(); // creates DIFFICULTY SELECTOR window

    main.setLayout(null);

    frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
    frame.setSize(500,500);
    frame.setVisible(true);
    frame.setResizable(false);

    frame.getContentPane().add(main); // adds MAIN screen to frame


    JButton start = new JButton();
    Image startImg = ImageIO.read(getClass().getResource("start.png"));
    start.setIcon(new ImageIcon(startImg));
    start.setBounds(150,270,200,40);
    start.setOpaque(false);
    start.setBorderPainted(false);

    JButton backgroundSelector = new JButton();
    Image selectorImg = ImageIO.read(getClass().getResource("selector.png"));
    backgroundSelector.setIcon(new ImageIcon(selectorImg));
    backgroundSelector.setBounds(150, 320,200,40);
    backgroundSelector.setOpaque(false);
    backgroundSelector.setBorderPainted(false);


    JButton quit = new JButton();
    Image quitImg = ImageIO.read(getClass().getResource("quit.png"));
    quit.setIcon(new ImageIcon(quitImg));
    quit.setBounds(150,370,200,40);
    quit.setOpaque(false);
    quit.setBorderPainted(false);

    JLabel loading = new JLabel();
    loading.setBounds(150,400,100,20);

    main.repaint();

    start.setBackground(Color.white);
    backgroundSelector.setBackground(Color.white);
    quit.setBackground(Color.white);

    start.setFocusable(false);
    quit.setFocusable(false);
    backgroundSelector.setFocusable(false);
    start.setAlignmentX(Component.CENTER_ALIGNMENT);
    quit.setAlignmentX(Component.CENTER_ALIGNMENT);
    backgroundSelector.setAlignmentX(Component.CENTER_ALIGNMENT);
    
    main.add(start); // adds JButton
    main.add(quit);
    main.add(backgroundSelector);
    main.add(loading);
    main.add(progressBar);

    start.addActionListener(e -> difficultyPanel());

    quit.addActionListener(e -> {
        frame.dispose();
    });

    backgroundSelector.addActionListener(e -> {
        loading.setText("Loading...");
        backgroundPanel();
    });

    //backgroundSelector.addActionListener(e -> backgroundPanel());
}

public static void mainPanel(){
    frame.getContentPane().removeAll();
    frame.getContentPane().add(main);
    frame.validate();
}

public void backgroundPanel(){
    //loaded = false;
    frame.getContentPane().removeAll();
    background = new BackgroundSelector();
    frame.getContentPane().add(background);
    frame.revalidate();
}

public void difficultyPanel(){
    frame.getContentPane().removeAll();
    difficulty = new DifficultySelector();
    frame.getContentPane().add(difficulty);
    frame.requestFocusInWindow();
    frame.revalidate();
}

    public static void main (String[]args) throws IOException {
        new Window();
    }
}

Background selector class:

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyListener;

/**
 * This class creates the background selector JPanel which allows the player to choose a background
 * of their choice. A choice of 6 backgrounds is given to the player to choose from.
 *
 */
public class BackgroundSelector extends JPanel{

    DifficultySelector difficulty = new DifficultySelector();

    private final ClassLoader cl = Thread.currentThread().getContextClassLoader();
    private final Image image = Toolkit.getDefaultToolkit().getImage(cl.getResource("black.jpg"));

    JLabel label;

    // creates the radioButtons which display the backgrounds to choose from
    JRadioButton radioButton;
    JRadioButton radioButton2;
    JRadioButton radioButton3;
    JRadioButton radioButton4;
    JRadioButton radioButton5;
    JRadioButton radioButton6;

    public static boolean option1 = false;
    public static boolean option2 = false;
    public static boolean option3 = false;
    public static boolean option4 = false;
    public static boolean option5 = false;
    public static boolean option6 = false;

    /**
 * Constructor which adds the radio buttons to a button group and displays them on the JPanel using a flow layout.
 *
 */
public BackgroundSelector(){

    label = new JLabel("Please select a background", JLabel.CENTER);
    label.setFont(new Font("Verdana", Font.BOLD, 18));
    label.setForeground(Color.white);

    setLayout(new FlowLayout());
    ButtonGroup group = new ButtonGroup();
    group.add(radioButton);
    group.add(radioButton2);
    group.add(radioButton3);
    group.add(radioButton4);
    group.add(radioButton5);
    group.add(radioButton6);

    option1();
    option2();
    option3();
    option4();
    option5();
    option6();
    add(label);
}


/**
 * Paints background image of panel to black chalk image.
 * @param g
 */
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    image.getScaledInstance(500, 500,Image.SCALE_SMOOTH);
    while(!prepareImage(image, this)) {
        prepareImage(image, this);
    }
    g.drawImage(image,0,0,null);
}

/**
 * Converts the url to an image which will be used as the icon for the JRadioButton.
 *
 * @param url The url of the image.
 * @return The image with a specific height and width.
 */
public String URL(String url){
    return "<html><body><img src='"   url   "'width=128 height=128>";
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the space background.
 *
 */
public void option1() {
    String url = URL("https://www.nasa.gov/sites/default/files/styles/full_width/public/thumbnails/image/main_image_star-forming_region_carina_nircam_final-1280.jpg");
    radioButton = new JRadioButton(url);
    add(radioButton);
    radioButton.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("space.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option1 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the bricks background.
 *
 */
public void option2(){
    String url = URL("https://appgrooves.com/cdn/mc/GAME_ARCADE/7_w1200.jpg");
    radioButton2 = new JRadioButton(url);
    add(radioButton2);
    radioButton2.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("space.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option2 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the stars background.
 *
 */
public void option3(){
    String url = URL("https://upload.wikimedia.org/wikipedia/commons/2/26/Oldest_star_in_solar_neighbourhood.jpg");
    radioButton3 = new JRadioButton(url);
    add(radioButton3);
    radioButton3.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("stars.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option3 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the bubbles background.
 *
 */
public void option4(){
    String url = URL("https://cdn.pocket-lint.com/assets/images/131835-phones-news-feature-cropped-best-iphone-wallpapers-image72-7pqcs1gy9h.jpg");
    radioButton4 = new JRadioButton(url);
    add(radioButton4);
    radioButton4.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("stars.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option4 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the forest background.
 *
 */
public void option5(){
    String url = URL("https://images.hdqwalls.com/download/blue-forest-minimal-4k-kz-2048x2048.jpg");
    radioButton5 = new JRadioButton(url);
    add(radioButton5);
    radioButton5.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("stars.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option5 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the japanese purple background.
 *
 */
public void option6(){
    String url = URL("https://www.pixelstalk.net/wp-content/uploads/images5/Cool-Japanese-Backgrounds-HD-Free-download.jpg");
    radioButton6 = new JRadioButton(url);
    add(radioButton6);
    radioButton6.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("stars.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option6 = true;
    });
}

}

CodePudding user response:

Not been able to run the code leads to a number of assumptions.

Based on you description, I would say you are blocking the Event Dispatching Thread while loading the image, this is going to prevent the UI from been updated.

See enter image description here

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new MainPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class MainPane extends JPanel {

        public interface Observer {
            public void start();
            public void quit();
            public void didLoadBackground(BufferedImage img);
        }

        enum View {
            MAIN, START
        }

        private BufferedImage background;
        private CardLayout cardLayout;

        public MainPane() throws IOException {
            cardLayout = new CardLayout();
            setLayout(cardLayout);
            background = ImageIO.read(getClass().getResource("/images/Mando01.jpeg"));
            add(new OptionsPane(new Observer() {
                @Override
                public void start() {
                    show(View.START);
                }

                @Override
                public void quit() {
                    SwingUtilities.windowForComponent(MainPane.this).dispose();
                }

                @Override
                public void didLoadBackground(BufferedImage img) {
                    JOptionPane.showMessageDialog(MainPane.this, "You have a pretty picture", "Notice", JOptionPane.INFORMATION_MESSAGE);
                }
            }), View.MAIN);

            add(new GamePane(), View.START);
        }       

        public void add(Component component, View view) {
            add(component, view.name());
        }

        public void show(View view) {
            cardLayout.show(this, view.name());
        }

        @Override
        public Dimension getPreferredSize() {
            if (background != null) {
                return new Dimension(background.getWidth(), background.getHeight());
            }
            return super.getPreferredSize();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background == null) {
                return;
            }
            int x = (getWidth() - background.getWidth()) / 2;
            int y = (getHeight() - background.getHeight()) / 2;
            g.drawImage(background, x, y, this);
        }
    }

    public class OptionsPane extends JPanel {
        private MainPane.Observer observer;
        public OptionsPane(MainPane.Observer observer) {
            setOpaque(false);
            setLayout(new GridBagLayout());
            JButton start = new JButton("Start");
            start.setOpaque(false);
            start.setBorderPainted(false);
            start.setForeground(Color.WHITE);

            JButton backgroundSelector = new JButton("Background");
            backgroundSelector.setOpaque(false);
            backgroundSelector.setBorderPainted(false);
            backgroundSelector.setForeground(Color.WHITE);

            JButton quit = new JButton("Quit");
            quit.setOpaque(false);
            quit.setBorderPainted(false);
            quit.setForeground(Color.WHITE);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weighty = 1;
            gbc.anchor = GridBagConstraints.SOUTH;
            gbc.insets = new Insets(4, 4, 4, 4);

            add(start, gbc); // adds JButton
            gbc.weighty = 0;
            gbc.gridy  ;
            add(backgroundSelector, gbc);
            gbc.gridy  ;
            add(quit, gbc);

            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    observer.start();
                }
            });

            quit.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    observer.quit();
                }
            });

            backgroundSelector.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    // This "could" use the glassPane, but that's
                    // an additional complexity
                    JPanel panel = new JPanel(new GridBagLayout());
                    JLabel label = new JLabel("Loading...");
                    label.setHorizontalAlignment(JLabel.CENTER);
                    JProgressBar progressBar = new JProgressBar(0, 100);

                    GridBagConstraints gbc = new GridBagConstraints();
                    gbc.gridx = GridBagConstraints.REMAINDER;
                    gbc.insets = new Insets(2, 2, 2, 2);
                    gbc.fill = gbc.HORIZONTAL;

                    panel.setBorder(new EmptyBorder(8, 8, 8, 8));
                    panel.add(label, gbc);
                    panel.add(progressBar, gbc);

                    gbc = new GridBagConstraints();
                    gbc.gridx = 0;
                    gbc.gridy = 0;
                    gbc.gridwidth = gbc.REMAINDER;
                    gbc.gridheight = gbc.REMAINDER;

                    add(panel, gbc);

                    revalidate();
                    repaint();

                    SwingWorker<BufferedImage, Void> worker = new SwingWorker<BufferedImage, Void>() {
                        @Override
                        protected BufferedImage doInBackground() throws Exception {
                            for (int progress = 0; progress <= 100; progress  ) {
                                Thread.sleep(50);
                                setProgress(progress);
                            }
                            return null;
                        }
                    };
                    worker.addPropertyChangeListener(new PropertyChangeListener() {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            String name = evt.getPropertyName();
                            if (worker.getState() == SwingWorker.StateValue.DONE) {
                                remove(panel);
                                revalidate();
                                repaint();
                                try {
                                    observer.didLoadBackground(worker.get());
                                } catch (InterruptedException | ExecutionException ex) {
                                    ex.printStackTrace();
                                    JOptionPane.showMessageDialog(OptionsPane.this, "Failed to load image", "Error", JOptionPane.ERROR_MESSAGE);
                                }
                            } else if ("progress".equalsIgnoreCase(name)) {
                                progressBar.setValue((int)evt.getNewValue());
                            }
                        }

                    });
                    worker.execute();
                }
            });
        }
    }

    public class GamePane extends JPanel {
        public GamePane() {
            setOpaque(false);
            setLayout(new GridBagLayout());
            add(new JLabel("Let's get this party started"));
        }        
    }
}

Now, if you want progress feedback when loading an image, that's a much more complex solution, see Using JProgressBar while converting image to byte array for more details

okay but now I am running into another issue. With card layout i cannot add key listener, setFocusable or requestFocusableInWindow so my paddle is not moving when i start the game

Stop using KeyListener, it's not an appropriate mechanism for what you're trying to achieve, instead, use the key bindings API, this will remove the need for all the related KeyListener hacks

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new MainPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class MainPane extends JPanel {

        public interface Observer {
            public void start();

            public void quit();

            public void didLoadBackground(BufferedImage img);
        }

        enum View {
            MAIN, START
        }

        private BufferedImage background;
        private CardLayout cardLayout;

        public MainPane() throws IOException {
            cardLayout = new CardLayout();
            setLayout(cardLayout);
            background = scaled(ImageIO.read(getClass().getResource("/images/Mando01.jpeg")));
            add(new OptionsPane(new Observer() {
                @Override
                public void start() {
                    show(View.START);
                }

                @Override
                public void quit() {
                    SwingUtilities.windowForComponent(MainPane.this).dispose();
                }

                @Override
                public void didLoadBackground(BufferedImage img) {
                    JOptionPane.showMessageDialog(MainPane.this, "You have a pretty picture", "Notice", JOptionPane.INFORMATION_MESSAGE);
                }
            }), View.MAIN);

            add(new GamePane(), View.START);
        }

        protected BufferedImage scaled(BufferedImage original) {
            BufferedImage scaled = new BufferedImage(original.getWidth() / 2, original.getHeight() / 2, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = scaled.createGraphics();
            g2d.transform(AffineTransform.getScaleInstance(0.5, 0.5));
            g2d.drawImage(original, 0, 0, this);
            g2d.dispose();
            return scaled;
        }

        public void add(Component component, View view) {
            add(component, view.name());
        }

        public void show(View view) {
            cardLayout.show(this, view.name());
        }

        @Override
        public Dimension getPreferredSize() {
            if (background != null) {
                return new Dimension(background.getWidth(), background.getHeight());
            }
            return super.getPreferredSize();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background == null) {
                return;
            }
            int x = (getWidth() - background.getWidth()) / 2;
            int y = (getHeight() - background.getHeight()) / 2;
            g.drawImage(background, x, y, this);
        }
    }

    public class OptionsPane extends JPanel {
        private MainPane.Observer observer;

        public OptionsPane(MainPane.Observer observer) {
            setOpaque(false);
            setLayout(new GridBagLayout());
            JButton start = new JButton("Start");
            start.setOpaque(false);
            start.setBorderPainted(false);
            start.setForeground(Color.WHITE);

            JButton backgroundSelector = new JButton("Background");
            backgroundSelector.setOpaque(false);
            backgroundSelector.setBorderPainted(false);
            backgroundSelector.setForeground(Color.WHITE);

            JButton quit = new JButton("Quit");
            quit.setOpaque(false);
            quit.setBorderPainted(false);
            quit.setForeground(Color.WHITE);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weighty = 1;
            gbc.anchor = GridBagConstraints.SOUTH;
            gbc.insets = new Insets(4, 4, 4, 4);

            add(start, gbc); // adds JButton
            gbc.weighty = 0;
            gbc.gridy  ;
            add(backgroundSelector, gbc);
            gbc.gridy  ;
            add(quit, gbc);

            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    observer.start();
                }
            });

            quit.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    observer.quit();
                }
            });

            backgroundSelector.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    // This "could" use the glassPane, but that's
                    // an additional complexity
                    JPanel panel = new JPanel(new GridBagLayout());
                    JLabel label = new JLabel("Loading...");
                    label.setHorizontalAlignment(JLabel.CENTER);
                    JProgressBar progressBar = new JProgressBar(0, 100);

                    GridBagConstraints gbc = new GridBagConstraints();
                    gbc.gridx = GridBagConstraints.REMAINDER;
                    gbc.insets = new Insets(2, 2, 2, 2);
                    gbc.fill = gbc.HORIZONTAL;

                    panel.setBorder(new EmptyBorder(8, 8, 8, 8));
                    panel.add(label, gbc);
                    panel.add(progressBar, gbc);

                    gbc = new GridBagConstraints();
                    gbc.gridx = 0;
                    gbc.gridy = 0;
                    gbc.gridwidth = gbc.REMAINDER;
                    gbc.gridheight = gbc.REMAINDER;

                    add(panel, gbc);

                    revalidate();
                    repaint();

                    SwingWorker<BufferedImage, Void> worker = new SwingWorker<BufferedImage, Void>() {
                        @Override
                        protected BufferedImage doInBackground() throws Exception {
                            for (int progress = 0; progress <= 100; progress  ) {
                                Thread.sleep(50);
                                setProgress(progress);
                            }
                            return null;
                        }
                    };
                    worker.addPropertyChangeListener(new PropertyChangeListener() {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            String name = evt.getPropertyName();
                            if (worker.getState() == SwingWorker.StateValue.DONE) {
                                remove(panel);
                                revalidate();
                                repaint();
                                try {
                                    observer.didLoadBackground(worker.get());
                                } catch (InterruptedException | ExecutionException ex) {
                                    ex.printStackTrace();
                                    JOptionPane.showMessageDialog(OptionsPane.this, "Failed to load image", "Error", JOptionPane.ERROR_MESSAGE);
                                }
                            } else if ("progress".equalsIgnoreCase(name)) {
                                progressBar.setValue((int) evt.getNewValue());
                            }
                        }

                    });
                    worker.execute();
                }
            });
        }
    }

    public class GamePane extends JPanel implements DeltaAction.Observer {

        public class Box {
            private Shape box = new Rectangle2D.Double(0, 0, 50, 50);
            private Point p = new Point();

            public void paint(Graphics2D g2d) {
                g2d = (Graphics2D) g2d.create();
                g2d.setColor(Color.BLUE);
                g2d.translate(p.getX(), p.getY());
                g2d.fill(box);
                g2d.dispose();
            }

            public Point getLocation() {
                return new Point(p);
            }

            public void setLocation(Point p) {
                this.p = p;
            }

            public Rectangle2D getBounds() {
                return new Rectangle2D.Double(p.getX(), p.getY(), box.getBounds2D().getHeight(), box.getBounds2D().getHeight());
            }
        }

        protected enum KeyInput {
            PRESSED_UP, RELEASED_UP,
            PRESSED_DOWN, RELEASED_DOWN,
            PRESSED_LEFT, RELEASED_LEFT,
            PRESSED_RIGHT, RELEASED_RIGHT;
        }

        private Box box = new Box();
        private int xDelta = 0;
        private int yDelta = 0;

        private Timer timer;

        public GamePane() {
            setOpaque(false);
            setLayout(new GridBagLayout());
            add(new JLabel("Let's get this party started"));

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), KeyInput.PRESSED_UP);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), KeyInput.RELEASED_UP);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), KeyInput.PRESSED_DOWN);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true), KeyInput.RELEASED_DOWN);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), KeyInput.PRESSED_LEFT);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), KeyInput.RELEASED_LEFT);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), KeyInput.PRESSED_RIGHT);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true), KeyInput.RELEASED_RIGHT);

            am.put(KeyInput.PRESSED_UP, new DeltaAction(DeltaAction.Direction.UP, true, this));
            am.put(KeyInput.RELEASED_UP, new DeltaAction(DeltaAction.Direction.UP, false, this));
            am.put(KeyInput.PRESSED_DOWN, new DeltaAction(DeltaAction.Direction.DOWN, true, this));
            am.put(KeyInput.RELEASED_DOWN, new DeltaAction(DeltaAction.Direction.DOWN, false, this));
            am.put(KeyInput.PRESSED_LEFT, new DeltaAction(DeltaAction.Direction.LEFT, true, this));
            am.put(KeyInput.RELEASED_LEFT, new DeltaAction(DeltaAction.Direction.LEFT, false, this));
            am.put(KeyInput.PRESSED_RIGHT, new DeltaAction(DeltaAction.Direction.RIGHT, true, this));
            am.put(KeyInput.RELEASED_RIGHT, new DeltaAction(DeltaAction.Direction.RIGHT, false, this));

            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Point location = box.getLocation();
                    location.x  = xDelta;
                    location.y  = yDelta;
                    box.setLocation(location);

                    Rectangle2D bounds = box.getBounds();
                    if (bounds.getX() < 0) {
                        location.x = 0;
                    } else if (bounds.getX()   bounds.getWidth() > getWidth()) {
                        location.x = (int)(getWidth() - bounds.getWidth());
                    }
                    if (bounds.getY() < 0) {
                        location.y = 0;
                    } else if (bounds.getY()   bounds.getHeight()> getHeight()) {
                        location.y = (int)(getHeight() - bounds.getHeight());
                    }

                    box.setLocation(location);
                    repaint();
                }
            });

            addComponentListener(new ComponentAdapter() {
                @Override
                public void componentHidden(ComponentEvent e) {
                    timer.stop();
                }

                @Override
                public void componentShown(ComponentEvent e) {
                    System.out.println("Hello");
                    timer.start();
                }
            });
        }

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

        @Override
        public void directionApplied(DeltaAction.Direction direction, boolean activate) {
            switch (direction) {
                case UP:
                    yDelta = activate ? -4 : 0;
                    break;
                case DOWN:
                    yDelta = activate ? 4 : 0;
                    break;
                case LEFT:
                    xDelta = activate ? -4 : 0;
                    break;
                case RIGHT:
                    xDelta = activate ? 4 : 0;
                    break;
            }
        }

    }

    public class DeltaAction extends AbstractAction {
        public interface Observer {
            public void directionApplied(Direction direction, boolean activate);
        }

        public enum Direction {
            UP, DOWN, LEFT, RIGHT;
        }

        private Direction direction;
        private boolean activate;
        private Observer observer;

        public DeltaAction(Direction direction, boolean activate, Observer observer) {
            this.direction = direction;
            this.activate = activate;
            this.observer = observer;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            observer.directionApplied(direction, activate);
        }
    }
}

I am getting so many bugs with card layout, its ruining my whole application

This has nothing to do with CardLayout but you choices in how you designed you original application. Layouts are your friends, make the time to learn how to use them

I don't see how I can update the background panel if its ALREADY added to the card pane, the only way I can think of is destroying it and adding a new one each time (which is what i have but is taking very long to load)

Then don't - this is my whole point, you need to change the way you think about the problem.

To change the background image of the background pane, all you need to do is change the reference to the background image the panel is using.

I'd have a "base" pane, which would use a BorderLayout and contain the "background" pane. The "background" pane would then have the CardLayout set to it and it would then become the parent container for all the other components.

When the user selects a new image, you'd make use of the "observer pattern" to generate a notification back to the "base" pane which would then assign the new image to the background pane.

I've run out of room to post any new updates, so this the last one I can provide via a simple gist

  • Related