Display multiple JFrame in a loop by click the button - java

I want to display several JFrame with the delay of several seconds in a loop by clicking on a button. Frames come but they are quite white, have the title but they don't have body (Buttons are not visible). Without loop hence once calling a JFrame, No problem. What should I do?
Do you have another idea?
Main class:
public class Game3 {
game3.NewJFrame2 start_frame = new game3.NewJFrame2();
public Game3() throws InterruptedException {
this.start_frame.setSize(500,500);
start_frame.setVisible(true);
final JButton enter = new JButton("Enter");
enter.setBounds(10,10,50,50);
start_frame.add(enter);
enter.setVisible(true);
enter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
start_frame.dispose();
try {
new Play();
} catch (InterruptedException ex) {
Logger.getLogger(Game3.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public static void main(String[] args) throws InterruptedException {
new Game3();
}
}
and Play class:
public class Play {
game3.NewJFrame2 start_frame1 = new game3.NewJFrame2();
public Play() throws InterruptedException {
this.select_rnd_word();
}
public static void select_rnd_word() throws InterruptedException {
for (int i = 0; i < 5; i++) {
game3.NewJFrame2 frame = new game3.NewJFrame2();
frame.setSize(200, 200);
JButton b = new JButton("A");
b.setBounds(0, 0, 30, 30);
frame.add(b);
b.setVisible(true);
frame.setVisible(true);
Thread.sleep(2000);
frame.dispose();
}
}
}
Follow code has this problem too:
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 3; i++) {
new Game3();
}
}

One idea is moving 'new Play() ' to out of ActionListener.
enter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
start_frame.dispose();
}
});
Thread.sleep(10000);
start_frame.dispose();
new Play();

By making a new thread, this problem is solved.
enter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
start_frame.dispose();
new Thread() {
#Override
public void run() {
try {
new Play();
} catch (InterruptedException ex) {
Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
}
});
for more information: Event Dispatch Thread

Related

Java join doesn't wait for thread exit

