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;
}
}
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);
}
}
I'm trying to make a trivia game in swing with CardLayout to change between screens in a single JFrame. I have a loop set to move through the states in my enumeration. Everything works quite well except for when, at the end of a game, if I choose to start a new game, it somehow goes to both the first and second states simultaneously. I'm not sure how this happens as this is the only state this happens in.
Code for main:
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.awt.CardLayout;
import java.awt.Color;
import java.io.IOException;
import java.util.Random;
import javax.swing.*;
public class Main
{
public enum State {SPLASH, PREQUESTION, QUESTION, WIN, LOSS};
public static JFrame frame;
public static JPanel content;
public static JPanel neutral;
public static int event;
public static Random rn = new Random();
public static Splash splash;
public static Prequestion eventStart;
public static Question question;
public static Win win;
public static Loss loss;
public static void main(String[] args) throws LineUnavailableException, UnsupportedAudioFileException, IOException
{
frame = new JFrame("DREWcathalon");
content = new JPanel();
neutral = new JPanel();
CardLayout cards = new CardLayout();
content.setLayout(cards);
neutral.setBackground(Color.WHITE);
content.add(neutral, "neutral");
frame.add(content);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 750);
frame.setVisible(true);
cards.show(content, "neutral");
State gameState = State.SPLASH;
while (true)
{
switch(gameState)
{
case SPLASH:
event = 0;
splash = new Splash(content, cards);
splash.splashSound();
while (splash.holdState()){};
cards.show(content, "neutral");
gameState = State.PREQUESTION;
splash = null;
break;
case PREQUESTION:
event++;
eventStart = new Prequestion(event, content, cards);
while (eventStart.holdState()){};
cards.show(content, "neutral");
gameState = State.QUESTION;
eventStart = null;
break;
case QUESTION:
question = new Question(event, rn.nextInt(5)+1, content, cards);
while (question.holdState()){};
cards.show(content, "neutral");
if (question.rightState() && event > 9)
{
gameState = State.WIN;
}
else if (question.rightState())
{
gameState = State.PREQUESTION;
}
else
{
gameState = State.LOSS;
}
question = null;
break;
case WIN:
win = new Win(content, cards);
while(win.holdState()){};
cards.show(content, "neutral");
gameState = State.SPLASH;
win = null;
break;
case LOSS:
loss = new Loss(content, cards);
while(loss.holdState()){};
cards.show(content, "neutral");
gameState = State.SPLASH;
loss = null;
break;
}
}
}
}
Code for Win:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.sound.sampled.*;
import java.io.*;
public class Win
{
static private Clip clip;
static private boolean hold = true;
public Win(JPanel content, CardLayout cards) throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
JButton restart = new JButton("New Game+");
JButton quit = new JButton("Flee");
JLabel title = new JLabel("A Winnar is You!");
JPanel wContent = new JPanel();
wContent.add(title);
wContent.add(restart);
wContent.add(quit);
wContent.setBackground(Color.WHITE);
content.add(wContent, "win");
cards.show(content, "win");
File soundFile = new File("TEST.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
restart.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
if (clip.getMicrosecondPosition() < clip.getMicrosecondLength())
{
clip.stop();
}
hold = false;
}
});
quit.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
}
public boolean holdState()
{
return hold;
}
}
I don't have the specific answer to your specific question, which is one reason I'm answering this as a Community Wiki, but I can state with confidence that your program structure is broken and is not written in a way that respects either object-oriented programming principles, as evidenced by your copious use of static fields, or GUI event-driven coding principles, as evidenced by your while (true) loop. The solution is to completely restructure your program, getting rid of your while (true) loop and instead use notifications / observer design pattern to drive state changes.
I can almost guarantee that if you fix these issues, especially by getting rid of the while (true) loop and replacing it with event notification and listening, your problem with game restart will resolve.
If you need more specific help, you'll want to create and post your valid SSCCE (please see the link for the details). I tried doing this myself with your code, but it's taking me too long, and the effort really should be yours.
A very simplistic example that uses simple notification to change state
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class Main2 extends JPanel {
private CardLayout cardLayout = new CardLayout();
private MyState myState = MyState.SPLASH;
private MySplash mySplash = new MySplash(this);
private MyPreQuestion myPreQuestion = new MyPreQuestion(this);
private MyQuestion myQuestion = new MyQuestion(this);
public Main2() {
setLayout(cardLayout);
add(mySplash, MyState.SPLASH.toString());
add(myPreQuestion, MyState.PREQUESTION.toString());
add(myQuestion, MyState.QUESTION.toString());
mySplash.startSplashTimer();
}
public void next() {
int index = 0;
for (int i = 0; i < MyState.values().length; i++) {
if (MyState.values()[i] == myState) {
index = i;
}
}
index++;
index %= MyState.values().length;
setState(MyState.values()[index]);
}
public void setState(MyState nextState) {
myState = nextState;
cardLayout.show(this, nextState.toString());
if (myState == MyState.SPLASH) {
mySplash.startSplashTimer();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Main");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Main2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
enum MyState {
SPLASH, PREQUESTION, QUESTION // ..., WIN, LOSS
}
#SuppressWarnings("serial")
class NextAction extends AbstractAction {
private Main2 main;
public NextAction(Main2 main) {
super("Next");
putValue(MNEMONIC_KEY, KeyEvent.VK_N);
this.main = main;
}
#Override
public void actionPerformed(ActionEvent e) {
main.next();
}
}
#SuppressWarnings("serial")
abstract class AbstractView extends JPanel {
private Main2 main;
public AbstractView(Main2 main) {
this.main = main;
}
public Main2 getMain() {
return main;
}
public void next() {
main.next();
}
}
#SuppressWarnings("serial")
class MySplash extends AbstractView {
private static final int TIMER_DELAY = 3000;
private Timer timer;
public MySplash(Main2 main) {
super(main);
setPreferredSize(new Dimension(300, 140));
add(new JLabel("My Splash"));
}
public void startSplashTimer() {
timer = new Timer(TIMER_DELAY, e -> {
next();
timer.stop();
});
timer.start();
}
}
#SuppressWarnings("serial")
class MyPreQuestion extends AbstractView {
public MyPreQuestion(Main2 main) {
super(main);
add(new JLabel("Prequestion"));
add(new JButton(new NextAction(main)));
}
}
#SuppressWarnings("serial")
class MyQuestion extends AbstractView {
public MyQuestion(Main2 main) {
super(main);
add(new JLabel("Question"));
add(new JButton(new NextAction(main)));
}
}
I need to make a slot machine that implements thread in java and jframe
this is what iv'e done so far kindly tell me what i need to do in order make the images change per .5 seconds when i press the the play and stop when i press stop. If all the three images are the same it'll say you won. This is what iv'e got so far how will i change this numbers or text to images in jlabel.
public class MySlotNumber extends JFrame{
private MyJLabel x;
private MyJLabel y;
private MyJLabel z;
private JButton btn;
public MySlotNumber(){
super("ABC");
setLayout(new FlowLayout());
Font font = new Font("arial",Font.ITALIC,50);
x = new MyJLabel();
x.setFont(font);
y = new MyJLabel();
y.setFont(font);
z = new MyJLabel();
z.setFont(font);
btn = new JButton("PLAY");
btn.setFont(font);
add(x);
add(y);
add(z);
add(btn);
final Thread thx = new Thread(x);
final Thread thy = new Thread(y);
final Thread thz = new Thread(z);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("PLAY")){
if(thx.isAlive()){
thx.resume();
thy.resume();
thz.resume();
} else {
thx.start();
thy.start();
thz.start();
}
btn.setText("STOP");
} else {
thx.suspend();
thy.suspend();
thz.suspend();
btn.setText("PLAY");
System.out.println(x.getText());
}
}
});
}
- - - - - - --
public class MyJLabel extends JLabel implements Runnable{
private Random r;
private int ctr;
private final int T = 500;
public MyJLabel(){
setText("0");
ctr = 0;
r= new Random();
}
#Override
public void run() {
while(true){
try {
Thread.sleep(T);
} catch (InterruptedException ex) {
Logger.getLogger(MyJLabel.class.getName()).log(Level.SEVERE, null, ex);
}
//ctr++;
ctr = r.nextInt(9)+1;
setText(String.valueOf(ctr));
}
}
}
Here is one way to put a picture on a JLabel and change it when you click a button. (I am using window builder for eclipse, so it may look a little odd.) It is not recommended you use absolute paths because when you move your project or the file, it breaks (I did this just for proof of concept).
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.BorderLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Test {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Test() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 1379, 643);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lblNewLabel = new JLabel("");
lblNewLabel.setIcon(new ImageIcon("C:\\Users\\Andrew\\Pictures\\Random Pictures\\Capture.JPG"));
frame.getContentPane().add(lblNewLabel, BorderLayout.CENTER);
JButton btnClickMe = new JButton("click me");
btnClickMe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
lblNewLabel.setIcon(new ImageIcon("C:\\Users\\Andrew\\Pictures\\Random Pictures\\I'm pretty sure he did.JPG"));
}
});
frame.getContentPane().add(btnClickMe, BorderLayout.EAST);
}
}
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();
}
});
}
}
I'm not sure how much of sense my title does but since you are suppose to have somewhat of a good title this was the best I came up with, so what I actually mean is...
Let's say in theory I've got 10 tabs, and instead of having them all compressed together in 1 line I'd like to split them in 2, so I'd have 5 tabs on the upper side and 5 on the lower.
Example pic:
not clear your question, but there are basic methods for Tabs in the JTabbedPane
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
public class TabComponentsDemo extends JFrame {
private static final long serialVersionUID = 1L;
private final int tabNumber = 15;
private final JTabbedPane pane = new JTabbedPane();
private JMenuItem tabComponentsItem;
private JMenuItem scrollLayoutItem;
public TabComponentsDemo(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initMenu();
add(pane);
}
public void runTest() {
pane.removeAll();
for (int i = 0; i < tabNumber; i++) {
String title = "Tab " + i;
pane.add(title, new JLabel(title));
//initTabComponent(i);
}
tabComponentsItem.setSelected(true);
pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
scrollLayoutItem.setSelected(false);
setSize(new Dimension(400, 200));
setLocationRelativeTo(null);
setVisible(true);
}
/*private void initTabComponent(int i) {
pane.setTabComponentAt(i, new ButtonTabComponent(pane));
}*/
private void initMenu() {//Setting menu
JMenuBar menuBar = new JMenuBar();//create Options menu
tabComponentsItem = new JCheckBoxMenuItem("Use TabComponents", true);
tabComponentsItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_MASK));
tabComponentsItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < pane.getTabCount(); i++) {
if (tabComponentsItem.isSelected()) {
//initTabComponent(i);
} else {
pane.setTabComponentAt(i, null);
}
}
}
});
scrollLayoutItem = new JCheckBoxMenuItem("Set ScrollLayout");
scrollLayoutItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK));
scrollLayoutItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (pane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT) {
pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
} else {
pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
}
}
});
JMenuItem resetItem = new JMenuItem("Reset JTabbedPane");
resetItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_MASK));
resetItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
runTest();
}
});
JMenu optionsMenu = new JMenu("Options");
optionsMenu.add(tabComponentsItem);
optionsMenu.add(scrollLayoutItem);
optionsMenu.add(resetItem);
menuBar.add(optionsMenu);
setJMenuBar(menuBar);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
UIManager.put("swing.boldMetal", Boolean.FALSE);
new TabComponentsDemo("TabComponentsDemo").runTest();
}
});
}
}
If you want them all displayed in a single row (which I think is what the latter part of your description indicates...), you'll want to set the tab layout policy to JTabbedPane.SCROLL_TAB_LAYOUT.
Here's an example with an image.