JLabel is not visible when JButton is clicked whilst JPanel is loading - java

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

Just add the following method to the background selector :)
and call it on background() method in window
public void resetLayout() {
radioButton.setSelected(false);
radioButton2.setSelected(false);
radioButton3.setSelected(false);
radioButton4.setSelected(false);
radioButton5.setSelected(false);
radioButton6.setSelected(false);
}
really ugly, could be better, but works!

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 Concurrency in Swing for more details. I'd recommend using a SwingWorker to actually load the image.
You should also be making use of layout managers, you'd find CardLayout especially helpful for switching between components.
For example...
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

How can I open a JInternalFrame inside a panel (inside parent) from another child JInternalFrame?

I have 3 frames, Main (as the parent) and 2 JInternalFrames (F1 and F2 as children). When a button (inside parent) is pressed, I make an instance of F1 and send it as a parameter to ShowIntrlFrame() so F1 can be displayed inside frmContainter. My question here is, how can I open F2 from F1 and display it on frmContrainer (which is in the Main frame)?
public class Main extends javax.swing.JFrame{
public Main(){
}
private void btnOpenFrmActionPerformed(java.awt.event.ActionEvent evt) {
F1 f1 = new F1();
frmContainer(f1);
}
}
public void ShowIntrlFrame(JInternalFrame f){
f.setSize(1100, 620);
f.setLocation(0, 0);
f.setVisible(true);
frmContainer.removeAll();
frmContainer.add(f, BorderLayout.CENTER);
frmContainer.revalidate();
frmContainer.repaint();
}
What I would do is follow a delegation pattern via dependency injection.
This is, I would "delegate" the functionality need to generate and show the window to some other class and then "inject" that into the workflow as required
I'd start with a concept of a "window manager"...
public interface WindowManager {
enum Window {
FIRST, SECOND;
}
public void openWindow(Window window);
}
At the moment, this is pretty basic and just opens a specified window. The nice thing about this, is we don't care if it's a JInternalFrame or JFrame which gets generated, that's not the callers responsibility.
Next, we make a implementation which supports JDesktopPane
public class DesktopWindowManage implements WindowManager {
private JDesktopPane desktopPane;
private int initialX = 0;
private int initialY = 0;
public DesktopWindowManage(JDesktopPane desktopPane) {
this.desktopPane = desktopPane;
}
public JDesktopPane getDesktopPane() {
return desktopPane;
}
#Override
public void openWindow(Window window) {
JInternalFrame frame = new JInternalFrame(window.name(), true, true, true, true);
frame.setContentPane(makeContentFor(window));
frame.pack();
frame.setLocation(initialX, initialY);
frame.setVisible(true);
try {
frame.setSelected(true);
} catch (PropertyVetoException ex) {
}
desktopPane.add(frame);
frame.toFront();
initialX += 20;
initialY += 20;
}
protected JPanel makeContentFor(Window window) {
switch (window) {
case FIRST: return new FirstPane(this);
case SECOND: return new SecondPane();
}
return null;
}
}
Now, important to note, this class is acting as kind of factory, in that it's generating the content view and JInternalFrame. I'd probably consider making a "content factory" which could be injected into this which would then create the content based on the desired destination, but that's probably getting a little more complicated then is required right now.
Now, before you ask, the actual content is based on JPanel, for example...
public class FirstPane extends JPanel {
public FirstPane(WindowManager windowManager) {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
add(new JLabel("I am first"), gbc);
JButton showSecond = new JButton("Show second");
showSecond.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.SECOND);
}
});
add(showSecond, gbc);
}
}
public class SecondPane extends JPanel {
public SecondPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
add(new JLabel("I am second"));
}
}
Why? Because it's a JPanel can be added to any container and, generally, we don't care if it's a JInternalFrame or JFrame.
And finally, some kind of "starting point"....
public class MainPane extends JPanel {
private WindowManager windowManager;
private JDesktopPane desktopPane;
public MainPane() {
setLayout(new BorderLayout());
JButton open = new JButton("Open");
desktopPane = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
windowManager = new DesktopWindowManage(desktopPane);
add(open, BorderLayout.NORTH);
add(desktopPane);
open.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.FIRST);
}
});
}
}
Runnable example...
import java.awt.BorderLayout;
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.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
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() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface WindowManager {
enum Window {
FIRST, SECOND;
}
public void openWindow(Window window);
}
public class DesktopWindowManage implements WindowManager {
private JDesktopPane desktopPane;
private int initialX = 0;
private int initialY = 0;
public DesktopWindowManage(JDesktopPane desktopPane) {
this.desktopPane = desktopPane;
}
public JDesktopPane getDesktopPane() {
return desktopPane;
}
#Override
public void openWindow(Window window) {
JInternalFrame frame = new JInternalFrame(window.name(), true, true, true, true);
frame.setContentPane(makeContentFor(window));
frame.pack();
frame.setLocation(initialX, initialY);
frame.setVisible(true);
try {
frame.setSelected(true);
} catch (PropertyVetoException ex) {
}
desktopPane.add(frame);
frame.toFront();
initialX += 20;
initialY += 20;
}
protected JPanel makeContentFor(Window window) {
switch (window) {
case FIRST: return new FirstPane(this);
case SECOND: return new SecondPane();
}
return null;
}
}
public class MainPane extends JPanel {
private WindowManager windowManager;
private JDesktopPane desktopPane;
public MainPane() {
setLayout(new BorderLayout());
JButton open = new JButton("Open");
desktopPane = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
windowManager = new DesktopWindowManage(desktopPane);
add(open, BorderLayout.NORTH);
add(desktopPane);
open.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.FIRST);
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class FirstPane extends JPanel {
public FirstPane(WindowManager windowManager) {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
add(new JLabel("I am first"), gbc);
JButton showSecond = new JButton("Show second");
showSecond.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.SECOND);
}
});
add(showSecond, gbc);
}
}
public class SecondPane extends JPanel {
public SecondPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
add(new JLabel("I am second"));
}
}
}
But wait, there's more...
Currently, if you tap "Open" or "Show second" multiple times, you get a bunch of new windows. This may or may not be desirable, but could be easily fixed via the WindowManager, in fact, you could create different WindowManagers based on your needs, for example...
public class DesktopWindowManage implements WindowManager {
private JDesktopPane desktopPane;
private int initialX = 0;
private int initialY = 0;
private Map<Window, JInternalFrame> windowCache = new HashMap<>();
public DesktopWindowManage(JDesktopPane desktopPane) {
this.desktopPane = desktopPane;
}
public JDesktopPane getDesktopPane() {
return desktopPane;
}
#Override
public void openWindow(Window window) {
JInternalFrame frame = windowCache.get(window);
if (frame == null) {
frame = new JInternalFrame(window.name(), true, true, true, true);
frame.setContentPane(makeContentFor(window));
windowCache.put(window, frame);
frame.pack();
frame.setLocation(initialX, initialY);
frame.setVisible(true);
desktopPane.add(frame);
initialX += 20;
initialY += 20;
}
try {
frame.setSelected(true);
} catch (PropertyVetoException ex) {
}
frame.toFront();
}
protected JPanel makeContentFor(Window window) {
switch (window) {
case FIRST:
return new FirstPane(this);
case SECOND:
return new SecondPane();
}
return null;
}
}