I'm trying to synchronize this code: what I want is that the class Gioca waits until the class Gioco calls the method fine (fine should stop the thread) but as the Gioca class invokes the run method it prints on the console the string "Fine" even thow the class Gioco hasn't called the method fine() yet.
public class Gioca implements Runnable
{
private int vite;
private int recuperi;
public Gioca()
{
vite=3;
recuperi=0;
}
public void gioca()
{
Thread t=new Thread(new Gioco(vite));
try
{
t.start();
t.join();
}
catch (Exception ex) {}
System.out.println("Fine");
}
#Override
public void run()
{
gioca();
}
}
public class Gioco extends Canvas implements ActionListener, KeyListener, Runnable
{
private int direzione;
private Timer timer;
private JFrame f;
private int vite;
private int velocità;
private int spazio;
private Personaggio p;
private int pos;
private LinkedList<Ostacolo> o;
private Random r;
private int po;
private Image imm1=new ImageIcon(this.getClass().getResource("images/sfondo.jpg")).getImage();
private Image imm2=new ImageIcon(this.getClass().getResource("images/cuore.png")).getImage();
public Gioco(int vite)
{
r=new Random();
try
{
File file=new File("images/punteggio.txt");
Scanner scanner=new Scanner(file);
spazio=scanner.nextInt();
}
catch (Exception e) {}
direzione=3;
this.vite=vite;
o=new LinkedList();
for(int i=0; i<20; i++)
o.add(new Ostacolo(Math.abs(400*i)+1000));
p=new Personaggio();
this.velocità=2;
timer=new Timer(10, this);
f=new JFrame("Gioco");
f.setSize(1000, 700);
f.setResizable(false);
f.setLocation(200,200);
f.add(this);
f.addKeyListener(this);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent ae)
{
if(direzione==2)
{
velocità-=2;
if(velocità<2)
velocità=2;
}
if(direzione==1)
p.setY(5);
if(direzione==0)
p.setY(-5);
spazio+=velocità;
if(spazio%1000<10)
velocità++;
pos=(pos+velocità)%4500;
po=-pos;
for(int i=0; i<20; i++)
{
o.get(i).muovi(velocità);
if(o.get(i).getX()<-100)
{
o.remove(i);
o.add(new Ostacolo(i*400));
}
}
verificaCollisioni();
repaint();
}
public void verificaCollisioni()
{
for(int i=0; i<20; i++)
{
if(o.get(i).getX()>300 && o.get(i).getX()<350)
{
int r[]=o.get(i).getDimensioni();
if(r[0]<p.getY() && r[1]>p.getY())
{
}
else
fine();
}
}
}
private void fine()
{
try
{
Thread.sleep(3000);
}
catch(Exception e){}
timer.stop();
try
{
File file=new File("images/punteggio.txt");
file.createNewFile();
FileOutputStream f=new FileOutputStream(file);
f.flush();
String sPunteggio=String.valueOf(spazio);
byte[] scrivi=sPunteggio.getBytes();
f.write(scrivi);
}
catch(Exception e){}
f.dispose();
}
#Override
public void keyPressed(KeyEvent ke)
{
int c=ke.getKeyCode();
if(c == 40)
direzione=1;
if(c == 38)
direzione=0;
if(c==32)
direzione=2;
}
public void paint(Graphics g)
{
Image workspace=createImage(getWidth(),getHeight());
Graphics2D buffer=(Graphics2D) workspace.getGraphics();
buffer.drawImage(imm1, po, 0, this);
buffer.setColor(new Color(242, 54, 33));
buffer.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 20));
buffer.drawString(""+(spazio/100), 10, 20);
buffer.drawImage(imm2, 940, 4, this);
buffer.setColor(new Color(13, 226, 13));
buffer.drawString(""+vite, 920, 20);
buffer.drawImage(p.getImage(), 300, p.getY(), this);
for(int i=0; i<20; i++)
{
Ostacolo tmp=o.get(i);
buffer.drawImage(tmp.getImage(), tmp.getX(),tmp.getY(), this);
}
Graphics2D g2=(Graphics2D)g;
g2.drawImage(workspace, 0, 0, this);
buffer.dispose();
}
public void update(Graphics g)
{
paint(g);
}
public void keyReleased(KeyEvent ke) {direzione=3;}
public void keyTyped(KeyEvent ke) {}
#Override
public void run()
{
f.setVisible(true);
timer.start();
}
}
This code, using the same instructions, works well
public class Campana implements Runnable{
private String suono;
private int volte;
public Campana(String suono,int volte)
{
this.suono =suono;
this.volte=volte;
}
public void run()
{
for(int i=0;i<volte;i++) {
System.out.println((i+1)+" "+suono);
}
}
}
public class Suona {
public static void main(String args[]){
Thread campana1=new Thread(new Campana("din", 5));
Thread campana2=new Thread(new Campana("don", 5));
Thread campana3=new Thread(new Campana("dan", 5));
try {
campana1.start();
campana1.join();
campana2.start();
campana2.join();
campana3.start();
campana3.join();
} catch (InterruptedException ex) {
Logger.getLogger(Suona.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
t.join(); in this case waits for run in Giocoto terminate. That method terminates after
f.setVisible(true);
timer.start();
have completed, which will be very fast since Timer will run actionPerformed a different thread from the one that timer.start(); is called in. It does not wait until the timer has been stopped. You can fix this by introducing some form of synchronization in your run method. I would not recommend a while loop since that will waste resources on running the loop. Instead consider using a CountDownLatch (javadoc link):
Add this to Gioco:
private final CountDownLatch doneSignal = new CountDownLatch(1);
At the end of fine() call doneSignal.countDown(). And finally change your run() method in Gioco to something like this:
#Override
public void run()
{
f.setVisible(true);
timer.start();
try {
doneSignal.await();
} catch (InterruptedException ex) {}//Logg this or something. Shouldn't really ever happen.
}

GUI from separate thread

Trying to create two independent forma that could run code in separate threads. Code below creates two forms , but if I press button on one of them I can't do the same with another. It simply not executes code. How to make two simple forms that could run non blocking each other?
public class MnemonicEx1 extends JFrame
{
public JeasiHandler jh = null;
private Log log = Log.getLog();
public MnemonicEx1()
{
initUI();
}
private void initUI()
{
JButton btnAuth = new JButton("1");
btnAuth.addActionListener(new ActionListener()
{
// #Override
public void actionPerformed(ActionEvent e)
{
System.out.println("starting");
for (int i = 0; i < 1000; i++)
{
try
{
Thread.sleep(100);
System.out.println(Integer.toString(i));
} catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
System.out.println("finishing");
}
});
btnAuth.setMnemonic(KeyEvent.VK_B);
//createLayout(btnAuth);
createLayout(btnAuth);
setTitle("****");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createLayout(JComponent authButn)
{
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
int i = 0;
gl.setHorizontalGroup(
gl.createSequentialGroup()
.addComponent(authButn)
);
gl.setVerticalGroup(gl.createParallelGroup()
.addComponent(authButn)
);
pack();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
MnemonicEx1 ex = new MnemonicEx1();
ex.setVisible(true);
}
});
EventQueue.invokeLater(new Runnable()
{
public void run()
{
MnemonicEx1 ex = new MnemonicEx1();
ex.setVisible(true);
}
});
}
}
UPD
Changed main() by creating separate threads , but got the same result
public static void main(String[] args)
{
new Thread (new Runnable()
{
public void run()
{
MnemonicEx1 ex = new MnemonicEx1();
ex.setVisible(true);
}
}).start();
new Thread(new Runnable()
{
public void run()
{
MnemonicEx1 ex = new MnemonicEx1();
ex.setVisible(true);
}
}).start();
}
#Nadir is more or less right.
You are launching both windows in the same thread represented by EventQueue.
I think swing programmers prefer to use SwingUtilities for opening new frame applications but you can achieve your goal changing your method actionPerformed
// #Override
public void actionPerformed(ActionEvent e) {
new Thread() {
#Override
public void run() {
System.out.println("starting");
for (int i = 0; i < 1000; i++)
{
try
{
Thread.sleep(100);
System.out.println(Integer.toString(i));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("finishing");
}
}.start();
That way you'll have two different threads. In your original version you only had one thread.
UPDATED: Change also your main method
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MnemonicEx1 ex = new MnemonicEx1();
ex.setVisible(true);
}
});
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
MnemonicEx1 ex = new MnemonicEx1();
ex.setVisible(true);
}
});
}

