First Time three random images shown on Jframe from three diffrent arrays.
even MouseClicked Method triggered but images does not refresh in Frame.
I want to refresh three random images each time i click on Frame.
Please help
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.*;
public class Cards extends JFrame implements MouseListener {
public static void main(String[] args) {
JFrame frame = new Cards();
frame.setTitle("Cards");
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
new Cards();
}
public Cards() {
this.getContentPane().addMouseListener(this);
cards1();
cards2();
cards3();
}
public void cards1() {
ImageIcon[] images = new ImageIcon[10];
for (int i = 1; i < images.length; i++) {
images[i] = new ImageIcon("Drawables//Images//" + i + ".png");
}
int[] threeRandoms = new int[1];
Random ran = new Random();
for (int i = 0; i < threeRandoms.length; i++) {
threeRandoms[i] = ran.nextInt(10);
}
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(images[threeRandoms[0]]));
}
public void cards2() {
ImageIcon[] images = new ImageIcon[10];
for (int i = 1; i < images.length; i++) {
images[i] = new ImageIcon("Drawables//Images1//" + i + ".png");
}
int[] threeRandoms = new int[1];
Random ran = new Random();
for (int i = 0; i < threeRandoms.length; i++) {
threeRandoms[i] = ran.nextInt(10);
}
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(images[threeRandoms[0]]));
}
public void cards3() {
// this.getContentPane().addMouseListener(this);
ImageIcon[] images = new ImageIcon[10];
for (int i = 1; i < images.length; i++) {
images[i] = new ImageIcon("Drawables//Images2//" + i + ".png");
}
int[] threeRandoms = new int[1];
Random ran = new Random();
for (int i = 0; i < threeRandoms.length; i++) {
threeRandoms[i] = ran.nextInt(10);
}
// Labels with gridLayout
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(images[threeRandoms[0]]));
}
public void mouseClicked(MouseEvent e) {
System.out.println("The frame was clicked.");
new Cards();
}
public void mouseEntered(MouseEvent e) {
System.out.println("The mouse entered the frame.");
}
public void mouseExited(MouseEvent e) {
System.out.println("The mouse exited the frame.");
}
public void mousePressed(MouseEvent e) {
System.out.println("The left mouse button was pressed.");
}
public void mouseReleased(MouseEvent e) {
System.out.println("The left mouse button was released.");
}
}
I'm sorry, but I'm confused by your code. For one thing your cards1(), cards2() and cards3() methods look to be all the very same, and if so, why 3 different methods? Why not just one method? In those methods you appear to be trying to add JLabels repeatedly. Are you trying to add many many JLabels to the GUI? Or are you simply trying to display 3 images that change randomly on mouse action?
I would recommend structuring things a bit differently:
If possible, read all necessary images in once in your class's constructor, put the images into ImageIcons and then add them to an ArrayList or several ArrayLists if need be.
Don't add new JLabels each time a mouseClick occurs.
Create a JPanel give it a GridLayout and in your class constructor add to it three JLabels that are either instance fields or in an array or ArrayList.
Add this JPanel to your JFrame.
Add a MouseListener to each JLabel
in that MouseListener's mousePressed(MouseEvent e) method (not mouseClicked) randomize your number and use that number to call setIcon(...) on the JLabel source, obtained by calling getSource() on your MouseEvent parameter.
For example:
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class RandomImages extends JPanel {
private static final int LABEL_COUNT = 3;
private Random random = new Random();
public RandomImages() {
setLayout(new GridLayout(1, 3));
for (int i = 0; i < LABEL_COUNT; i++) {
final List<Icon> iconList = new ArrayList<>();
// TODO: get images for the ith list
// and fill iconList with ImageIcons from the first grouping
// create JLabel and give it the first Icon from the List above
final JLabel label = new JLabel(iconList.get(0));
label.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
// get random number from random object using iconList.size()
// get random Icon from list
// set label's icon via setIcon(...)
}
});
// add to GUI
add(label);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("RandomImages");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new RandomImages());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Concrete example 2:
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class RandomChessMen extends JPanel {
// for this example I get a sprite sheet that holds several sprite images in it
// the images can be found here: http://stackoverflow.com/questions/19209650
private static final String IMAGE_PATH = "http://i.stack.imgur.com/memI0.png";
private static final int LABEL_COUNT = 2;
private static final int ICON_COLUMNS = 6;
private Random random = new Random();
public RandomChessMen() throws IOException {
URL url = new URL(IMAGE_PATH);
BufferedImage largeImg = ImageIO.read(url);
setLayout(new GridLayout(1, 0));
// break down large image into its constituent sprites and place into ArrayList<Icon>
int w = largeImg.getWidth() / ICON_COLUMNS;
int h = largeImg.getHeight() / LABEL_COUNT;
for (int i = 0; i < LABEL_COUNT; i++) {
final List<Icon> iconList = new ArrayList<>();
int y = (i * largeImg.getHeight()) / LABEL_COUNT;
// get 6 icons out of large image
for (int j = 0; j < ICON_COLUMNS; j++) {
int x = (j * largeImg.getWidth()) / ICON_COLUMNS;
// get subImage
BufferedImage subImg = largeImg.getSubimage(x, y, w, h);
// create ImageIcon and add to list
iconList.add(new ImageIcon(subImg));
}
// create JLabel
final JLabel label = new JLabel("", SwingConstants.CENTER);
int eb = 40;
label.setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
// get random index for iconList
int randomIndex = random.nextInt(iconList.size());
Icon icon = iconList.get(randomIndex); // use index to get random Icon
label.setIcon(icon); // set label's icon
label.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
Icon secondIcon = label.getIcon();
// so we don't repeat icons
while (label.getIcon() == secondIcon) {
int randomIndex = random.nextInt(iconList.size());
secondIcon = iconList.get(randomIndex);
}
label.setIcon(secondIcon);
}
});
// add to GUI
add(label);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("RandomImages");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
frame.getContentPane().add(new RandomChessMen());
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I have made these changes to your code:
Instead of having three methods cards1() cards2() cards3(), i have just made one cards() method.
Everytime you click on the frame, three random images get loaded.
I have set every image inside a JLabel in order to make it easy to update it.
The code below works perfectly according to your needs.
package example;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
public class Cards extends JFrame implements MouseListener {
JPanel subPanel1;
JLabel label1, label2, label3;
static ImageIcon[] images ;
static Random ran ;
static int[] threeRandoms;
public Cards() {
super("Cards");
subPanel1 = new JPanel();
// Set up first subpanel
subPanel1.setPreferredSize (new Dimension(400, 400));
//subPanel1.setBackground (Color.cyan);
label1 = new JLabel ("image 1",SwingConstants.CENTER);
label2 = new JLabel ("image 2", SwingConstants.LEFT);
label3 = new JLabel ("image 3", SwingConstants.CENTER);
subPanel1.add (label1);
subPanel1.add (label2);
subPanel1.add (label3);
add(subPanel1);
addMouseListener(this);
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
System.out.println("Success.....");
}
public void cards() {
for (int i = 0; i < threeRandoms.length; i++)
threeRandoms[i] = ran.nextInt(3);
label1.setIcon(images[threeRandoms[0]]);
label2.setIcon(images[threeRandoms[1]]);
label3.setIcon(images[threeRandoms[2]]);
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouseClicked");
cards();
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("mouseEntered");
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("mouseExited");
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("mouseReleased");
}
public static void loadImages(){
images = new ImageIcon[4];
ran = new Random();
threeRandoms = new int[3];
for (int i = 1; i <= images.length; i++) {
images[i-1] = new ImageIcon("Drawables//Images//" + i + ".png");
}
}
public static void main(String[] args) {
loadImages();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Cards();
}
});
}
}
Related
I'm trying to move a robot represented by a JLabel into a GridLayout. The move is made but the display of the JLabel is only done for the final finishing square. I would like to see the move from box to box. I try to use javax.swing.Timer but it's not working.
import java.awt.Color;
import java.awt.Component;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.util.Vector;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.LayoutStyle;
import javax.swing.Timer;
// Robot
public class Robot extends Case implements Serializable {
private ImageIcon imageRobot;
private Color couleur;
public Robot () {
imageRobot = new ImageIcon("./assets/balle.png");
setIcon(imageRobot);
}
public void seDeplacer (JPanel panel) {
Robot currentRoot = this;
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
for (int i=0; i<5; i++) {
panel.remove(panel.getComponent(i));
panel.add(currentRoot, i);
panel.doLayout();
}
}
};
new Timer(delay, taskPerformer).start();
}
public void detruire () {
}
public void setCouleur (Color couleur) {
this.couleur=couleur;
}
public Color getCouleur () {
return this.couleur;
}
}
This block
public void seDeplacer (JPanel panel) {
Robot currentRoot = this;
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
for (int i=0; i<5; i++) {
panel.remove(panel.getComponent(i));
panel.add(currentRoot, i);
panel.doLayout();
}
}
};
new Timer(delay, taskPerformer).start();
says literally "move my robot 5 times every second" thus robots moves 5 in blink of an eye every second.
What you wat is to move robot 1 time every second. To do that you need to introduce delay between robot moves.
You & the current commentators are over (or under - shrugs) thinking this. It is not necessary to add or remove components or change Z order to move the robot, just change the label text of the place moved from " " and the new label text to `"🤖".
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class MovingBot {
private JComponent ui = null;
String bot = new String(Character.toChars(129302));
Font font;
JLabel[] labels = new JLabel[100];
MovingBot() {
initUI();
}
public void initUI() {
if (ui!=null) return;
Font[] fonts = GraphicsEnvironment.
getLocalGraphicsEnvironment().getAllFonts();
for (Font font : fonts) {
if (font.canDisplay(129302)) {
this.font = font.deriveFont(20f);
}
}
ui = new JPanel(new GridLayout(0,20,2,2));
ui.setBorder(new EmptyBorder(4,4,4,4));
for (int ii=0; ii<labels.length; ii++) {
JLabel l = new JLabel(" ");
l.setFont(font);
ui.add(l);
labels[ii] = l;
}
labels[0].setText(bot);
ActionListener moveListener = new ActionListener() {
int count = 0;
#Override
public void actionPerformed(ActionEvent e) {
int indexLast = count%100;
labels[indexLast].setText(" ");
count++;
int indexCurrent = count%100;
labels[indexCurrent].setText(bot);
}
};
Timer timer = new Timer(50, moveListener);
timer.start();
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
MovingBot o = new MovingBot();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
Im creating a program in which I must from time to time reset a button Array and display it on a jPanel. The function below adds the jButtons to my panel and displays them perfectly the first time that it is called, but from then on, every time I call it (after emptying the jButton array and applying .removeAll() to the panel) it wont let me change the background color of the jButton. Some assistance to help me find out why this is would be great, thanks.
import java.awt.*;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import javafx.scene.layout.Border;
import javax.swing.*;
/**
*
* #author Luis
*/
public class MineSweeper extends JFrame implements ActionListener {
int int_dim = 11;
int int_cellsShown = 0;
JButton[][] arr_btnField = new JButton[int_dim][int_dim];
int[][] arr_solution = new int[int_dim][int_dim];
Color[] clr_palette = {Color.white, new Color(0X00, 0X94, 0XFF), new Color(0X00, 0X26, 0XFF), new Color(0X00, 0XAA, 0X0A), Color.red, Color.MAGENTA, new Color(0XFF, 0X00, 0X00), new Color(0X9B, 0X00, 0X00)};
boolean bool_change = false;
boolean bool_won = false;
boolean bool_firstround = false;
javax.swing.border.Border border = BorderFactory.createLineBorder(Color.darkGray, 1, true);
MenuBar menu_bar;
Menu menu;
MenuItem optionNew;
//boolean[][] arr_boolShowed=new boolean[int_dim][int_dim];
int int_mines = 8;
ArrayList<Integer> arl_field = new ArrayList<Integer>();
JPanel jpanel = new JPanel();
JPanel jpanel2 = new JPanel();
//ArrayList<Boolean> arl_boolShowed = new ArrayList<Boolean>();
/**
* #param args the command line arguments
*/
public MineSweeper() throws FontFormatException, IOException {
resetGame();
//JFrame frame = new JFrame("");
this.getContentPane().add(jpanel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(true);
this.setTitle("Minesweeper");
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setSize(500, 500);
menu_bar = new MenuBar();
menu = new Menu("File");
optionNew = new MenuItem("Win");
optionNew.addActionListener(this);
menu.add(optionNew);
menu_bar.add(menu);
this.setMenuBar(menu_bar);
}
public void resetGame() {
jpanel.removeAll();
arl_field.clear();
arr_btnField = new JButton[int_dim][int_dim];
arr_solution = new int[int_dim][int_dim];
bool_change = false;
bool_won = false;
//arl_field = new ArrayList<Integer>();
for (int i = 0; i < arr_solution.length; i++) {
for (int j = 0; j < arr_solution[i].length; j++) {
arr_solution[i][j] = 1;
}
}
jpanel.setLayout(new GridLayout(0, int_dim));//if(bool_firstround==false)jpanel.setLayout(new GridLayout(0,int_dim));
for (int i = 0; i < arr_btnField.length; i++) {
for (int j = 0; j < arr_btnField[i].length; j++) {
arr_btnField[i][j] = new JButton();////if(bool_firstround==false)arr_btnField[i][j] = new JButton();//arl_field.get(i*int_dim+j)+"");
arr_btnField[i][j].setText("");
arr_btnField[i][j].setBackground(new Color(0X00, 0X94, 0XFF));
arr_btnField[i][j].setBorder(border);
arr_btnField[i][j].setForeground(clr_palette[1]);
arr_btnField[i][j].addMouseListener(listener);
arr_btnField[i][j].setFocusable(false);
jpanel.add(arr_btnField[i][j]);
}
}
jpanel.revalidate();
jpanel.repaint();
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new MineSweeper();
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
}
});
}
MouseListener listener = new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
outerloop:
for (int i = 0; i < arr_btnField.length; i++) {
for (int j = 0; j < arr_btnField[i].length; j++) {
if (e.getSource() == arr_btnField[i][j]) {
if (SwingUtilities.isLeftMouseButton(e)) {
labelText(i, j);
}
if (SwingUtilities.isRightMouseButton(e)) {
arr_btnField[i][j].setBackground(Color.red);
}
//bool_won=false;
break outerloop;
}
}
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
if (bool_won == true)
gameWon();
}
#Override
public void mouseExited(MouseEvent e) {
}
};
public void labelText(int i, int j) {
if (bool_won == false) {
arr_btnField[i][j].setText("1");
arr_btnField[i][j].setBackground(Color.white);
if (arr_btnField[i][j].getBorder() == border) {
int_cellsShown++;
System.out.println("Cells shown: " + int_cellsShown);
if (int_cellsShown >= (int_dim * int_dim - int_mines)) {
bool_won = true;
}
}
if (bool_won == false)
arr_btnField[i][j].setBorder(BorderFactory.createLineBorder(Color.darkGray, 1, true));
}
}
public void gameWon() {
int dialogResult = JOptionPane.showConfirmDialog(null, "You Won! Do you want to start a new game?", "Congratulations!", JOptionPane.YES_NO_OPTION);
if (dialogResult == JOptionPane.YES_OPTION) {
bool_won = false;
int_cellsShown = 0;
resetGame();
}
}
#Override
public void actionPerformed(ActionEvent e) {
int_cellsShown = 0;
int_dim++;
resetGame();
for (int i = 0; i < arr_btnField.length; i++) {
for (int j = 0; j < arr_btnField[i].length; j++) {
arr_btnField[i][j].setBackground(Color.red);
}
}
}
}
Display after the first time:
Display after the second time:
I invoke .revalidate in the fourth line of the method.
That doesn't do anything since there on no components added to the panel. The revalidate() needs to be done AFTER the components have been added.
The displayed panel is not jpanel, the displayed panel is jpanel2, thats why I assign jpanel2 to the value of jpanel in the end of the method.
You can't just change a reference and expect the components to be moved from one panel to another.
The components need to be added to the panel that is added to the GUI.
Edit:
First of all Swing components start with "J". Don't use AWT components (MenuBar, Menu, MenuItem) in a Swing application.
The problem is your LAF:
new MineSweeper();
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
The components are created with the current LAF. When you first create the game, the default LAF is used to create all the buttons (and other components). This LAF allows you to change the background color of the buttons.
However, then you change the LAF. So when you reset the game board the buttons are now created with the System LAF. This LAF apparently does not allow you to change the background color of the button.
This should be easy to test. Create a GUI:
//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
JButton button = new JButton("testing");
button.setBackground(Color.RED);
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( button );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
First test the code as above to see if the background of the button changes.
Then uncomment the LAF change and retest.
A possible solution so you are not dependent on the LAF is to use an Icon to represent the background color of the button. Then you can center any text on top of the Icon. Something like:
import java.awt.*;
import javax.swing.*;
public class ColorIcon implements Icon
{
private Color color;
private int width;
private int height;
public ColorIcon(Color color, int width, int height)
{
this.color = color;
this.width = width;
this.height = height;
}
public int getIconWidth()
{
return width;
}
public int getIconHeight()
{
return height;
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
g.setColor(color);
g.fillRect(x, y, width, height);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI()
{
JPanel panel = new JPanel( new GridLayout(2, 2) );
for (int i = 0; i < 4; i++)
{
Icon icon = new ColorIcon(Color.RED, 50, 50);
JLabel label = new JLabel( icon );
label.setText("" + i);
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.CENTER);
panel.add(label);
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(panel);
f.setSize(200, 200);
f.setLocationRelativeTo( null );
f.setVisible(true);
}
}
Yep, I too just noticed, that the problem is here:
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new MineSweeper();
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
}
});
}
If you comment out the UIManager line, your code works. This line is only valid after the GUI has been created, and so doesn't take effect until new components are created. Note that I was working on minimizing your code to discover this, and was cutting out code to see what caused the problem until this was all that was left.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.UIManager;
#SuppressWarnings("serial")
public class MineSweeper extends JFrame implements ActionListener {
private static final Color BTN_COLOR = new Color(0X00, 0X94, 0XFF);
int int_dim = 11;
JButton[][] arr_btnField = new JButton[int_dim][int_dim];
JMenuBar menu_bar;
JMenu menu;
JMenuItem optionNew;
JPanel jpanel = new JPanel();
public MineSweeper() {
resetGame();
this.getContentPane().add(jpanel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(true);
this.setTitle("Minesweeper");
menu_bar = new JMenuBar();
menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
optionNew = new JMenuItem("Win");
optionNew.setMnemonic(KeyEvent.VK_W);
optionNew.addActionListener(this);
menu.add(optionNew);
menu_bar.add(menu);
this.setJMenuBar(menu_bar);
this.setPreferredSize(new Dimension(500, 500));
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public void resetGame() {
jpanel.removeAll();
arr_btnField = new JButton[int_dim][int_dim];
jpanel.setLayout(new GridLayout(0, int_dim));
for (int i = 0; i < arr_btnField.length; i++) {
for (int j = 0; j < arr_btnField[i].length; j++) {
arr_btnField[i][j] = new JButton();
arr_btnField[i][j].setBackground(BTN_COLOR);
jpanel.add(arr_btnField[i][j]);
}
}
jpanel.revalidate();
jpanel.repaint();
}
#Override
public void actionPerformed(ActionEvent e) {
resetGame();
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new MineSweeper();
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
}
});
}
}
I'm trying to create a program where you press start and a new JFrame comes up with 3 buttons , you have to switch the button after you click on it using a random , I'm fairly new to java so I don't know what to do. Thank you
package code;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.Timer;
public class StartListener implements java.awt.event.ActionListener {
private int counter;
private Game Ga;
private JFrame z;
private int x;
public StartListener(Game a, int co){
Ga=a;
counter = co;
}
public void actionPerformed(ActionEvent e) {
Timer time = new Timer(10000,new Time(Ga));
time.start();
z = new JFrame("Sequence game");
FlowLayout fl = new FlowLayout(0, 50, 40);
z.getContentPane().setLayout(fl);
z.setVisible(true);
JButton a = new JButton("A");
Font f = a.getFont();
Font myFont = f.deriveFont(Font.BOLD, f.getSize()*4);
a.setSize(200,100);
a.setVisible(true);
JButton b = new JButton("B");
b.setVisible(true);
b.setSize(200,100);
JButton c = new JButton("C");
c.setVisible(true);
c.setSize(200,100);
z.getContentPane().add(a);
z.getContentPane().add(b);
z.getContentPane().add(c);
z.pack();
Random r = new Random();
x=r.nextInt(3);
figure(a,b,c,x,myFont,f);}
public void figure(JButton a,JButton b, JButton c, int x, Font myFont,Font f){
if(x==0){
a.setEnabled(true);
b.setEnabled(false);
c.setEnabled(false);
a.setFont(myFont);
b.setFont(f);
c.setFont(f);
x =buttonA(a);
figure(a,b,c,x,myFont,f);
;}
else if(x==1){
a.setEnabled(false);
b.setEnabled(true);
c.setEnabled(false);
a.setFont(f);
c.setFont(f);
b.setFont(myFont);
x = buttonB(b);
figure(a,b,c,x,myFont,f);
}
else if(x==2){
a.setEnabled(false);
b.setEnabled(false);
c.setEnabled(true);
a.setFont(f);
b.setFont(f);
c.setFont(myFont);
x = buttonC(c);
figure(a,b,c,x,myFont,f);
}
}
public int buttonA(JButton a){
Random r = new Random();
int rand = 0;
a.addActionListener(new Something(Ga));
rand = r.nextInt(3);
return rand;
}
public int buttonB(JButton b){
Random r = new Random();
int rand = 0;
b.addActionListener(new Something(Ga));
rand=r.nextInt(3);
return rand;
}
public int buttonC(JButton c){
Random r = new Random();
int rand=0;
c.addActionListener(new Something(Ga));
rand = r.nextInt(3);
return rand;
}
}
And here's the code for Something
package code;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Something implements ActionListener {
private Game G;
public Something(Game a){
G = a;
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
G.increment();
}
}
Here's the error :
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at java.awt.Component.enable(Unknown Source)
at java.awt.Component.setEnabled(Unknown Source)
at javax.swing.JComponent.setEnabled(Unknown Source)
at javax.swing.AbstractButton.setEnabled(Unknown Source)
Your figure method continuously calls itself recursively forever, or until stack space runs out. Solution: get rid of those recursive calls. Also you really don't want to keep adding multiple ActionListeners on to JButtons, all this suggesting that you will want to refactor and perhaps redesign the entire program.
You will want to change the state of a field in the class, and use that field's state to decide what to do within the ActionListener.
For example:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class SwapButtons extends JPanel {
private static final Font ACTIVE_FONT = new Font(Font.DIALOG, Font.BOLD, 15);
private static final String[] BTN_TEXT = { "Monday", "Tuesday", "Wednesday" };
private static final int EXTRA_WIDTH = 50;
private List<AbstractButton> buttonList = new ArrayList<>();
private int buttonIndex = 0;
public SwapButtons() {
setLayout(new GridLayout(1, 0, 5, 0));
BtnListener btnListener = new BtnListener();
for (int i = 0; i < BTN_TEXT.length; i++) {
JButton button = new JButton(BTN_TEXT[i]);
button.addActionListener(btnListener);
buttonList.add(button); // add to ArrayList
add(button); // add to GUI
}
setActiveButton();
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
}
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
// give preferred size extra width so gui can handle larger fonts
int prefW = superSz.width + EXTRA_WIDTH;
int prefH = superSz.height;
return new Dimension(prefW, prefH);
}
private void setActiveButton() {
// iterate through buttonList, turning on the "active" button
// as determined by the buttonIndex variable
for (int i = 0; i < buttonList.size(); i++) {
if (i == buttonIndex) {
buttonList.get(i).setFont(ACTIVE_FONT);
buttonList.get(i).setEnabled(true);
} else {
buttonList.get(i).setFont(null);
buttonList.get(i).setEnabled(false);
}
}
}
private class BtnListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// show which button pressed
System.out.println("Button Pressed: " + e.getActionCommand());
// advance button index so that next button can be activated
buttonIndex++;
// but change index to 0 if buttonList size is reached
buttonIndex %= buttonList.size();
// activate the next button:
setActiveButton();
}
}
private static void createAndShowGui() {
SwapButtons mainPanel = new SwapButtons();
JFrame frame = new JFrame("Swap Buttons");
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();
}
});
}
}
I have a Gridlayout filled with images loaded from File and I want to add a different, for example, popup, on mouseEvent mouseClicked for each image. How do I determine which image I'm clicking? I've tried adding GetComponentAt(Point), but Eclipse keeps showing that as an unidentified method for the mouseAdapter, and how do I determine the fields for the if statement?
This is what I have:
public class testclass implements ItemListener {
JPanel template;
final static String title = "Title";
public void testclass (Container window){
JPanel index = new JPanel();
String index2[] = {title};
JComboBox index3 = new JComboBox(index2);
index3.setEditable(false);
index3.addItemListener(this);
index.add(index3);
File folder = new File("images/");
File[] listOfFiles = folder.listFiles();
String nr;
final JPanel panel = new JPanel(new GridLayout(4, 4, 4, 4));
for (int i = 0; i < listOfFiles.length; i++) {
nr = "images/" + listOfFiles[i].getName();
final ImageIcon images = new ImageIcon(nr);
final JLabel display[] = new JLabel[1];
for (int n = 0; n < 1; n++){
display[n] = new JLabel(images);
panel.add(display[n]);
} }
panel.addMouseListener(new MouseAdapter()
{ public void mouseClicked (MouseEvent e)
{ //JPanel panel = (JPanel) getComponentAt(e.getPoint());
JOptionPane.showMessageDialog(null, "Message");
}});
template = new JPanel(new CardLayout());
template.add(panel, title);
window.add(index, BorderLayout.PAGE_START);
window.add(template, BorderLayout.CENTER);
}
public void itemStateChanged(ItemEvent event){
CardLayout change = (CardLayout)(template.getLayout());
change.show(template, (String)event.getItem());
}
private static void userinterface() {
JFrame showwindow = new JFrame("Window");
showwindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testclass show = new testclass();
show.testclass(showwindow.getContentPane());
showwindow.pack();
showwindow.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch(Exception e){
}
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
userinterface();
}
});
}
}
Edit: Proper Answer
Thankyou for providing code. I have adjusted some things so hopefully you can understand them.
Firstly I have added a new object, ImageButton. From when I added the actionListener the functionality you wanted was already done (minus the good looks, you will have to play around with that, or ask another question)
Added a 'dir' string so that you don't have to keep copy and pasting the directory address.
I had to adjust the size of the window through the userInterface() method, you should look at being able to shorten the sequence of being able to adjust the parameters, maybe another GUI object to keep all that information together.
A couple of things:
The code you wrote was good but it would need for you to adjust alot of (getting the size of windows and repeatedly check for different sizes if you adjusted the window size where a mouse click could click on other image that you don't want!) in order for a mouseListener to work, I am guessing with a wide range of images you would be providing.
Putting comments in your code can help both you and someone trying to help you.
Anyways, please upvote/accept answer if this helps out, which I'm sure it does.
Good Luck!
Put these files into your eclipse and run them it should work if you adjust the dir string to follow your original directory path.
testclass.java
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class testclass implements ItemListener {
JPanel template;
final static String title = "Title";
final String dir = "images/";
public void testclass(Container window) {
JPanel index = new JPanel();
String[] index2 = { title };
JComboBox index3 = new JComboBox(index2);
index3.setEditable(false);
index3.addItemListener(this);
index.add(index3);
index.setSize(500, 500);
File folder = new File(dir);
File[] listOfFiles = folder.listFiles();
String nr;
final JPanel panel = new JPanel(new GridLayout(4, 4, 4, 4));
for (int i = 0; i < listOfFiles.length; i++) {
nr = dir + listOfFiles[i].getName();
panel.add(new ImageButton(nr));
}
template = new JPanel(new CardLayout());
template.add(panel, title);
window.add(template, BorderLayout.CENTER);
window.add(index, BorderLayout.NORTH);
window.setVisible(true);
}
public void itemStateChanged(ItemEvent event) {
CardLayout change = (CardLayout) (template.getLayout());
change.show(template, (String) event.getItem());
}
private static void userinterface() {
JFrame showwindow = new JFrame("Window");
showwindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testclass show = new testclass();
show.testclass(showwindow.getContentPane());
showwindow.pack();
showwindow.setVisible(true);
showwindow.setSize(500, 500);
}
public static void main(String[] args) {
try {
UIManager
.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
}
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
userinterface();
}
});
}
}
ImageButton.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
public class ImageButton extends JButton {
private String fileName;
private ImageIcon image;
private JButton button;
public ImageButton(String fileName) {
setFileName(fileName);
setImage(new ImageIcon(fileName));
setButton(new JButton(getImage()));
this.setIcon(getImage());
this.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
JOptionPane.showMessageDialog(null, ae.getSource());
}
});
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public ImageIcon getImage() {
return image;
}
public void setImage(ImageIcon image) {
this.image = image;
}
public JButton getButton() {
return button;
}
public void setButton(JButton button) {
this.button = button;
}
}
I have a simple puzzle game. There is an image consisting of 16 tiles (randomly placed). Images are stored in an array and when game is launched they're added to main JPanel.
Game works in this way : Each image has atributes 'place' and 'number'. 'Place' is the current place on grid (either correct or not) and 'number' is the desired place for the image. When a user clicks image their 'place' and 'number' attributes are checked. If they match nothing happens. If not game checks if any image is currently in memory. If there is none, then this image's 'place' and 'number' are stored. If there is some image in memory, then the currently clicked image's 'plac'e is checked with stored image's 'number'. When they match - their places are exchanged. This part works properly. But now, I'm calling addComponent method on my JPanel with updated images and simply nothing happens. Shouldn't the new images be added to JPanel replacing the old ones ?
package Bonus;
import javax.swing.*;
import java.util.Random;
import java.awt.event.*;
import java.awt.*;
class Puzzle extends JPanel implements ActionListener {
private int selected_nr=-1;
private int selected_pl=-1;
private boolean memory=false;
private static Img[] images;
public Puzzle(){
JFrame f = new JFrame("Smile");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.setSize(252,252);
f.setVisible(true);
setLayout(new GridLayout(4, 4));
images = new Img[16];
int[] buttons = new int[16];
for(int i=0; i<16; i++){
buttons[i] = i;
}
int rand;
int temp;
Random random;
random = new Random(System.currentTimeMillis());
for (int i = 0; i < buttons.length; i++) {
rand = (random.nextInt() & 0x7FFFFFFF) % buttons.length;
temp = buttons[i];
buttons[i] = buttons[rand];
buttons[rand] = temp;
}
for (int i = 0; i < 16; i++) {
images[i] = new Img(i, buttons[i]);
}
addComponents(images);
}
public void addComponents(Img[] im){
this.removeAll();
for(int i=0; i<16; i++){
im[i].addActionListener(this);
im[i].setPreferredSize(new Dimension(53,53));
add(im[i]);
}
this.validate();
}
public void actionPerformed(ActionEvent e) {
Img b = (Img)(e.getSource());
int num = b.getNumber();
int pl = b.getPlace();
if(!(b.rightPlace())){
if(memory){
if(pl == selected_nr){
images[pl].setPlace(selected_pl);
images[selected_pl].setPlace(selected_nr);
selected_nr = -1;
selected_pl = -1;
memory = false;
addComponents(images);
}
else{
System.out.println("Try other image");
}
}
else{
memory = true;
selected_nr = num;
selected_pl = pl;
}
}
else{
System.out.println("OK !");
}
}
public static void main(String args[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Puzzle();
}
});
}
}
class Img extends JButton {
int number;
int place;
ImageIcon img;
public Img(int p, int n){
number = n;
place = p;
img = new ImageIcon("u"+number+".jpg", BorderLayout.CENTER);
setIcon(img);
}
public boolean rightPlace(){
boolean correct=false;
if(number == place){
correct = true;
}
return correct;
}
public void setPlace(int i){
place = i;
}
public int getNumber(){
return number;
}
public int getPlace(){
return place;
}
}
EDIT: Changed the code to use the answers, but still no luck. addComponents() gets updated images[] but doesn't revalidate them.
Rather than relying on precut image files, here's an example of slicing an existing image and shuffling the resulting pieces. It combines the helpful (+1) suggestions of both #Frederick and #akf.
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ImageLabelPanel extends JPanel implements ActionListener {
private static final int N = 4;
private final List<JLabel> list = new ArrayList<JLabel>();
private final Timer timer = new Timer(1000, this);
ImageLabelPanel() {
this.setLayout(new GridLayout(N, N));
BufferedImage bi = null;
try {
bi = ImageIO.read(new File("image.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
int w = bi.getWidth() / N;
int h = bi.getHeight() / N;
BufferedImage b = bi.getSubimage(c * w, r * h, w, h);
list.add(new JLabel(new ImageIcon(b)));
}
}
createPane();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setVisible(true);
timer.start();
}
private void createPane() {
this.removeAll();
for (JLabel label : list) add(label);
this.validate();
}
#Override
public void actionPerformed(ActionEvent e) {
Collections.shuffle(list);
createPane();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ImageLabelPanel();
}
});
}
}
You are adding all of your components again to your JPanel without actually removing any of them. In your addComponents() method, I would first call removeAll(). You might want to rename that method to highlight the side-effects, as it no longer would only be adding components. Perhaps, resetComponents() would be better.
After changing the components, you need to 'refresh' the Swing component by calling invalidate() or revalidate().