I'm makeing a simple color chooser and i'm trying to update my slider position by textfield value entered by user. It's seems to work but only when programme starts and I'm entering 0 value, slider moves to the 0, and every next try to eneter a new value is not working. Here is my code
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MyFrame extends JFrame implements ChangeListener, ActionListener {
int width;
int height;
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JSlider slider = new JSlider(0,255,100);
JTextField textField = new JTextField();
JLabel label = new JLabel();
public MyFrame(int width, int height) {
super("SliderTest");
this.width = width;
this.height = height;
this.setPreferredSize(new Dimension(width,height));
panel1.setPreferredSize(new Dimension(150,150));
panel2.setPreferredSize(new Dimension(150,300));
slider.setPaintTicks(true);
slider.setMinorTickSpacing(15);
slider.setPaintTrack(true);
slider.setMajorTickSpacing(50);
slider.setPaintLabels(true);
slider.setOrientation(SwingConstants.VERTICAL);
label.setText("R: ");
textField.setText(String.valueOf(slider.getValue()));
slider.setValue(Integer.parseInt(textField.getText()));
textField.addActionListener(this);
slider.addChangeListener(this);
panel1.setBounds(25,25,75,150);
panel2.setBounds(50,50,225,75);
panel1.setBackground(Color.GREEN);
panel2.add(slider);
panel2.add(textField);
this.add(panel1);
this.add(panel2);
}
#Override
public void stateChanged(ChangeEvent e) {
textField.setText("R: " + slider.getValue());
}
#Override
public void actionPerformed(ActionEvent e) {
slider.setValue(Integer.parseInt(textField.getText()));
}
}
Here's a complete RGB Display GUI that uses JSliders and JTextFields.
The "trick" Is to use separate ActionListeners and ChangeListeners. I used three ChangeListeners for the JSliders and three ActionListeners for the JTextFields / JButtons.
Here's the complete runnable code. I made all the classes inner classes so I could post the code as one block.
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.Insets;
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.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class RGBDisplay implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new RGBDisplay());
}
private final ColorModel colorModel;
private final DrawingPanel drawingPanel;
private JSlider redSlider;
private JSlider greenSlider;
private JSlider blueSlider;
private JTextField redField;
private JTextField greenField;
private JTextField blueField;
public RGBDisplay() {
this.colorModel = new ColorModel();
this.colorModel.setColor(128, 128, 128);
this.drawingPanel = new DrawingPanel(colorModel);
}
#Override
public void run() {
JFrame frame = new JFrame("RGB Display");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.add(createSliderPanel(), BorderLayout.AFTER_LAST_LINE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
System.out.println(frame.getSize());
}
private JPanel createSliderPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0.0;
JLabel label = new JLabel("Red");
panel.add(label, gbc);
gbc.gridx++;
gbc.weightx = 1.0;
redSlider = new JSlider(0, 255, colorModel.getRed());
redSlider.addChangeListener(new RedSliderListener(this, colorModel));
redSlider.setMajorTickSpacing(48);
redSlider.setMinorTickSpacing(8);
redSlider.setPaintLabels(true);
redSlider.setPaintTicks(true);
panel.add(redSlider, gbc);
gbc.gridx++;
gbc.weightx = 0.0;
redField = new JTextField(4);
panel.add(redField, gbc);
gbc.gridx++;
gbc.weightx = 0.0;
JButton button = new JButton("Change Red");
button.addActionListener(new RedFieldListener(this, colorModel));
panel.add(button, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.weightx = 0.0;
label = new JLabel("Green");
panel.add(label, gbc);
gbc.gridx++;
gbc.weightx = 1.0;
greenSlider = new JSlider(0, 255, colorModel.getGreen());
greenSlider.addChangeListener(new GreenSliderListener(this, colorModel));
greenSlider.setMajorTickSpacing(48);
greenSlider.setMinorTickSpacing(8);
greenSlider.setPaintLabels(true);
greenSlider.setPaintTicks(true);
panel.add(greenSlider, gbc);
gbc.gridx++;
gbc.weightx = 0.0;
greenField = new JTextField(4);
panel.add(greenField, gbc);
gbc.gridx++;
gbc.weightx = 0.0;
button = new JButton("Change Green");
button.addActionListener(new GreenFieldListener(this, colorModel));
panel.add(button, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.weightx = 0.0;
label = new JLabel("Blue");
panel.add(label, gbc);
gbc.gridx++;
gbc.weightx = 1.0;
blueSlider = new JSlider(0, 255, colorModel.getBlue());
blueSlider.addChangeListener(new BlueSliderListener(this, colorModel));
blueSlider.setMajorTickSpacing(48);
blueSlider.setMinorTickSpacing(8);
blueSlider.setPaintLabels(true);
blueSlider.setPaintTicks(true);
panel.add(blueSlider, gbc);
gbc.gridx++;
gbc.weightx = 0.0;
blueField = new JTextField(4);
panel.add(blueField, gbc);
gbc.gridx++;
gbc.weightx = 0.0;
button = new JButton("Change Blue");
button.addActionListener(new BlueFieldListener(this, colorModel));
panel.add(button, gbc);
updateSliderPanel();
return panel;
}
public void repaint() {
drawingPanel.repaint();
}
public void updateSliderPanel() {
redField.setText(Integer.toString(colorModel.getRed()));
greenField.setText(Integer.toString(colorModel.getGreen()));
blueField.setText(Integer.toString(colorModel.getBlue()));
}
public JSlider getRedSlider() {
return redSlider;
}
public JSlider getGreenSlider() {
return greenSlider;
}
public JSlider getBlueSlider() {
return blueSlider;
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final ColorModel colorModel;
public DrawingPanel(ColorModel colorModel) {
this.colorModel = colorModel;
this.setPreferredSize(new Dimension(300, 200));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(colorModel.getColor());
g.fillRect(0, 0, getWidth(), getHeight());
}
}
public class RedFieldListener implements ActionListener {
private final RGBDisplay frame;
private final ColorModel model;
public RedFieldListener(RGBDisplay frame, ColorModel model) {
this.frame = frame;
this.model = model;
}
#Override
public void actionPerformed(ActionEvent event) {
try {
int red = Integer.valueOf(redField.getText());
if (red >= 0 && red <= 255) {
int green = model.getGreen();
int blue = model.getBlue();
model.setColor(red, green, blue);
frame.getRedSlider().setValue(red);
frame.repaint();
}
} catch (NumberFormatException e) {
return;
}
}
}
public class GreenFieldListener implements ActionListener {
private final RGBDisplay frame;
private final ColorModel model;
public GreenFieldListener(RGBDisplay frame, ColorModel model) {
this.frame = frame;
this.model = model;
}
#Override
public void actionPerformed(ActionEvent event) {
try {
int green = Integer.valueOf(greenField.getText());
if (green >= 0 && green <= 255) {
int red = model.getRed();
int blue = model.getBlue();
model.setColor(red, green, blue);
frame.getGreenSlider().setValue(green);
frame.repaint();
}
} catch (NumberFormatException e) {
return;
}
}
}
public class BlueFieldListener implements ActionListener {
private final RGBDisplay frame;
private final ColorModel model;
public BlueFieldListener(RGBDisplay frame, ColorModel model) {
this.frame = frame;
this.model = model;
}
#Override
public void actionPerformed(ActionEvent event) {
try {
int blue = Integer.valueOf(blueField.getText());
if (blue >= 0 && blue <= 255) {
int green = model.getGreen();
int red = model.getRed();
model.setColor(red, green, blue);
frame.getBlueSlider().setValue(blue);
frame.repaint();
}
} catch (NumberFormatException e) {
return;
}
}
}
public class RedSliderListener implements ChangeListener {
private final RGBDisplay frame;
private final ColorModel model;
public RedSliderListener(RGBDisplay frame, ColorModel model) {
this.frame = frame;
this.model = model;
}
#Override
public void stateChanged(ChangeEvent event) {
JSlider source = (JSlider) event.getSource();
// if (!source.getValueIsAdjusting()) {
int red = source.getValue();
int green = model.getGreen();
int blue = model.getBlue();
model.setColor(red, green, blue);
frame.updateSliderPanel();
frame.repaint();
// }
}
}
public class GreenSliderListener implements ChangeListener {
private final RGBDisplay frame;
private final ColorModel model;
public GreenSliderListener(RGBDisplay frame, ColorModel model) {
this.frame = frame;
this.model = model;
}
#Override
public void stateChanged(ChangeEvent event) {
JSlider source = (JSlider) event.getSource();
// if (!source.getValueIsAdjusting()) {
int red = model.getRed();
int green = source.getValue();
int blue = model.getBlue();
model.setColor(red, green, blue);
frame.updateSliderPanel();
frame.repaint();
// }
}
}
public class BlueSliderListener implements ChangeListener {
private final RGBDisplay frame;
private final ColorModel model;
public BlueSliderListener(RGBDisplay frame, ColorModel model) {
this.frame = frame;
this.model = model;
}
#Override
public void stateChanged(ChangeEvent event) {
JSlider source = (JSlider) event.getSource();
// if (!source.getValueIsAdjusting()) {
int red = model.getRed();
int green = model.getGreen();
int blue = source.getValue();
model.setColor(red, green, blue);
frame.updateSliderPanel();
frame.repaint();
// }
}
}
public class ColorModel {
private int red;
private int green;
private int blue;
public void setColor(int red, int green, int blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
public Color getColor() {
return new Color(red, green, blue);
}
public int getRed() {
return red;
}
public int getGreen() {
return green;
}
public int getBlue() {
return blue;
}
}
}
Related
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
I have one main JFrame with one button, when i press this button, one JDialog open with some objects from a Json File. For each object i have a delete button. Everything works great but to see all objects except this one i deleted, i have to close the JDialog and open it again. Is there any way i can refresh JDialog? I found one "solution" witch is to dispose the JDialog and make new one and then set the new one visible, but its not really what i need. I need to see the new results immediately after the button press.The JFrame myFrame bellow is the main Frame dont care about it("i guess").
this is my Dialog:
public class MyFavoriteCoctails extends JDialog {
public MyFavoriteCoctails(JFrame myFrame) {
this.myFrame = myFrame;
setLocationRelativeTo(myFrame);
maker();
}
private void maker() {
setModal(true);
setTitle("My Favortie Cocktails");
setResizable(false);
setLayout(new BorderLayout());
JPanel panelOnTop = new JPanel(new BorderLayout());
JLabel favCocktailLabel = new JLabel("My Favorite Cocktails");
favCocktailLabel.setFont(new Font("Sans Serif", Font.PLAIN, 150));
favCocktailLabel.setForeground(Color.red);
panelOnTop.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, Color.red));
panelOnTop.add(favCocktailLabel, BorderLayout.CENTER);
panelOnTop.setBackground(Color.white);
this.add(panelOnTop, BorderLayout.NORTH);
JPanel panelForCocktails = new JPanel();
this.add(panelForCocktails, BorderLayout.CENTER);
List<Coctail> list = SingleObject.getfavCoctailList();
int row;
if ((list.size() % 5) != 0) {
row = list.size() / 5 + 1;
} else {
row = list.size() / 5;
}
panelForCocktails.setLayout(new GridLayout(row, 5));
this.add(panelForCocktails, BorderLayout.CENTER);
for (int i = 0; i < list.size(); i++) {
panelForCocktails.add(new CocktailJPanelForFavorites(list.get(i).getId(), list.get(i).getImg(),
list.get(i).getName(), list.get(i), this, myFrame));
}
pack();
}
JFrame myFrame;
}
This is my JPanel witch it has some details from json file in every panel.:
public class CocktailJPanelForFavorites extends JPanel {
public CocktailJPanelForFavorites(String id, String img, String name, Coctail coctail, JDialog dialog, JFrame myFrame) {
this.coctail = coctail;
this.myFrame=myFrame;
this.id = id;
this.name = name;
this.img = img;
this.dialog=dialog;
maker();
}
#SuppressWarnings({ "rawtypes", "unchecked" })
public void maker() {
setLayout(new BorderLayout(1, 1));
this.setBackground(Color.white);
this.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.black));
JLabel nameLabel = new JLabel(name, SwingConstants.CENTER);
nameLabel.setFont(new Font("Sans Serif", Font.BOLD, 18));
this.add(nameLabel, BorderLayout.NORTH);
JButton deleteFavorite = new JButton("X");
JComboBox comboBox = new JComboBox(Favouritetype.values());
comboBox.setRenderer(new MyComboBoxRenderer("ΚΑΤΗΓΟΡΙΑ"));
comboBox.setSelectedIndex(-1);
;
try {
URL url = new URL(img);
BufferedImage c = ImageIO.read(url);
ImageIcon imageIcon = new ImageIcon(c); // load the image to a imageIcon
Image image = imageIcon.getImage(); // transform it
Image newimg = image.getScaledInstance(200, 200, java.awt.Image.SCALE_SMOOTH); // scale
imageIcon = new ImageIcon(newimg); // transform it back
JLabel jp = new JLabel(imageIcon, JLabel.CENTER);
jp.setBorder(BorderFactory.createMatteBorder(10, 10, 10, 10, Color.white));
jp.addMouseListener(new MouseAdapter(id));
jp.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
add(jp, BorderLayout.CENTER);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JPanel deleteAndCombo = new JPanel(new GridLayout(1, 2));
deleteAndCombo.add(deleteFavorite);
deleteAndCombo.add(comboBox);
add(deleteAndCombo, BorderLayout.SOUTH);
DeleteFavorite act = new DeleteFavorite(coctail, deleteFavorite, dialog, this, myFrame);
deleteFavorite.addActionListener(act);
}
String id, name, img;
Coctail coctail;
JDialog dialog;
JFrame myFrame;
}
And this is my Action Listener of my Delete Button(is the button with the "X" inside):
public class DeleteFavorite implements ActionListener {
public DeleteFavorite(Coctail coctail, JButton deleteFavorite, JDialog dialog, JPanel cockPane, JFrame myFrame) {
this.deleteFavorite = deleteFavorite;
this.coctail = coctail;
this.myFrame=myFrame;
this.dialog=dialog;
this.cockPane=cockPane;
}
#Override
public void actionPerformed(ActionEvent e) {
SingleObject obj = SingleObject.getInstance();
List<Coctail> list = SingleObject.getfavCoctailList();
List<Coctail> favcoctailList = list;
int len = favcoctailList.size();
if (favcoctailList != null) {
for (int i = 0; i < len; i++) {
if ((favcoctailList.get(i).getId().toString().trim().equals(coctail.getId().toString().trim()))) {
favcoctailList.remove(i);
break;
}
}
}
System.out.println(favcoctailList);
obj.make(favcoctailList);
dialog.dispose();
MyFavoriteCoctails dialog1 = new MyFavoriteCoctails(myFrame);
dialog1.setVisible(true);
}
JButton deleteFavorite;
Coctail coctail;
JDialog dialog;
JPanel cockPane;
JFrame myFrame;
}
The basic answer to your question is, your dialog/panel needs some way to get the "next" cocktail. Then all you need to do is update the details of the new cocktail.
The best way to achieve this is to have some kind of "manager", which managers all the cocktails within your system. Before deleting the current cocktail, you'd ascertain the current index of the cocktail within the list, remove the cocktail and then present the cocktail which now occupies this position. You could also do this with some kind of Iterator, but where's the fun in that.
Since I don't have access to all you code (and your UI code is a bit of mess), I devised my own example.
Below is the "detail" pane, which presents details about a give cocktail and allows the user to remove it.
public class CocktailDetailPane extends JPanel {
private JLabel imageLabel;
private JLabel nameLabel;
private CocktailManager cocktailManager;
private Cocktail cocktail;
public CocktailDetailPane(Cocktail cocktail, CocktailManager manager) {
this.cocktailManager = manager;
setLayout(new BorderLayout());
imageLabel = new JLabel();
nameLabel = new JLabel();
JPanel contentPane = new JPanel(new GridBagLayout());
contentPane.setBorder(new EmptyBorder(16, 16, 16, 16));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridheight = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.PAGE_START;
gbc.insets = new Insets(4, 4, 4, 4);
contentPane.add(imageLabel, gbc);
gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.LINE_START;
contentPane.add(nameLabel, gbc);
gbc.gridy++;
contentPane.add(new JLabel("Drink it fast, drink it often"), gbc);
add(contentPane);
setCocktail(cocktail);
JPanel actionPane = new JPanel(new GridBagLayout());
JButton deleteButton = new JButton("Delete");
deleteButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CocktailManager manager = getCocktailManager();
List<Cocktail> cocktails = manager.getCocktails();
Cocktail cocktail = getCocktail();
int index = cocktails.indexOf(cocktail);
manager.remove(cocktail);
if (cocktails.isEmpty()) {
JOptionPane.showMessageDialog(CocktailDetailPane.this, "No more cocktails for you", "Empty", JOptionPane.ERROR_MESSAGE);
SwingUtilities.windowForComponent(CocktailDetailPane.this).dispose();
} else {
if (index >= cocktails.size()) {
index = 0;
}
setCocktail(cocktails.get(index));
}
}
});
actionPane.add(deleteButton);
add(actionPane, BorderLayout.SOUTH);
}
protected void setCocktail(Cocktail cocktail) {
imageLabel.setIcon(new ImageIcon(cocktail.getImage()));
nameLabel.setText(cocktail.getName());
this.cocktail = cocktail;
}
public CocktailManager getCocktailManager() {
return cocktailManager;
}
public Cocktail getCocktail() {
return cocktail;
}
}
You will note that I've passed an instance of CocktailManager to the details pane as well as the instance of the Cocktail to be initially presented.
If the current Cocktail is deleted, the next Cocktail is presented (made current) and so on until you have no more cocktails left.
Some of this could have been decoupled through the use of an observer pattern on the CocktailManager itself (so when a cocktail was added or removed, interested parties could react to it, but I took that concept as been out of context for the question).
Runnable example...
Because out of context code can be hard to follow, I've provided a runnable example...
This example makes use of dependency injection (for reference, reference, reference, reference) and "coding to interface" (for reference and reference)
This will allow you to define you own "contract" for the CocktailManager and define your own implementations based on your needs, but the core concept should continue to work
You may also want to take a look at How to Use Lists
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.AbstractListModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
CocktailManager manager = new DefaultCocktailManager();
JFrame frame = new JFrame();
frame.add(new CocktailListPane(manager));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface Cocktail {
public String getId();
public Image getImage();
public String getName();
}
public interface CocktailManager {
public List<Cocktail> getCocktails();
public void add(Cocktail coctail);
public void remove(Cocktail coctail);
}
public class CocktailListPane extends JPanel {
private JList<Cocktail> list;
private CocktailManager manager;
public CocktailListPane(CocktailManager manager) {
this.manager = manager;
list = new JList<>(new CocktailListModel(manager));
list.setCellRenderer(new CocktailListCellRenderer());
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(2);
setLayout(new BorderLayout());
add(new JLabel("My Favorite Cocktails"), BorderLayout.NORTH);
add(new JScrollPane(list));
list.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() != 2) {
return;
}
int index = list.locationToIndex(e.getPoint());
if (index < 0) {
return;
}
Cocktail cocktail = list.getModel().getElementAt(index);
JDialog dialog = new JDialog(SwingUtilities.windowForComponent(CocktailListPane.this));
dialog.setTitle("All your cocktail belong to us");
dialog.setModal(true);
dialog.add(new CocktailDetailPane(cocktail, getCocktailManager()));
dialog.pack();
dialog.setLocationRelativeTo(CocktailListPane.this);
dialog.setVisible(true);
list.setModel(new CocktailListModel(getCocktailManager()));
}
});
}
public CocktailManager getCocktailManager() {
return manager;
}
protected class CocktailListModel extends AbstractListModel<Cocktail> {
private CocktailManager manager;
public CocktailListModel(CocktailManager manager) {
this.manager = manager;
}
#Override
public int getSize() {
return manager.getCocktails().size();
}
#Override
public Cocktail getElementAt(int index) {
return manager.getCocktails().get(index);
}
}
protected class CocktailListCellRenderer extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof Cocktail) {
Cocktail cocktail = (Cocktail) value;
value = cocktail.getName();
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
setIcon(new ImageIcon(cocktail.getImage()));
return this;
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
}
}
public class CocktailDetailPane extends JPanel {
private JLabel imageLabel;
private JLabel nameLabel;
private CocktailManager cocktailManager;
private Cocktail cocktail;
public CocktailDetailPane(Cocktail cocktail, CocktailManager manager) {
this.cocktailManager = manager;
setLayout(new BorderLayout());
imageLabel = new JLabel();
nameLabel = new JLabel();
JPanel contentPane = new JPanel(new GridBagLayout());
contentPane.setBorder(new EmptyBorder(16, 16, 16, 16));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridheight = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.PAGE_START;
gbc.insets = new Insets(4, 4, 4, 4);
contentPane.add(imageLabel, gbc);
gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.LINE_START;
contentPane.add(nameLabel, gbc);
gbc.gridy++;
contentPane.add(new JLabel("Drink it fast, drink it often"), gbc);
add(contentPane);
setCocktail(cocktail);
JPanel actionPane = new JPanel(new GridBagLayout());
JButton deleteButton = new JButton("Delete");
deleteButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CocktailManager manager = getCocktailManager();
List<Cocktail> cocktails = manager.getCocktails();
Cocktail cocktail = getCocktail();
int index = cocktails.indexOf(cocktail);
manager.remove(cocktail);
if (cocktails.isEmpty()) {
JOptionPane.showMessageDialog(CocktailDetailPane.this, "No more cocktails for you", "Empty", JOptionPane.ERROR_MESSAGE);
SwingUtilities.windowForComponent(CocktailDetailPane.this).dispose();
} else {
if (index >= cocktails.size()) {
index = 0;
}
setCocktail(cocktails.get(index));
}
}
});
actionPane.add(deleteButton);
add(actionPane, BorderLayout.SOUTH);
}
protected void setCocktail(Cocktail cocktail) {
imageLabel.setIcon(new ImageIcon(cocktail.getImage()));
nameLabel.setText(cocktail.getName());
this.cocktail = cocktail;
}
public CocktailManager getCocktailManager() {
return cocktailManager;
}
public Cocktail getCocktail() {
return cocktail;
}
}
public class DefaultCocktailManager implements CocktailManager {
private List<Cocktail> cocktails;
private List<Cocktail> nonmutableCocktails;
public DefaultCocktailManager() {
cocktails = new ArrayList<>(4);
nonmutableCocktails = Collections.unmodifiableList(cocktails);
for (int index = 1; index < 5; index++) {
Image image = null;
try {
image = ImageIO.read(getClass().getResource("/images/ct0" + index + ".png")).getScaledInstance(-1, 50, Image.SCALE_SMOOTH);
} catch (IOException ex) {
ex.printStackTrace();
}
Cocktail cocktail = new DefaultCocktail(Integer.toString(index), image, "Cocktail " + index);
cocktails.add(cocktail);
}
}
#Override
public List<Cocktail> getCocktails() {
return nonmutableCocktails;
}
#Override
public void add(Cocktail cocktail) {
cocktails.add(cocktail);
}
#Override
public void remove(Cocktail cocktail) {
cocktails.remove(cocktail);
}
}
public class DefaultCocktail implements Cocktail {
private String id;
private Image image;
private String name;
public DefaultCocktail(String id, Image image, String name) {
this.id = id;
this.image = image;
this.name = name;
}
#Override
public String getId() {
return id;
}
#Override
public Image getImage() {
return image;
}
#Override
public String getName() {
return name;
}
}
}
nb: BYO your own images
nbb: No cocktails were consumed in the creation of this example, although it probably would have improved the quality 😉
I have been trying to figure this out for 6 hours now. I finally got the colors to change as desired, but I just want to keep the default color for the arrow of the combobox.
Here is the code...
Note: Edited code to compile without background shown in pictures...
import org.apache.commons.lang3.ArrayUtils;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.metal.MetalComboBoxButton;
public class TestGui extends JFrame {
private final String[] guiCharSelDefault = {"--- Select Character ---"};
private final String[] characters = {"SelectedTextOne", "SelectedTextTwo", "SelectedTextThree", "SelectedTextFour"};
private final String[] guiCharSel = (String[]) ArrayUtils.addAll(guiCharSelDefault, characters);
private JComboBox charCombo = createStandardCombo(guiCharSel);
private JPanel topFrame = createTopFrame();
private JScrollPane topFrameScroll = createTopScrollPane();
private JPanel centerFrame = createCenterFrame();
//**************************************************************************************
// Constructor
TestGui(){
add(topFrameScroll, BorderLayout.NORTH);
add(centerFrame, BorderLayout.CENTER);
setSize(800,600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
//**************************************************************************************
// Support Methods
private static GridBagConstraints setGbc(int gridx, int gridy, int gridWidth, int gridHeight, int ipadx, int ipady, String anchorLocation, double weightx, double weighty, Insets insets){
GridBagConstraints gbc = new GridBagConstraints();
if (anchorLocation.toUpperCase().equals("NORTHWEST")){
gbc.anchor = GridBagConstraints.NORTHWEST;
} else if (anchorLocation.toUpperCase().equals("NORTH")){
gbc.anchor = GridBagConstraints.NORTH;
} else if (anchorLocation.toUpperCase().equals("NORTHEAST")){
gbc.anchor = GridBagConstraints.NORTHEAST;
} else if (anchorLocation.toUpperCase().equals("WEST")){
gbc.anchor = GridBagConstraints.WEST;
} else if (anchorLocation.toUpperCase().equals("EAST")){
gbc.anchor = GridBagConstraints.EAST;
} else if (anchorLocation.toUpperCase().equals("SOUTHWEST")){
gbc.anchor = GridBagConstraints.SOUTHWEST;
} else if (anchorLocation.toUpperCase().equals("SOUTH")){
gbc.anchor = GridBagConstraints.SOUTH;
} else if (anchorLocation.toUpperCase().equals("SOUTHEAST")){
gbc.anchor = GridBagConstraints.SOUTHEAST;
} else {
gbc.anchor = GridBagConstraints.CENTER;
}
gbc.gridx = gridx; // column
gbc.gridy = gridy; // row
gbc.gridwidth = gridWidth; // number of columns
gbc.gridheight = gridHeight; // number of rows
gbc.ipadx = ipadx; // width of object
gbc.ipady = ipady; // height of object
gbc.weightx = weightx; // shifts rows to side of set anchor
gbc.weighty = weighty; // shifts columns to side of set anchor
gbc.insets = insets; // placement inside cell
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.fill = GridBagConstraints.VERTICAL;
return gbc;
}
private Insets setInsets(int top, int left, int bottom, int right){
Insets insets = new Insets(top,left,bottom,right);
return insets;
}
//**************************************************************************************
// Interactive Object Methods
private JComboBox createStandardCombo(String[] defaultValues){
JComboBox comboBox = new JComboBox(defaultValues);
ComboBoxRenderer cbr = new ComboBoxRenderer();
DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
dlcr.setHorizontalTextPosition(SwingConstants.CENTER);
comboBox.setRenderer(cbr);
comboBox.setPrototypeDisplayValue("X" + guiCharSelDefault + "X");
return comboBox;
}
//**************************************************************************************
// Object Action Methods
private void setComboBoxColorBackgroundWithMetalArrow(Color color){
int componentCount = charCombo.getComponentCount();
for (int i = 0; i < componentCount; i++) {
Component component = charCombo.getComponent(i);
if (component instanceof MetalComboBoxButton) {
MetalComboBoxButton metalComboBoxButton =
(MetalComboBoxButton) component;
Icon comboIcon = metalComboBoxButton.getComboIcon();
BufferedImage bufferedImage =
new BufferedImage(
comboIcon.getIconWidth(),
comboIcon.getIconHeight(),
BufferedImage.TYPE_INT_ARGB);
comboIcon.paintIcon(
metalComboBoxButton, bufferedImage.getGraphics(), 0, 0);
}
}
}
private void setCharComboAction(){
charCombo.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
String charName = ((JComboBox)(e.getSource())).getSelectedItem().toString();
if (!(charName.equals(guiCharSelDefault[0]))){
DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
DefaultComboBoxModel model = new DefaultComboBoxModel(characters);
model.setSelectedItem(charName);
charCombo.setModel(model);
if (charName.equals("SelectedTextOne")){
//charCombo.getEditor().getEditorComponent().setBackground(Color.GREEN);
charCombo.setBackground(Color.GREEN);
} else if (charName.equals("SelectedTextTwo")){
charCombo.setBackground(Color.RED);
} else {
charCombo.setBackground(dlcr.getBackground());
}
}
}
}
);
}
//**************************************************************************************
// Panel Methods
private JPanel createTopFrame(){
JPanel pnl = new JPanel();
pnl.setLayout(new GridBagLayout());
setCharComboAction();
pnl.add(charCombo, setGbc(0,0, 1,1, 0,0, "WEST", 0, 0, setInsets(0, 10, 0, 0)));
JButton button = new JButton("Button");
pnl.add(button, setGbc(0,1, 1,1, 0,0, "WEST", 0, 0, setInsets(0, 10, 0, 0)));
pnl.setOpaque(false);
return pnl;
}
private JScrollPane createTopScrollPane(){
JScrollPane scrollPane = new JScrollPane();
Border raisedBevel = BorderFactory.createRaisedBevelBorder();
Border lineBorder = BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(224,224,224));
Border loweredBevel = BorderFactory.createLoweredBevelBorder();
Border compoundSetup = BorderFactory.createCompoundBorder(raisedBevel, lineBorder);
Border compoundFinal = BorderFactory.createCompoundBorder(compoundSetup, loweredBevel);
scrollPane.setBorder(compoundFinal);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
scrollPane.getViewport().setView(topFrame);
return scrollPane;
}
private JPanel createCenterFrame() {
JPanel pnl = new JPanel();
Border raisedBevel = BorderFactory.createRaisedBevelBorder();
Color lineColor = new Color(224, 224, 224);
Border lineBorder = BorderFactory.createMatteBorder(5, 5, 5, 5, lineColor);
Border loweredBevel = BorderFactory.createLoweredBevelBorder();
Border compoundSetup = BorderFactory.createCompoundBorder(raisedBevel, lineBorder);
Border compoundFinal = BorderFactory.createCompoundBorder(compoundSetup, loweredBevel);
TitledBorder topFrameTitle = BorderFactory.createTitledBorder(compoundFinal, "Stuff");
topFrameTitle.setTitleJustification(TitledBorder.CENTER);
pnl.setBorder(topFrameTitle);
pnl.setLayout(new GridBagLayout());
pnl.setOpaque(false);
return pnl;
}
//**************************************************************************************
public static void main(String[] args) {
new TestGui();
}
}
Note: I am using a custom renderer. Here is the code for that...
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class ComboBoxRenderer extends JLabel implements ListCellRenderer
{
private Color selectionBackgroundColor;
private DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
// Constructor
public ComboBoxRenderer()
{
setOpaque(true);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
selectionBackgroundColor = this.dlcr.getBackground(); // Have to set a color, else a compiler error will occur
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
// Set the list background color to default color (default color will show once selection is made)
setBackground(list.getBackground());
Color mouseHoverHighlight = Color.LIGHT_GRAY;
setText((String)value);
// Check which item is selected
if(isSelected)
{
// Set background color of the item your cursor is hovering over to the original background color
setBackground(mouseHoverHighlight);
}
else
{
// Set background to specific color depending on text value
String selectedTextInDropdownList = getText();
if (selectedTextInDropdownList.equals("SelectedTextOne")) {
setBackground(Color.GREEN);
} else if (selectedTextInDropdownList.equals("SelectedTextTwo")) {
setBackground(Color.RED);
} else {
setBackground(this.dlcr.getBackground());
}
}
String selectedText = getText();
if (selectedText.equals("SelectedTextOne")){
list.setSelectionBackground(Color.GREEN);
} else if (selectedText.equals("SelectedTextTwo")){
list.setSelectionBackground(Color.RED);
} else {
list.setSelectionBackground(this.dlcr.getBackground());
}
return this;
}
}
Steps to reproduce error:
Expected Result
Your approach is correct, but BasicComboBoxUI put a spoke in your wheel. Fortunately I have a trick for you, which helps to avoid this problem.
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
#SuppressWarnings("unchecked")
public class ComboBgTest {
private static final String[] VALUES = {"One", "Two", "Three"};
#SuppressWarnings("serial")
public static void main(String[] args) {
JComboBox<String> cb = new JComboBox<>(VALUES);
cb.setSelectedItem(null);
cb.setRenderer(new BasicComboBoxRenderer() {
boolean ignoreBG = true;
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
ignoreBG = false;
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (index == -1) { // check whether we are render the item shown at top
if (VALUES[0].equals(value)) {
c.setBackground(Color.RED);
} else if (VALUES[1].equals(value)) {
setBackground(Color.GREEN);
} else if (VALUES[2].equals(value)) {
setBackground(Color.BLUE);
}
}
ignoreBG = true;
return this;
}
#Override
public void setBackground(Color bg) {
// ignore all BG which is set from outside.
if (!ignoreBG) {
super.setBackground(bg);
}
}
});
JFrame frm = new JFrame("Combo test");
frm.add(cb);
frm.pack();
frm.setLocationRelativeTo(null);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setVisible(true);
}
}
P.S. The same approach works also for font and foregorund.
What's happening is, the JComboBox is changing the background color of the selected item AFTER it's been selected (and rendered) from the list. One possible solution is to simply circumvent this by having a "override" color which is always returned, regardless of what is set, for example...
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestGui extends JFrame {
private final String[] guiCharSel = {"--- Select Character ---", "SelectedTextOne", "SelectedTextTwo", "SelectedTextThree", "SelectedTextFour"};
public static void main(String[] args) {
new TestGui();
}
public TestGui() throws HeadlessException {
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JComboBox box = new JComboBox(guiCharSel);
box.setRenderer(new ComboBoxRenderer());
JTextField field = new JTextField(10);
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
frame.add(box, gbc);
frame.add(field, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
class ComboBoxRenderer extends DefaultListCellRenderer {
private Color overrideBackground;
private Color mouseHoverHighlight = Color.LIGHT_GRAY;
// Constructor
public ComboBoxRenderer() {
setOpaque(true);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
}
#Override
public void setOpaque(boolean isOpaque) {
System.out.println("setOpaque " + isOpaque);
//NOOP
}
#Override
public boolean isOpaque() {
return true;
}
#Override
public void setBackground(Color bg) {
System.out.println(">> Background = " + bg);
super.setBackground(bg); //To change body of generated methods, choose Tools | Templates.
}
#Override
public Color getBackground() {
return overrideBackground == null ? super.getBackground() : overrideBackground;
}
#Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
// Set the list background color to default color (default color will show once selection is made)
overrideBackground = null;
setText((String) value);
// Check which item is selected
System.out.println(value + "; isSelected = " + isSelected + "; cellHasFocus = " + cellHasFocus);
if (isSelected) {
// Set background color of the item your cursor is hovering over to the original background color
setBackground(mouseHoverHighlight);
} else {
// Set background to specific color depending on text value
String selectedTextInDropdownList = getText();
if (selectedTextInDropdownList.equals("SelectedTextOne")) {
System.out.println(">> Green");
overrideBackground = Color.GREEN;
} else if (selectedTextInDropdownList.equals("SelectedTextTwo")) {
System.out.println(">> Red");
overrideBackground = Color.RED;
} else {
overrideBackground = null;
}
}
return this;
}
}
}
This will only show up AFTER the combobox loses focus, as the item is been rendered as "selected". You could muck around with change the selection background as well, but I couldn't find any decent combination of states where it was simple to do
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);
}
}
}
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