JFrame and while loop

How do I break a while loop if I click on my jframe shutdown? I 'm making a clicker that needs to be stopped at some point, but it'll just continue clicking even tho the exit has been pressed.
public class ClickWindow {
private JFrame frame;
private static Clicker click;
private static long currTime;
private static long totalTime;
private JTextField textField;
private static int textFieldValue = 0;
private static Boolean Bool = true;
/**
* Launch the application.
*/
public static void main(String[] args) throws InterruptedException {
click = new Clicker();
ClickWindow window = new ClickWindow();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ClickWindow() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setBounds(100, 100, 289, 90);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton btnNewButton_1 = new JButton("Press Space");
btnNewButton_1.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
Bool = false;
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
if(textFieldValue == 0){
textFieldValue = 250;
}
try {
while (Bool) {
click.click();
textFieldValue = Integer.parseInt(textField.getText());
Thread.sleep(textFieldValue);
}
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
btnNewButton_1.setBounds(10, 25, 110, 23);
frame.getContentPane().add(btnNewButton_1);
textField = new JTextField();
textField.setBounds(127, 25, 141, 23);
frame.getContentPane().add(textField);
textField.setColumns(10);
}
public void windowClosing(WindowEvent event) {
Bool = false;
}
}
Clicker class
public class Clicker{
public static void click() throws AWTException{
Robot bot = new Robot();
bot.mousePress(InputEvent.BUTTON1_MASK);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
}
}
Edited with the full code.
You should define the defaultCloseOperation for your JFrame:
JFrame myFrame = new JFrame("MyFrame");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
If you set the defaultCloseOperation, hitting the close button will trigger a call to System exit:
public static void main(String[] args)
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
JFrame myFrame = new JFrame("MyFrame");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//...add components here
myFrame.pack();
myFrame.setVisible(true);
}
catch (Exception e)
{
System.exit(-1);
}
}
});
}
If you want to shutdown the entire application you can just do this:
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
This will shutdown your application after the Jframe was closed.
You can also call System.exit(0) in your windowClosing method or whenever you want to shutdown your application
instead of adding the keyListener to your JButton try having your JFrame, i.e. ClickWindow implement it. I think this would work.

Swing invokeLater() method not working

