Hi everybody I am a bit of stack here. When I run the program and press the button submit it is supposed to change 4 pictures in every 2 seconds.However it is not redisplaying the images. If anyone can give me a hand it would be great. I am using eclipse and the program is compiling and running. Here is the code.
/** Here is the GUI of the program
* class name SlideShowGui.java
* #author Kiril Anastasov
* #date 07/03/2012
*/
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SlideShowGui extends JPanel implements ActionListener, Runnable
{
JLabel name, comments, images;
JTextField namejtf, commentsjtf, captionjtf;
JButton submit;
ImageIcon pictures1, pictures2, pictures3, pictures4;
//ImageIcon []pictures2 = {galileo1.jpg};
SlideShowGui()
{
name = new JLabel("Name:");
this.add(name);
namejtf = new JTextField(15);
this.add(namejtf);
comments = new JLabel("Comments:");
this.add(comments);
commentsjtf = new JTextField(15);
this.add(commentsjtf);
submit = new JButton("Submit");
this.add(submit);
submit.addActionListener(this);
pictures1 = new ImageIcon("galileo1.jpg");
images = new JLabel(pictures1);
this.add(images);
pictures2 = new ImageIcon("galileo2.jpg");
this.add(images);
pictures3 = new ImageIcon("galileo3.jpg");
this.add(images);
pictures4 = new ImageIcon("galileo4.jpg");
this.add(images);
captionjtf = new JTextField(24);
this.add(captionjtf);
//pictures = new ImageIcon("galileo1.jpg");
// images.setIcon(pictures);
}
public void actionPerformed(ActionEvent ae)
{
Thread t = new Thread(this);
t.start();
if(ae.getSource() == submit)
{
int i = 0;
boolean go = true;
while(go)
{
i++;
System.out.println(i);
try
{
Thread.sleep(2000);
if(i == 1)
{
pictures1 = new ImageIcon("galileo1.jpg");
images.setIcon(pictures1);
System.out.println("picture 1 should be displayed here");
}
if(i == 2)
{
pictures2 = new ImageIcon("galileo2.jpg");
images.setIcon(pictures2);
System.out.println("picture 2 should be displayed here");
}
if(i == 3)
{
pictures3 = new ImageIcon("galileo3.jpg");
images.setIcon(pictures3);
System.out.println("picture 3 should be displayed here");
}
if(i == 4)
{
pictures4 = new ImageIcon("galileo4.jpg");
images.setIcon(pictures4);
System.out.println("picture 4 should be displayed here");
}
if(i == 4)
{
i = 0;
}
}
catch (InterruptedException ie)
{
System.out.println("thread exception");
}
}
}
}
public void run()
{
}
}
/**The driver class of the program. Here is the JFrame
* class name TestSlideShow.java
* #author Kiril Anastasov
* #date 07/03/2012
*/
import java.awt.*;
import javax.swing.*;
public class TestSlideShow
{
public static void main(String[] args)
{
JFrame application = new JFrame();
SlideShowGui panel = new SlideShowGui();
application.add(panel);
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.setSize(300,600);
application.setLocation(400,100);
application.setVisible(true);
}
}
Always use javax.swing.Timer never use Thread.sleep(...) in Swing atleast. Here try this code, but do replace the path to your images :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SlideShow extends JPanel
{
private int i = 0;
private Timer timer;
private JLabel images = new JLabel();
private Icon bg = UIManager.getIcon("OptionPane.warningIcon");
private Icon red = UIManager.getIcon("OptionPane.errorIcon");
private Icon blue = UIManager.getIcon("OptionPane.informationIcon");
private ImageIcon pictures1, pictures2, pictures3, pictures4;
private ActionListener action = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
boolean go = true;
i++;
System.out.println(i);
if(i == 1)
{
images.setIcon(bg);
System.out.println("picture 1 should be displayed here");
}
if(i == 2)
{
images.setIcon(red);
System.out.println("picture 2 should be displayed here");
}
if(i == 3)
{
images.setIcon(blue);
System.out.println("picture 3 should be displayed here");
}
if(i == 4)
{
images.setIcon(bg);
System.out.println("picture 4 should be displayed here");
}
if(i == 5)
{
go = false;
timer.stop();
System.exit(0);
}
revalidate();
repaint();
}
};
public SlideShow()
{
JFrame frame = new JFrame("SLIDE SHOW");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.getContentPane().add(this);
add(images);
frame.setSize(300, 300);
frame.setVisible(true);
timer = new Timer(2000, action);
timer.start();
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new SlideShow();
}
});
}
}
The whole if (i == ... part can be simplified. Declare a static class member in SlideShowGUI:
private final static ImageIcon[] icons = {new ImageIcon("galileo1.jpg"),
new ImageIcon("galileo2.jpg"),
new ImageIcon("galileo3.jpg"),
new ImageIcon("galileo4.jpg")};
and use it in the replacement of the if statements:
images.setIcon(icons[i-1]);
System.printf("Picture %s should be displayed%n", i-1);
if (i == 4) {
i = 0;
}
You can simplify your code as Andreas_D mentioned.
Your current design will block the main thread as you call Thread.sleep() to it, this will freeze your application.
If you would like to update the Image, you should implement the update code inside run() method.
So if you detect the user press on submit JButton, create and start the new Thread for updating UI.
Related
My project uses Java Swing as a GUI. I am making a Towers of Hanoi game. I've just about got the GUI all working, but my solve command wont work properly.
Without threading calls, it immediately solves the towers as expected. I added a couple Thread.waits expected it to solve it step by step so the user can see how it does but instead, it waits some time, then solves the entire puzzle at once. I'm thinking it might not be repainting, but I'm not sure why. Does anyone know what is going on?
Heres the code for the solve:
public class Solver {
public Solver() {
// nothing
}
public void solve(
int numberBlocks,
int startPin,
int auxiliaryPin,
int endPin) {
if (numberBlocks == 1) {
movePin(startPin, endPin);
try {
Thread.sleep(200);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
solve(numberBlocks - 1, startPin, endPin, auxiliaryPin);
movePin(startPin, endPin);
try {
Thread.sleep(200);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
solve(numberBlocks - 1, auxiliaryPin, startPin, endPin);
}
}
private void movePin(int startPin, int endPin) {
TowersOfHanoiGame.moveTopBlock(startPin, endPin);
}
Here is the code from the GUI that does the work:
I know its terribly written, this is my first time writing with Java Swing, Im learning it as I go. If anyone has any pointers on how to better structure this, I'd love to hear about that also.
I'm pasting the whole class, but the important methods are initListeners, and moveTopBlock, and the methods they call.
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class TowersOfHanoiGame {
private static JFrame mainWindow;
private static JPanel mainContentPanel;
private static JPanel content;
private static ArrayList<Block> pegOneBlocks = new ArrayList<Block>();
private static ArrayList<Block> pegTwoBlocks = new ArrayList<Block>();
private static ArrayList<Block> pegThreeBlocks = new ArrayList<Block>();
private Color[] randomColors = new Color[8];
private Dimension menuSize = new Dimension(100, 100);
private static final int DISCSTEXTSIZE = 20;
private static final int MOVESTEXTSIZE = 30;
private ActionListener downButtonListener;
private ActionListener upButtonListener;
private ActionListener solveButtonListener;
private JLabel discs;
private JLabel moves;
private int discsNumber = 3;
private int movesNumber = 0;
private Solver solver = new Solver();
public TowersOfHanoiGame() {
// do nothing
initRandomColors();
initBlocks(3);
}
/**
* Initialize and display the game
*/
public void display() {
initListeners();
initWindow();
mainWindow.setVisible(true);
}
private void initListeners() {
downButtonListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if (discsNumber > 3) {
discsNumber--;
updateLabels();
// clearContentFrame();
clearBlockArrays();
initBlocks(discsNumber);
reDrawContentFrame();
}
}
};
upButtonListener = new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (discsNumber < 8) {
discsNumber++;
updateLabels();
// clearContentFrame();
clearBlockArrays();
initBlocks(discsNumber);
reDrawContentFrame();
}
}
};
solveButtonListener = new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
solver.solve(discsNumber, 0, 1, 2);
}
};
}
private void updateLabels() {
discs.setText("DISCS: " + discsNumber);
moves.setText("MOVES: " + movesNumber);
}
/**
* Init the main window
*/
private void initWindow() {
mainWindow = new JFrame("Towers Of Hanoi");
initContentPanel();
mainWindow.setContentPane(mainContentPanel);
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWindow.setSize(1000, 1000);
mainWindow.setResizable(false);
mainWindow.getContentPane().setBackground(Color.WHITE);
}
/**
* Init the main content panel
*/
private void initContentPanel() {
mainContentPanel = new JPanel(new BorderLayout(50, 50));
JPanel menu = initMenuFrame();
content = initContentFrame();
mainContentPanel.add(menu, BorderLayout.PAGE_START);
mainContentPanel.add(content, BorderLayout.CENTER);
}
private static JPanel initContentFrame() {
JPanel ret = new JPanel(new BorderLayout());
JPanel pegs = new JPanel(new BorderLayout());
pegs.setBackground(Color.WHITE);
ret.setBackground(Color.WHITE);
Peg peg1 = new Peg(25, 500, 1.2);
Peg peg2 = new Peg(50, 500, 1.2);
Peg peg3 = new Peg(0, 500, 1.2);
peg1.addBlocks(pegOneBlocks);
peg2.addBlocks(pegTwoBlocks);
peg3.addBlocks(pegThreeBlocks);
pegs.add(peg1, BorderLayout.LINE_START);
pegs.add(peg2, BorderLayout.CENTER);
pegs.add(peg3, BorderLayout.LINE_END);
ret.add(pegs, BorderLayout.CENTER);
return ret;
}
private Color randomColor() {
int R = (int)(Math.random() * 256);
int G = (int)(Math.random() * 256);
int B = (int)(Math.random() * 256);
Color color = new Color(R, G, B); // random color, but can be bright or
// dull
// to get rainbow, pastel colors
Random random = new Random();
final float hue = random.nextFloat();
final float saturation = 0.9f;// 1.0 for brilliant, 0.0 for dull
final float luminance = 1.0f; // 1.0 for brighter, 0.0 for black
color = Color.getHSBColor(hue, saturation, luminance);
return color;
}
private void initRandomColors() {
for (int i = 0; i < 8; i++) {
randomColors[i] = randomColor();
}
}
private void initBlocks(int numBlocks) {
int startWidth = Block.LONGESTWIDTH;
for (int i = 0; i < numBlocks; i++) {
Block b = new Block((startWidth - (i * 15)), randomColors[i]);
pegOneBlocks.add(b);
}
}
private static void clearContentFrame() {
mainContentPanel.remove(content);
mainContentPanel.repaint();
}
private void clearBlockArrays() {
pegOneBlocks.clear();
pegTwoBlocks.clear();
pegThreeBlocks.clear();
}
public static void reDrawContentFrame() {
content = initContentFrame();
mainContentPanel.add(content, BorderLayout.CENTER);
mainContentPanel.repaint();
}
public static void moveTopBlock(int startPin, int destinationPin) {
Block b = null;
if (startPin == 0) {
b = pegOneBlocks.get(pegOneBlocks.size() - 1);
pegOneBlocks.remove(pegOneBlocks.size() - 1);
}
else if (startPin == 1) {
b = pegTwoBlocks.get(pegTwoBlocks.size() - 1);
pegTwoBlocks.remove(pegTwoBlocks.size() - 1);
}
else if (startPin == 2) {
b = pegThreeBlocks.get(pegThreeBlocks.size() - 1);
pegThreeBlocks.remove(pegThreeBlocks.size() - 1);
}
if (destinationPin == 0) {
pegOneBlocks.add(b);
}
else if (destinationPin == 1) {
pegTwoBlocks.add(b);
}
else if (destinationPin == 2) {
pegThreeBlocks.add(b);
}
reDrawContentFrame();
content.validate();
mainContentPanel.validate();
mainWindow.validate();
}
/**
* Build the menu panel
*
* #return menu panel
*/
private JPanel initMenuFrame() {
JPanel ret = new JPanel(new BorderLayout());
ret.setPreferredSize(menuSize);
// left
JPanel left = new JPanel(new FlowLayout());
left.setPreferredSize(menuSize);
JLabel label = new JLabel("DISCS: 3");
discs = label;
label.setFont(new Font("Serif", Font.BOLD, DISCSTEXTSIZE));
Button down = new Button("Decrease");
down.addActionListener(downButtonListener);
Button up = new Button("Increase");
up.addActionListener(upButtonListener);
left.add(label);
left.add(up);
left.add(down);
// mid
moves = new JLabel("MOVES: 0");
moves.setHorizontalAlignment(JLabel.CENTER);
moves.setFont(new Font("Serif", Font.BOLD, MOVESTEXTSIZE));
// right
JPanel right = new JPanel(new FlowLayout());
Button solve = new Button("Solve");
solve.addActionListener(solveButtonListener);
Button reset = new Button("Reset");
right.add(solve);
right.add(reset);
// sync
JPanel menu = new JPanel(new BorderLayout());
menu.add(left, BorderLayout.LINE_START);
menu.add(moves, BorderLayout.CENTER);
menu.add(right, BorderLayout.LINE_END);
ret.add(menu, BorderLayout.CENTER);
return ret;
}
}
solveButtonListener = new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
solver.solve(discsNumber, 0, 1, 2);
}
};
The problem is that code invoked for any listener is executed on the Event Dispatch Thread (EDT). The EDT is responsible for responding to event and repaint the GUI. The Thread.sleep() method causes the EDT to sleep and as a result the GUI can't repaint itself until all the code has finished executing.
What you need to do is start a separate Thread when you invoke the solver.solve(...) method.
Read the section from the Swing tutorial on Concurrency for more information.
Note, the above suggestion to use a separate Thread is still not a proper solution. Swing was designed to be single Thread, which means that all updates to the state of your GUI and the repainting of the GUI should be done on the EDT. So this would mean you should also be using SwingUtilities.invokeLater() to add code to the EDT for processing. I have never tried doing this when using recursion, so I'm not sure the best way to do this.
My task is to switch two images after capturing mouse click, means when any user clicks on two images both should switch.
but somehow in my code not able to detect the mouse click,
imageAnimal = createImageIcon("Lion", "Lion");
Image scale = imageAnimal.getImage().getScaledInstance(200,200,Image.SCALE_SMOOTH);
imageAnimal = new ImageIcon(scale);
image1Label = new JLabel("", imageAnimal, JLabel.CENTER);
imageMot = createImageIcon("car", "car");
Image scale = imageMot.getImage().getScaledInstance(200,200,Image.SCALE_SMOOTH);
imageMot = new ImageIcon(scale);
image1Label = new JLabel("", imageMot, JLabel.CENTER);
---Code to catch mouse event
public void switch() {
abstract class MouseListener implements ActionListener {
public void actionPerformed(MouseEvent event){
boolean clicked = false;
JPanel imageClicked1;
JPanel imageClicked2 = (JPanel) event.getSource();
int numClicks = 0;
for(int i = 0; i < temp.size(); i++)
{
if(clicked)
{
numClicks++;
imageClicked1 = (JPanel) event.getSource();
if(numClicks == 2)
{
switchImages(imageClicked1, imageClicked2);
}
}
MAINpanel.repaint();
MAINpanel.revalidate();
}
}
public void switchImages(JPanel img1, JPanel img2)
{
//ArrayList<JPanel>sorted = new ArrayList<JPanel>();
JPanel t;
JPanel posValue, nextValue;
for(int i = 0; i < temp.size(); i++)
{
for(int k = 1; k < temp.size(); k++)
{
if(temp.get(i) == img1 && temp.get(k) == img2)
{
posValue = temp.get(k);
nextValue = temp.get(i);
t = temp.get(k);
posValue = temp.get(i);
nextValue = t;
}
}
}
for(int i = 0; i < 5; i++)
{
mainPanel.add(temp.get(i), BorderLayout.CENTER);
}
}
}
}
For better help sooner, post a Minimal, Complete, and Verifiable example or Short, Self Contained, Correct Example. See example below.
One way to get image(s) for an example is to hot link to images seen in this Q&A. See example below.
It seems to make no sense to declare and add the mouse listener within the switch method. But maybe an MCVE / SSCCE would make it clear.
MAINpanel.repaint(); Ouch.. Use labels to display the images! On switch, swap their ImageIcon instances. See example below.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.*;
public class ImageSwitch {
private JComponent ui = null;
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
ImageIcon imageIconA;
ImageIcon imageIconB;
ImageSwitch() {
try {
initUI();
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
private void switchImages() {
if (label1.getIcon().equals(imageIconA)) {
label1.setIcon(imageIconB);
label2.setIcon(imageIconA);
} else {
label1.setIcon(imageIconA);
label2.setIcon(imageIconB);
}
}
public void initUI() throws MalformedURLException {
if (ui!=null) return;
ui = new JPanel(new GridLayout(0,1,2,2));
ui.setBorder(new EmptyBorder(4,4,4,4));
imageIconA = new ImageIcon(new URL("https://i.stack.imgur.com/OVOg3.jpg"));
imageIconB = new ImageIcon(new URL("https://i.stack.imgur.com/lxthA.jpg"));
label1.setIcon(imageIconA);
label2.setIcon(imageIconB);
ui.add(label1);
ui.add(label2);
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
switchImages();
}
};
label1.addMouseListener(mouseListener);
label2.addMouseListener(mouseListener);
}
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) {
}
ImageSwitch o = new ImageSwitch();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
Somehow the Jprogressbar is moving, but not in time with the code in the background method thru Swingworker. The task is done in another Thread, it works.
I tried to use a while loop. println is not printing at the end.
?
Thanks
// this is part of a time consuming task
for (int j = 0; j < ba.length; j++) {
String s1 = Integer.toHexString((ba[j] & 255) | 256).substring(1);
s2 += s1;
} // instead of the while loop, now is working a for loop.
for(int z = 0; z <= 100; z++) {
Thread.sleep(50);
setProgress(z);
}
/*int z = 0;
while(z <= 100) {
z++;
Thread.sleep(50);
setProgress(z); */
}
System.out.println(s2);
here is the full example to execute.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class PbTest extends JPanel implements ActionListener, PropertyChangeListener {
private JProgressBar progressBar;
private JButton startButton;
private JTextArea taskOutput;
private Task task;
private String nameString;
private String s2;
private int timeFlow;
private boolean done;
private int z = 0;
class Task extends SwingWorker<Void, Void> {
/*
* Main task. Executed in background thread.
*/
#Override
public Void doInBackground() throws InterruptedException {
done = false;
try {
FileInputStream fis = new FileInputStream("timeConsuming.iso");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] b = new byte[1024];
int i;
while ((i = fis.read(b)) >= 0) {
md.update(b, 0, i);
}
while (i != -1)
fis.close();
byte[] ba = md.digest();
// while loop correct?
while (ba.length <= 16) {
int z = 0;
while (z <= 100) {
z++;
Thread.sleep(50);
setProgress(z);
}
}
// System.out.print(i);
for (int j = 0; j < ba.length; j++) {
String s1 = Integer.toHexString((ba[j] & 255) | 256).substring(1);
s2 += s1;
}
System.out.println(s2);
} catch (IOException | NoSuchAlgorithmException ex) {
Logger.getLogger(PbTest.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
} // System.out.println(javax.swing.SwingUtilities.isEventDispatchThread());
/*
* Executed in event dispatching thread
*/
#Override
public void done() {
Toolkit.getDefaultToolkit().beep();
startButton.setEnabled(true);
setCursor(null); // turn off the wait cursor
taskOutput.append("Done!\n");
done = true;
}
}
public PbTest() {
super(new BorderLayout());
// Create the demo's UI.
startButton = new JButton("Start");
startButton.setActionCommand("start");
startButton.addActionListener(this);
progressBar = new JProgressBar(0, 100);
// progressBar.setMinimum(0);
// progressBar.setMaximum(100);
progressBar.setValue(0);
progressBar.setStringPainted(true);
taskOutput = new JTextArea(5, 20);
taskOutput.setMargin(new Insets(5, 5, 5, 5));
taskOutput.setEditable(false);
JPanel panel = new JPanel();
panel.add(startButton);
panel.add(progressBar);
add(panel, BorderLayout.PAGE_START);
add(new JScrollPane(taskOutput), BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
/**
* Invoked when the user presses the start button.
*/
public void actionPerformed(ActionEvent evt) {
// progressBar.setIndeterminate(true);
startButton.setEnabled(false);
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// Instances of javax.swing.SwingWorker are not reusuable, so
// we create new instances as needed.
task = new Task();
task.addPropertyChangeListener(this);
task.execute();
}
/**
* Invoked when task's progress property changes.
*/
public void propertyChange(PropertyChangeEvent evt) {
//this code block would work better with more gui components ?!
/*if ("progress".equals(evt.getPropertyName())) {
int progress = (Integer) evt.getNewValue();
progressBar.setValue(progress);
ls.setText(String.format(
"Completed %d%% of task.\n", task.getProgress()));
} */
if (!done) {
int progress = task.getProgress();
progressBar.setValue(progress);
System.out.println(String.format("Completed %d%% of task.\n", task.getProgress()));
}
}
/**
* Create the GUI and show it. As with all GUI code, this must run on the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("ProgressBarDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
JComponent newContentPane = new PbTest();
newContentPane.setOpaque(true); // content panes must be opaque
frame.setContentPane(newContentPane);
// Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I have written this code for a simple music player, the problem is that when I click openLabel and open a song and then when I pause it by clicking playLabel the program stops execution (program hangs).
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.Random;
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.filechooser.FileNameExtensionFilter;
public class A extends MouseAdapter implements ChangeListener, Runnable {
private ImageIcon playImage = new ImageIcon(getClass().getResource("Images/play.png"));
private ImageIcon pauseImage = new ImageIcon(getClass().getResource("Images/pause.png"));
private ImageIcon openImage = new ImageIcon(getClass().getResource("Images/open.png"));
private JLabel playLabel = new JLabel(playImage);
private JLabel openLabel = new JLabel(openImage);
public JFrame frame = new JFrame();
public JPanel colorPanel = new JPanel();
private enum Status {ON,OFF,PAUSE,END};
private Status playStatus=Status.OFF;
private JSlider slider = new JSlider();
public Clip songClip;
Thread screenThread = new Thread(this);
public static void main(String arg[]) throws Exception {
new A();
}
public A() throws Exception {
setFrame();
setComponents();
}
public void setFrame() {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setCursor(new Cursor(Cursor.HAND_CURSOR));
frame.getContentPane().setBackground(Color.BLACK);
frame.setVisible(true);
}
public void setComponents() {
slider.setBounds(0,640,1000,15);
slider.setBackground(Color.BLACK);
slider.addChangeListener(this);
slider.setValue(0);
playLabel.setBounds(450,665,100,100);
playLabel.addMouseListener(this);
openLabel.setBounds(540,690,60,60);
openLabel.addMouseListener(this);
colorPanel.setBackground(Color.BLACK);
colorPanel.setBounds(0,100,1500,500);
frame.add(openLabel);
frame.add(playLabel);
frame.add(colorPanel);
frame.add(slider);
}
public void mouseClicked(MouseEvent clicked) {
if (clicked.getSource() == openLabel) {
openLabel.setIcon(openImage);
open();
}
else if (clicked.getSource()==playLabel && playStatus != Status.OFF) {
if (playStatus == Status.PAUSE) {
songClip.start();
screenThread.resume();
playStatus=Status.ON;
playLabel.setIcon(pauseImage);
}
else if (playStatus == Status.ON) {
songClip.stop();
screenThread.suspend();
playStatus=Status.PAUSE;
playLabel.setIcon(playImage);
}
else if (playStatus==Status.END) {
songClip.setMicrosecondPosition(0);
slider.setValue(0);
songClip.start();
screenThread.resume();
playStatus = Status.ON;
playLabel.setIcon(pauseImage);
}
}
}
public void stateChanged(ChangeEvent e) {
if (playStatus != Status.OFF) {
JSlider jslider = (JSlider)e.getSource();
int position = jslider.getValue();
songClip.setMicrosecondPosition(position * 1000000);
}
}
public void open() {
JFileChooser chooseSong = new JFileChooser();
chooseSong.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooseSong.setFileFilter(new FileNameExtensionFilter(null, "wav"));
int chooseButton = chooseSong.showOpenDialog(null);
File songPath = chooseSong.getSelectedFile();
if ( (chooseButton!=JFileChooser.CANCEL_OPTION) && (songPath!=null) && (songPath.getName() != null) ) {
try {
playLabel.setIcon(pauseImage);
if (playStatus != Status.OFF)
songClip.close();
AudioInputStream songFile = AudioSystem.getAudioInputStream(songPath);
songClip = AudioSystem.getClip();
songClip.open(songFile);
int clipLength = (int)(songClip.getMicrosecondLength() / 1000000);
slider.setMinimum(0);
slider.setMaximum(clipLength);
songClip.start();
if (playStatus == Status.OFF)
screenThread.start();
else if (playStatus != Status.OFF)
screenThread.resume();
playStatus=Status.ON;
}
catch(Exception exp) {
Toolkit.getDefaultToolkit().beep();
JOptionPane.showMessageDialog(null, String.format("ERROR = %s",exp.getClass()));
System.exit(0);
}
}
}
public void run() {
while (true) {
colorPanel.setBackground(new Color(new Random().nextInt(256), new Random().nextInt(256), new Random().nextInt(256)));
if (songClip.getMicrosecondPosition() == songClip.getMicrosecondLength()) {
screenThread.suspend();
playStatus=Status.END;
playLabel.setIcon(playImage);
}
}
}
}
This method has been deprecated, as it is inherently deadlock-prone.
This is the reason that is given for the deprecation of Thread.stop(), .suspend() and .resume(). As you are using these in your code it could be the problem.
You are calling screenThread.suspend(); in the block that responds to clicking the play/pause button. Thread methods suspend() and resume() are deadlock prone - that is, using them often causes hard-to-diagnose issues like the one you're having.
You need to remove the use of these methods by instead polling a variable, as described on this page.
I'm new in Java and I need your help in implementing a GUI. Below is a Guessing Game code. It works.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class GuessGame extends JFrame {
private JTextField guessTextField;
private JLabel introLabel, guessLabel, clueLabel;
private JButton enterB, playAgainB;
private int randomNumber;
public GuessGame() {
super("Guessing Game!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Creates components
enterB = new JButton("Guess");
playAgainB = new JButton("Quit");
introLabel = new JLabel("I have a number between 1 and 1000.");
guessLabel = new JLabel("Can you guess my number? Please enter your guess:");
clueLabel = new JLabel("");
// comment2 = new JLabel(" ");
guessTextField = new JTextField(5);
//content pane
Container c = getContentPane();
setLayout(new FlowLayout());
//adding component to the pane
c.add(introLabel);
c.add(guessLabel);
c.add(guessTextField);
//c.add(comment2);
c.add(enterB);
c.add(playAgainB);
c.add(clueLabel);
//enterB.setMnemonic('G');
//playAgainB.setMnemonic('Q');
setSize(350, 200);
setLocationRelativeTo(null);
setVisible(true);
//setResizable(false);
initializeNumber();
//creating the handler
GuessButtonHandler ghandler = new GuessButtonHandler(); //instantiate new object
enterB.addActionListener(ghandler); // add event listener
QuitButtonHandler qhandler = new QuitButtonHandler();
playAgainB.addActionListener(qhandler);
}
private void initializeNumber() {
randomNumber = new Random().nextInt(1000) + 1;
System.out.println(randomNumber);
}
class QuitButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
class GuessButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
int getUserInput;
int diff;
int Difference;
try {
getUserInput = Integer.parseInt(guessTextField.getText().trim());
if (getUserInput == randomNumber) {
clueLabel.setText(" Correct!");
}
if (getUserInput > randomNumber) {
clueLabel.setText(" Too High");
} else {
clueLabel.setText(" Too Low");
}
}
catch (NumberFormatException e1) {
clueLabel.setText("Enter a VALID number!");
}
}
}
public static void main(String args[]) {
//instantiate gueesgame object
GuessGame app = new GuessGame();
}
}
However, the color of the window should change into red or blue. Please help me with this code. I'm new in Java and it's syntax. I'd really appreciate your help. Thank you!
You could use:
current = Integer.parseInt(guessTextField.getText().trim());
if (!firstTime) {
if (getUserInput > previous) {
getContentPane().setBackground(Color.red);
} else {
getContentPane().setBackground(Color.blue);
}
}
where firstTime and previous are class member variables.
Don't forget to assign previous if the getUserInput == randomNumber is not met.
Update:
You are setting the background blue twice:
if (getUserInput < randomNumber) {
clueLabel.setText("Too Low");
getContentPane().setBackground(Color.blue); <------ remove this extra call
previous = getUserInput;
}
A code is better than thousand words.....
if (current_Input > previous) {
c.setBackground(Color.red);
} else {
c.setBackground(Color.blue);
}