Swing: How to create a scrollable list of JPanels that use no Layout

I am trying to find a way to create a list of JPanels which have no Layout manager.
I found several examples on SO providing solutions to the 'scrollable JPanel list' problem. More specifically, I started from this thread and worked on it.
My current problem is that I am having issues when I remove the layout from the JPanels in the list.
They get added correctly but the scrollbar does not appear when needed, and the panels start overlapping.
Note: I know that layouts are heavily preferred but I find it more straightforward to work with pure X, Y coordinates and a mockup program. Please do not bash me for this...
Here is a small working example (taken and modified from this comment):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.MatteBorder;
public class JScrollPanels {
private int i;
private JPanel listContainer;
private void initUI() {
final JFrame frame = new JFrame(JScrollPanels.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
listContainer = new JPanel();
listContainer.setLayout(new BoxLayout(listContainer, BoxLayout.Y_AXIS));
frame.add(new JScrollPane(listContainer), BorderLayout.CENTER);
JButton button = new JButton("Add");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
final JPanel newPanel = new JPanel();
newPanel.setLayout(null);
newPanel.setSize(272, 110);
JLabel name = new JLabel("Name " + i++);
name.setBounds(18, 13, 84, 21);
newPanel.setBorder(new MatteBorder(0, 0, 1, 0, Color.GRAY));
JLabel date = new JLabel("12/11/2014");
date.setBounds(10, 44, 123, 21);
JButton btn= new JButton(">");
btn.addActionListener( new NameListener(name, date) );
btn.setBounds(205, 44, 48, 30);
newPanel.add(name);
newPanel.add(date);
newPanel.add(btn);
listContainer.add(newPanel);
listContainer.revalidate();
// Scroll down to last added panel
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
newPanel.scrollRectToVisible(newPanel.getBounds());
}
});
}
});
frame.add(button, BorderLayout.PAGE_END);
frame.setSize(272, 300);
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JScrollPanels().initUI();
}
});
}
public class NameListener implements ActionListener {
private JLabel name;
private JLabel date;
public NameListener(JLabel name, JLabel date) {
this.name = name;
this.date = date;
}
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked " + name.getText() + " on " + date.getText());
}
}
}
EDIT:
Fixed by using this:
final JPanel newPanel = new JPanel(){
#Override
public Dimension getPreferredSize() {
return new Dimension(272, 110);
}
};
Thanks, mKorbel!
Again, I still persist in my claim that in the long run, a layout manager will work best. For instance, your GUI could use something perhaps like this:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;
import javax.swing.border.Border;
#SuppressWarnings("serial")
public class JScrollPanels2 extends JPanel {
private static final int PREF_W = 300;
private static final int PREF_H = 300;
private int i;
private JPanel listContainer;
public JScrollPanels2() {
JPanel outerWrapperPanel = new JPanel(new BorderLayout());
listContainer = new JPanel();
listContainer.setLayout(new BoxLayout(listContainer, BoxLayout.Y_AXIS));
outerWrapperPanel.add(listContainer, BorderLayout.PAGE_START);
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
buttonPanel.add(new JButton(new AddAction("Add")));
setLayout(new BorderLayout());
add(new JScrollPane(outerWrapperPanel), BorderLayout.CENTER);
add(buttonPanel, BorderLayout.PAGE_END);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class AddAction extends AbstractAction {
public AddAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent evt) {
listContainer.add(new CellPanel(i));
listContainer.revalidate();
listContainer.repaint();
i++;
}
}
private class CellPanel extends JPanel {
private final int gap = 4;
private int index;
private String name;
private Date date;
private final String format = "MM/dd/yyyy";
private SimpleDateFormat sdf = new SimpleDateFormat(format);
public CellPanel(int i) {
this.index = i;
this.name = "Name " + index;
setLayout(new GridBagLayout());
date = new Date();
Border emptyBorder = BorderFactory.createEmptyBorder(gap, gap, gap, gap);
Border lineBorder = BorderFactory.createLineBorder(Color.black);
setBorder(BorderFactory.createCompoundBorder(lineBorder, emptyBorder));
add(new JLabel(name), createGbc(0, 0));
add(new JLabel(""), createGbc(1, 0));
add(new JLabel(sdf.format(date)), createGbc(0, 1));
add(new JButton(new MyBtnAction(">")), createGbc(1, 1));
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
if (x % 2 == 0) {
gbc.anchor = GridBagConstraints.WEST;
} else {
gbc.anchor = GridBagConstraints.EAST;
}
return gbc;
}
private class MyBtnAction extends AbstractAction {
public MyBtnAction(String name) {
super(name);
// int mnemonic = (int) name.charAt(0);
// putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent evt) {
System.out.println("Button pressed for " + name);
}
}
}
private static void createAndShowGui() {
JScrollPanels2 mainPanel = new JScrollPanels2();
JFrame frame = new JFrame("JScrollPanels2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
One of the beauties of use of layout managers is their flexibility. If you wanted to add new components to the inner JPanel, you can easily do so without having to manually recalculate every dang other component's position, if they need to be shifted. Instead, let the layout managers do the heavy lifting for you. Also, while your null-layout using GUI might look good on one platform it will usually look terrible on most other platforms or screen resolutions.

getText from JTextField in 1 class and place it on a label in the other

I have one class Names and it has a JTextField. I am trying to place getText from this textfield and save it in the variable nameString1. I then want the other class Game to call Names and place the string collected from ``the JTextField onto a label. For some reason it is not displaying. Please let me know if there are any rookie errors, I am only year 10.
Names
package com.aqagame.harrykitchener;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Names
{
private JLabel player1Label;
private JTextField player1Input;
private JButton nextButton;
public String nameString1;
public Names()
{
final JFrame window = new JFrame("Player 1 username");
JPanel firstPanel = new JPanel(new GridLayout(3,2));
player1Label = new JLabel("Player 1");
player1Input = new JTextField();
nextButton = new JButton("Next");
firstPanel.add(player1Label);
firstPanel.add(player1Input);
firstPanel.add(nextButton);
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
nameString1 = player1Input.getText();
System.out.print(nameString1);
Names2 names2Call = new Names2();
window.dispose();
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(firstPanel);
window.setSize(250, 150);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Names();
}
});
}
}
Game
package com.aqagame.harrykitchener;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Game
{
private JLabel player1Str, player2Str;
public Game()
{
JFrame window = new JFrame ("Main Game");
JPanel drawPanel = new JPanel(new GridLayout(3, 1))
{
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() / 4;
int height = getHeight() / 11;
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
}
};
Names namesCall2 = new Names();
player1Str = new JLabel(namesCall2.nameString1);
drawPanel.add(player1Str);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawPanel);
window.setSize(700, 600);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Game();
}
});
}
}
The problem is that you are setting the label without getting the textfield text. The JLabel on your Game wont change by the time you click the button..
Okie I made some change in you classes What I did is that I maid an interface which will be called when your button is pressed
Here is the interface:
public interface Lawl {
public void changename(String name);
}
I then implemented this interface to the game:
public class Game implements Lawl
{
private JLabel player1Str, player2Str;
JPanel drawPanel;
Names namesCall2;
public Game()
{
JFrame window = new JFrame ("Main Game");
drawPanel = new JPanel(new GridLayout(3, 1))
{
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() / 4;
int height = getHeight() / 11;
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
}
};
// Names namesCall2 = new Names(this);
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
namesCall2 = new Names(Game.this);
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawPanel);
window.setSize(700, 600);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Game();
}
});
}
#Override
public void changename(String name) {
System.out.println("I am clicked");
player1Str = new JLabel(name);
drawPanel.add(player1Str);
drawPanel.revalidate();
}
}
In the names class:
public class Names
{
private JLabel player1Label;
private JTextField player1Input;
private JButton nextButton;
public String nameString1;
public Names(){}
public Names(final Lawl game)
{
final JFrame window = new JFrame("Player 1 username");
JPanel firstPanel = new JPanel(new GridLayout(3,2));
player1Label = new JLabel("Player 1");
player1Input = new JTextField();
nextButton = new JButton("Next");
firstPanel.add(player1Label);
firstPanel.add(player1Input);
firstPanel.add(nextButton);
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
nameString1 = player1Input.getText();
System.out.print(nameString1);
game.changename(nameString1);
// Names2 names2Call = new Names2();
window.dispose();
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(firstPanel);
window.setSize(250, 150);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
How it works??
I created an interface and implemented it to the game class then pass the reference of the interface to the Names class which will then be called when button is clicked..
when it is called game.changename(nameString1);by the button clicked it will then be called on the game class as you could see there is an method from the implemented inteface in the game class that will be called when you click the button..
If you want to chain data dont create a new Main thread to just execute a new Window.. just use the one I did in the code..
replace
public final static JTextField player1Input;
instead of
private JTextField player1Input;

ActionListener And JButtons

So I have the following code, and whenever I press the square tool button it should draw a square in the lefthand corner, but I can't even get the console to print its message. That makes me think that the actionListener is never even responding to my click. Can anybody help?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Game extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private GridPane gridPane;
private DragPanel drag;
public boolean isMouseClicked = false;
public static JMenuBar bar = new JMenuBar();
public int gridY = 1;
public int gridX = 1;
public int x = 0,y = 0;
public Game() {
setLayout(new BorderLayout());
OptionPanel options = new OptionPanel();
options.addActionListener(this);
add(options, BorderLayout.NORTH);
gridPane = new GridPane();
gridPane.setBorder(BorderFactory.createLineBorder(Color.white));
add(gridPane);
drag = new DragPanel();
drag.setBorder(BorderFactory.createLineBorder(Color.white));
drag.setBackground(new Color(100,100,125));
add(drag,BorderLayout.WEST);
}
public static void main(String args[]) {
Game game = new Game();
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setTitle("Game");
frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(game);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equalsIgnoreCase("grid")) {
gridPane.setGridOn(!gridPane.isGridOn());
}
if (e.getActionCommand().equalsIgnoreCase("square")){
gridPane.setSqaureOn(!gridPane.isSquareOn());
}
if (e.getActionCommand().equalsIgnoreCase("vgrid")){
gridPane.setVertOn(!gridPane.isVertOn());
}
}
public class GridPane extends JPanel {
private static final long serialVersionUID = 1L;
private boolean gridOn = false;
private boolean squareOn = false;
private boolean vertOn = false;
public GridPane() {
setBackground(Color.BLACK);
}
public boolean isGridOn() {
return gridOn;
}
public boolean isSquareOn(){
return squareOn;
}
public boolean isVertOn(){
return vertOn;
}
public void setGridOn(boolean value) {
if (value != gridOn) {
this.gridOn = value;
repaint();
}
}
public void setVertOn(boolean value){
if (value != vertOn){
this.vertOn = value;
repaint();
}
}
public void setSqaureOn(boolean value){
if (value != squareOn){
this.squareOn = value;
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Toolkit tk = Toolkit.getDefaultToolkit();
if (gridOn) {
System.out.println("Grid works");
g.setColor(Color.white);
for (int i = 0; i < tk.getScreenSize().height; i += 64){
gridY++;
g.drawLine(0, (64 * gridY), tk.getScreenSize().width,(64 * gridY));
}
}
gridY = -1;
gridX = -1;
if (vertOn){
System.out.println("vert grid works");
g.setColor(Color.white);
for (int ig = 0; ig < tk.getScreenSize().width; ig += 64){
gridX++;
g.drawLine((64 * gridX), 0,(64 * gridX),tk.getScreenSize().height);
}
}
if (squareOn)
{
System.out.println("Square works");
g.setColor(Color.red);
g.fillRect(0,0,64,64);
}
}
}
public class DragPanel extends JPanel{
OptionPanel op = new OptionPanel();
public DragPanel(){
add(op.squareButton);
op.squareButton.setActionCommand("square");
}
public void addActionListener(ActionListener listener){
op.squareButton.addActionListener(listener);
}
}
public class OptionPanel extends JPanel {
public JButton grid;
public JButton vgrid;
public JButton squareButton;
public JTextField squareX;
public JTextField squareY;
public JTextField squareW;
public JTextField squareH;
public Square square = new Square();
public OptionPanel() {
//Sets the stuff for the panel
setBackground(new Color(155,0,255));
setLayout(new GridBagLayout());
//end
//The Show Grid Button Stuff
grid = new JButton("Show Horizontal Grid");
grid.setActionCommand("grid");
//end
//The vertical grid
vgrid = new JButton("Show Vertical Grid");
vgrid.setActionCommand("vgrid");
//end
//The Square tool button stuff
squareButton = new JButton("Sqaure Tool");
//end
squareX = new JTextField(3);
squareY = new JTextField(3);
squareW = new JTextField(3);
squareH = new JTextField(3);
//The gridbagConstraints things
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTH;
//kind of like padding
gbc.weighty = 1;
//sets the positions
gbc.gridx = 0;
gbc.gridy = 0;
//add it
add(grid, gbc);
//changes position for the second button
gbc.gridx = -1;
gbc.gridy = 0;
// adds it
add(vgrid,gbc);
//end
add(squareX,gbc);
add(squareY,gbc);
add(squareW,gbc);
add(squareH,gbc);
}
public void addActionListener(ActionListener listener) {
//adds action listeners
grid.addActionListener(listener);
vgrid.addActionListener(listener);
}
}
DragPanel had a different OptionPanel than the Game. I added the real one as a parameter and used this to qualify the reference, more to illustrate the problem than to suggest a correct usage. As HFOE suggests, re-factor your listeners to be as local as possible, using Action.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Game extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private GridPane gridPane;
private DragPanel drag;
public boolean isMouseClicked = false;
public static JMenuBar bar = new JMenuBar();
public int gridY = 1;
public int gridX = 1;
public int x = 0, y = 0;
public Game() {
setLayout(new BorderLayout());
OptionPanel options = new OptionPanel();
options.addActionListener(this);
add(options, BorderLayout.NORTH);
gridPane = new GridPane();
gridPane.setBorder(BorderFactory.createLineBorder(Color.white));
add(gridPane);
drag = new DragPanel(options);
drag.setBorder(BorderFactory.createLineBorder(Color.white));
drag.setBackground(new Color(100, 100, 125));
add(drag, BorderLayout.WEST);
}
public static void main(String args[]) {
Game game = new Game();
JFrame frame = new JFrame();
frame.setTitle("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e);
if (e.getActionCommand().equalsIgnoreCase("grid")) {
gridPane.setGridOn(!gridPane.isGridOn());
}
if (e.getActionCommand().equalsIgnoreCase("square")) {
gridPane.setSqaureOn(!gridPane.isSquareOn());
}
if (e.getActionCommand().equalsIgnoreCase("vgrid")) {
gridPane.setVertOn(!gridPane.isVertOn());
}
}
public class GridPane extends JPanel {
private static final long serialVersionUID = 1L;
private boolean gridOn = false;
private boolean squareOn = false;
private boolean vertOn = false;
public GridPane() {
setBackground(Color.BLACK);
}
public boolean isGridOn() {
return gridOn;
}
public boolean isSquareOn() {
return squareOn;
}
public boolean isVertOn() {
return vertOn;
}
public void setGridOn(boolean value) {
if (value != gridOn) {
this.gridOn = value;
repaint();
}
}
public void setVertOn(boolean value) {
if (value != vertOn) {
this.vertOn = value;
repaint();
}
}
public void setSqaureOn(boolean value) {
if (value != squareOn) {
this.squareOn = value;
repaint();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Toolkit tk = Toolkit.getDefaultToolkit();
if (gridOn) {
System.out.println("Grid works");
g.setColor(Color.white);
for (int i = 0; i < tk.getScreenSize().height; i += 64) {
gridY++;
g.drawLine(0, (64 * gridY), tk.getScreenSize().width, (64 * gridY));
}
}
gridY = -1;
gridX = -1;
if (vertOn) {
System.out.println("vert grid works");
g.setColor(Color.white);
for (int ig = 0; ig < tk.getScreenSize().width; ig += 64) {
gridX++;
g.drawLine((64 * gridX), 0, (64 * gridX), tk.getScreenSize().height);
}
}
if (squareOn) {
System.out.println("Square works");
g.setColor(Color.red);
g.fillRect(0, 0, 64, 64);
}
}
}
public class DragPanel extends JPanel {
OptionPanel op;
public DragPanel(OptionPanel op) {
this.op = op;
this.add(this.op.squareButton);
this.op.squareButton.setActionCommand("square");
}
public void addActionListener(ActionListener listener) {
System.out.println(listener);
this.op.squareButton.addActionListener(listener);
}
}
private static class Square {
}
private class OptionPanel extends JPanel {
public JButton grid;
public JButton vgrid;
public JButton squareButton;
public JTextField squareX;
public JTextField squareY;
public JTextField squareW;
public JTextField squareH;
public Square square = new Square();
public OptionPanel() {
//Sets the stuff for the panel
setBackground(new Color(155, 0, 255));
setLayout(new GridBagLayout());
//end
//The Show Grid Button Stuff
grid = new JButton("Show Horizontal Grid");
grid.setActionCommand("grid");
//end
//The vertical grid
vgrid = new JButton("Show Vertical Grid");
vgrid.setActionCommand("vgrid");
//end
//The Square tool button stuff
squareButton = new JButton("Sqaure Tool");
//end
squareX = new JTextField(3);
squareY = new JTextField(3);
squareW = new JTextField(3);
squareH = new JTextField(3);
//The gridbagConstraints things
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTH;
//kind of like padding
gbc.weighty = 1;
//sets the positions
gbc.gridx = 0;
gbc.gridy = 0;
//add it
add(grid, gbc);
//changes position for the second button
gbc.gridx = -1;
gbc.gridy = 0;
// adds it
add(vgrid, gbc);
//end
add(squareX, gbc);
add(squareY, gbc);
add(squareW, gbc);
add(squareH, gbc);
}
public void addActionListener(ActionListener listener) {
//adds action listeners
grid.addActionListener(listener);
vgrid.addActionListener(listener);
squareButton.addActionListener(listener);
System.out.println(listener);
}
}
}

Why does Canvas as contentPane not paint opaque components that are added to the JFrame glasspane

Okay I have a Canvas (I am using this because it can implement BufferedStrategy).
I add my Canvas to my JFrame contentPane and than add HUDPanel ( which is a JPanel consisting of 2 other JPanels - with JProgressBars and JLabels - to show health and chakara bars) to my JFrames glassPane.
All of the components on HUD are opaque.
Now when I add the HUDPanel to my JFrames glassPane with a Canvas as its contentPane the 2 JPanels which hold components are not painted opaque:
But if I add a JPanel instead of Canvas to JFrame contentPane all works fine:
Why is this?
and how can I fix it?
Thank you in advance
HUDPanelTest.java
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class HUDPanelTest {
public HUDPanelTest() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new HUDPanelTest();
}
});
}
private void initComponents() {
JFrame frame = new JFrame() {
#Override
public Dimension getPreferredSize() {//testing only
return new Dimension(800, 600);
}
};
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
HUDPanel hudPanel = new HUDPanel();
frame.setGlassPane(hudPanel);
JPanel p = new JPanel() {
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
grphcs.setColor(Color.yellow);
grphcs.fillRect(0, 0, getWidth(), getHeight());
}
};
Canvas c = new Canvas() {
#Override
public void paint(Graphics grphcs) {//for testing ONLY I actually use a BufferStrategy
super.paint(grphcs);
grphcs.setColor(Color.yellow);
grphcs.fillRect(0, 0, getWidth(), getHeight());
}
};
frame.add(c);
//frame.add(p);//this works as expected
frame.pack();
frame.setVisible(true);
hudPanel.setVisible(true);
}
}
HUDPanel.java
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
public class HUDPanel extends JPanel {
HUDPanel.HealthPanel healthPanel;
HUDPanel.ChakaraPanel chakaraPanel;
public HUDPanel() {
super(new BorderLayout(), true);
setOpaque(false);
healthPanel = new HUDPanel.HealthPanel();
chakaraPanel = new HUDPanel.ChakaraPanel();
initComponents();
setHealthPlayer1(100);
setHealthPlayer2(100);
setChakaraPlayer1(0);
setChakaraPlayer2(0);
setLabelTextHealthPlayer1("Player 1 (Health):");
setLabelTextHealthPlayer2("Player 2 (Health):");
setLabelTextChakaraPlayer1("Player 1 (Chakara):");
setLabelTextChakaraPlayer2("Player 2 (Chakara):");
}
private void initComponents() {
add(healthPanel, BorderLayout.NORTH);
add(chakaraPanel, BorderLayout.SOUTH);
}
public void setHealthPlayer1(int health) {
healthPanel.setPlayer1ProgressBarValue(health);
}
public void setHealthPlayer2(int health) {
healthPanel.setPlayer2ProgressBarValue(health);
}
public void setChakaraPlayer1(int chakara) {
chakaraPanel.setPlayer1ProgressBarValue(chakara);
}
public void setChakaraPlayer2(int chakara) {
chakaraPanel.setPlayer2ProgressBarValue(chakara);
}
public void setLabelTextHealthPlayer1(String text) {
healthPanel.setPlayer1LabelText(text);
}
public void setLabelTextHealthPlayer2(String text) {
healthPanel.setPlayer2LabelText(text);
}
public void setLabelTextChakaraPlayer1(String text) {
chakaraPanel.setPlayer1LabelText(text);
}
public void setLabelTextChakaraPlayer2(String text) {
chakaraPanel.setPlayer2LabelText(text);
}
private class HealthPanel extends JPanel {
JProgressBar player1ProgressBar = new JProgressBar();
JProgressBar player2ProgressBar = new JProgressBar();
JLabel player1Label = new JLabel();
JLabel player2Label = new JLabel();
public HealthPanel() {
super(new GridBagLayout(), true);
setOpaque(false);
initComponents();
}
private void initComponents() {
GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.NONE;
gc.anchor = GridBagConstraints.WEST;
gc.insets = new Insets(10, 10, 10, 10);
//or else the anchoring wont work
gc.weightx = 1;
//gc.gridx = 0;//does not seem to make a difference
//gc.gridy = 0;
add(player1Label, gc);
//gc.gridx = 1;
//gc.gridy = 0;
add(player1ProgressBar, gc);
gc.anchor = GridBagConstraints.EAST;
//gc.gridx = 2;
//gc.gridy = 0;
add(player2Label, gc);
//gc.gridx = 3;
//gc.gridy = 0;
add(player2ProgressBar, gc);
}
public void setPlayer1ProgressBarValue(int val) {
player1ProgressBar.setValue(val);
}
public void setPlayer2ProgressBarValue(int val) {
player2ProgressBar.setValue(val);
}
public void setPlayer2LabelText(String text) {
player2Label.setText(text);
}
public void setPlayer1LabelText(String text) {
player1Label.setText(text);
}
}
private class ChakaraPanel extends JPanel {
JProgressBar player1ProgressBar = new JProgressBar();
JProgressBar player2ProgressBar = new JProgressBar();
JLabel player1Label = new JLabel();
JLabel player2Label = new JLabel();
public ChakaraPanel() {
super(new GridBagLayout(), true);
setOpaque(false);
initComponents();
}
private void initComponents() {
GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.NONE;
gc.anchor = GridBagConstraints.WEST;
gc.insets = new Insets(10, 10, 10, 10);
//or else the anchoring wont work
gc.weightx = 1;
gc.weighty = 1;
//gc.gridx = 0;
//gc.gridy = 0;
add(player1Label, gc);
//gc.gridx = 1;
//gc.gridy = 0;
add(player1ProgressBar, gc);
gc.anchor = GridBagConstraints.EAST;
//gc.gridx = 2;
//gc.gridy = 0;
add(player2Label, gc);
//gc.gridx = 3;
//gc.gridy = 0;
add(player2ProgressBar, gc);
}
public void setPlayer1ProgressBarValue(int val) {
player1ProgressBar.setValue(val);
}
public void setPlayer2ProgressBarValue(int val) {
player2ProgressBar.setValue(val);
}
public void setPlayer2LabelText(String text) {
player2Label.setText(text);
}
public void setPlayer1LabelText(String text) {
player1Label.setText(text);
}
}
}
GlassPane is lightweight, then is always behind AWT Canvas,
this is quite common issue for JLayeredPane, GlassPane and Java and 3D, CAD/CAM, Open GL/Cl, these APIs are based on AWT Containers
same issue will be by using JLayer (lightweight container), but there you can to test isLightWe....() for peer from Native OS and/or its resources

Categories