In my main Swing frame I have this method:
public void receiveCommand(String command) {
if (command.equals("enable")) {
Runnable enable = new Runnable() {
public void run() {
button1.setEnabled(true);
button1.revalidate();
button1.repaint();
}
};
SwingUtilities.invokeLater(enable);
}
basically, I'm trying to update the GUI (enable the button button1) from outside by calling the receiveCommand() method.
However this doesn't work, i.e button1 is still disabled. What did I do wrong here?
EDIT:
Here is the declaration of button1:
private javax.swing.JButton button1;
button1.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
button1.setEnabled(false);
button1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
button1ActionPerformed(evt);
}
});
Both button1 and the receiveCommand method are in this Game class:
public class Game extends javax.swing.JFrame
The method is called from another class:
gameUI.receiveCommand("enable"); //gameUI is a Game object
EDIT 2: Thank you for all your help! It turns out to be a wrong reference after all, so all I did was trying to update the GUI of a wrong frame that hadn't been set visible yet. Silly me
So anyway, this works.
public class TestInvokeLater {
public static void main(String[] args) {
new TestInvokeLater();
}
public TestInvokeLater() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBorder(new EmptyBorder(12, 12, 12, 12));
final JButton runMe = new JButton("Run me");
runMe.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
runMe.setEnabled(false);
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
runMe.setEnabled(true);
}
});
}
}).start();
}
});
setLayout(new GridBagLayout());
add(runMe);
}
}
}

JFrame.setVisible(false) and Robot.createScreenCapture timing

I'm trying to capture the screen without including my application's window. To do this I first call setVisible(false), then I call the createScreenCapture method, and finally I call setVisible(true). This isn't working however and I'm still getting my applications window in the screen capture. If I add a call to sleep this seems to resolve the issue, but I know this is bad practice. What is the right way to do this?
Code:
setVisible(false);
BufferedImage screen = robot.createScreenCapture(rectScreenSize);
setVisible(true);
Have you tried to use SwingUtilities.invokeLater() and run the capture inside of the runnable passed as an argument? My guess is that the repaint performed to remove your application is performed right after the end of the current event in the AWT-EventQueue and thus invoking the call immediately still captures your window. Invoking the createCapture in a delayed event through invokeLater should fix this.
you have to delay this action by implements Swing Timer, for example
import javax.imageio.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
public class CaptureScreen implements ActionListener {
private JFrame f = new JFrame("Screen Capture");
private JPanel pane = new JPanel();
private JButton capture = new JButton("Capture");
private JDialog d = new JDialog();
private JScrollPane scrollPane = new JScrollPane();
private JLabel l = new JLabel();
private Point location;
private Timer timer1;
public CaptureScreen() {
capture.setActionCommand("CaptureScreen");
capture.setFocusPainted(false);
capture.addActionListener(this);
capture.setPreferredSize(new Dimension(300, 50));
pane.add(capture);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(pane);
f.setLocation(100, 100);
f.pack();
f.setVisible(true);
createPicContainer();
startTimer();
}
private void createPicContainer() {
l.setPreferredSize(new Dimension(700, 500));
scrollPane = new JScrollPane(l,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setBackground(Color.white);
scrollPane.getViewport().setBackground(Color.white);
d.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
d.add(scrollPane);
d.pack();
d.setVisible(false);
d.addWindowListener(new WindowListener() {
public void windowOpened(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
f.setVisible(true);
}
public void windowClosed(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
});
}
private void startTimer() {
timer1 = new Timer(1000, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
capture.doClick();
f.setVisible(false);
}
});
}
});
timer1.setDelay(500);
timer1.setRepeats(false);
timer1.start();
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("CaptureScreen")) {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // gets the screen size
Robot r;
BufferedImage bI;
try {
r = new Robot(); // creates robot not sure exactly how it works
Thread.sleep(1000); // waits 1 second before capture
bI = r.createScreenCapture(new Rectangle(dim)); // tells robot to capture the screen
showPic(bI);
saveImage(bI);
} catch (AWTException e1) {
e1.printStackTrace();
} catch (InterruptedException e2) {
e2.printStackTrace();
}
}
}
private void saveImage(BufferedImage bI) {
try {
ImageIO.write(bI, "JPG", new File("screenShot.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
private void showPic(BufferedImage bI) {
ImageIcon pic = new ImageIcon(bI);
l.setIcon(pic);
l.revalidate();
l.repaint();
d.setVisible(false);
//location = f.getLocationOnScreen();
//int x = location.x;
//int y = location.y;
//d.setLocation(x, y + f.getHeight());
d.setLocation(150, 150);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
d.setVisible(true);
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
CaptureScreen cs = new CaptureScreen();
}
});
}
}

Categories