SwingUtilities.invokeLater() displaying just during one frame - java

I'm using Swing in order to create a little java 2D game. I only try to display an image. Since i'm not on the EDT I'm using SwingUtilities.invokeLater() to do the stuff. When I use it, image is not displayed (in fact it's displayed during few miliseconds and disapear).
When I don't use SwingUtilities.invokeLater() the image is correctly displayed but I need to use invokeLater().
Here's my basic code :
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
final BreizhFrame frame = new BreizhFrame();
File imgFile = new File("src/test/lvl1-800x450.jpg");
System.out.println(String.valueOf(imgFile.exists()));
System.out.println(SwingUtilities.isEventDispatchThread());
Image i;
try {
i = ImageIO.read(imgFile);
frame.getGraphics().drawImage(i, 0, 0, null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (InvocationTargetException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Any idea ?
Thanks.

That's not how you do it in Java. Yes, you are drawing the image, but after a while the control gets invalidated and it's re-drawn without your image.
This tutorial should help you

Related

Java Thread.sleep() within a for loop

public void playPanel() throws IOException{
for(int i = 0; i<listData.size(); i++){
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ascii.setText(listData.get(i));
}
}
What I'm trying to do is play through the listData ArrayList type, which was copied from the ascii JTextArea. Its supposed to be an animation, so when they hit play the function displays the first slide, waits a second, then the next slide, etc.
When I run this the only thing that happens is a pause with nothing on the screen changing until it displays only the final slide. I'm not sure what's wrong with it
You should never call Thread.sleep(...) on the Swing event thread unless your goal is to put the entire application to sleep, rendering it useless. Instead, get rid of the for loop, and "loop" using a Swing Timer. Something like this should work, or be close to a functioning solution (caveat: code has not been compiled nor tested):
int delay = 1000;
new Timer(delay, new ActionListener() {
private int i = 0;
#Override
public void actionPerformed(ActionEvent e) {
if (i < listData.size()) {
ascii.setText(listData.get(i));
} else {
((Timer) e.getSource()).stop();
}
i++;
}
}).start();

How to add background music to gamescene in andengine

bg music plays on splash,menu and gamescene when i had put the below code, but i want to make bg music to play only on my gamescene, can you please help me. Thank you.
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws IOException
{
MusicFactory.setAssetBasePath("mfx/");
try {
music = MusicFactory.createMusicFromAsset(mEngine
.getMusicManager(), this, "abcd.wav");
music.setLooping(true);
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ResourcesManager.prepareManager(mEngine, this, camera, getVertexBufferObjectManager());
pOnCreateResourcesCallback.onCreateResourcesFinished();
}
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws IOException
{
music.play();
SceneManager.getInstance().createSplashScene(pOnCreateSceneCallback);
}
I usually use music.pause() and music.resume() (because after stop the play does not work any more, I do not know why). When you leave a scene, you can call music.pause(). When you enter a scene, you can call music.resume();

Java Threading Issue with run()

I have 2 classes defined below:
public class TextsManager extends Thread {
LinkedList<String> lstOfPendingStr = new LinkedList<String>();
boolean stopLoop = false;
JTextArea txtArea;
public void run()
{
while (!stopLoop)
{
while (!lstOfPendingStr.isEmpty())
{
String tmp = lstOfPendingStr.getFirst();
this.txtArea.append(tmp);
lstOfPendingStr.removeFirst();
}
try {
Thread.sleep(0); // note: I had to force this code
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void AddNewStr(String newStr)
{
this.lstOfPendingStr.add(newStr);
}
}
And
public class ClientApp {
private JFrame frame;
private JTextField textField;
private JTextArea textArea;
static private TextsManager txtManager;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ClientApp window = new ClientApp();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ClientApp() {
initialize();
/*
* Client app
*/
txtManager = new TextsManager(textArea);
txtManager.start();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
textArea = new JTextArea();
textField = new JTextField();
textField.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
txtManager.AddNewStr(textField.getText() + "\n");
textField.setText("");
}
}
});
}
}
The program will read User Input from textField, pass it into TextsManager.lstOfPendingStr. Then, on each loop inside TextsManager.run(), it will check for existed members in lstOfPendingStr and output them via txtArea.
The problem is that if I removed the code Thread.sleep(0) inside run(), the run() then apparently stopped working. Despite lstOfPendingStr had been successfully updated with new elements, codes inside the loop while(!lstOfPendingStr.isEmpty()) would not ever to be called.
I put hard codes such as System.out.println or Thread.sleep(0) (as in the provided code) inside the while(!stopLoop), then it worked fine.
Although, I managed to solve the problem by forcing the thread to sleep for a few miliseconds, I want to know the reason behind this issue.
I appreciate your wisdom.
Regard :)
You have a couple of problems.
You are calling methods on lstOfPendingStr from two threads, but initialized it with LinkedList, which is not thread-safe. You should use a thread safe class, LinkedBlockingQueue seems the best options as far as I understood from your code.
Inside the thread you are calling JTextArea#append(). As all AWT/Swing methods, you can not call them from arbitrary threads, but only from the AWT thread. Wrap the call inside an invokeLater block.
The fact that sleep appears to make your code work is just a sign of the concurrency problems.

Method not run in java listener actionPerformed

I have a method myFuncs.requestData() that works standalone. It subcribes to listen for data and sets ReadyTxt="TRUE" when the listener has received all the data - which comes in multiple callbacks.
But, when I try to to check DataReady within the actionPerformed method that is attached to a button - it is unset because it appears that myFuncs.requestData() is only processed/run AFTER we come out of actionPerformed.
By "standalone" I mean that if I put no function at ##HERE## then the requestData() works after actionPerformed has completed.
How can I make sure it runs and wait for it to finish at the point ##HERE##?
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
writePaneln("BUTTON PRESSED "+myFuncs.ReadyTxt);
myFuncs.requestData();
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
}
writePaneln("REQUESTED "+myFuncs.ReadyTxt);
##HERE##
}
Threaded version:
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
writePaneln("BUTTON PRESSED "+myFuncs.ReadyTxt);
Thread thread = new Thread() {
public void run(){
myFuncs.requestData();
}
};
thread.start();
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
}
writePaneln("REQUESTED "+myFuncs.ReadyTxt);
##HERE##
}
simplified requestData():
public void requestData() {
DataReady="FALSE"
this.dataSubscription.setListener(this);
}
#Override
public void dataUpdated(List<long> updatedData) {
if (updatedData.size() <= 1 ){
this.dataSubscription.destroy();
writePaneln("In dataUpdated DataReady num: "+Dates.size());
DataReady="TRUE";
return;
}
for (long l: updatedData){
writePaneln(l);
Dates.add(l);
}
}
Answer seems to lie in using TimerTask to time a task for AFTER actioPerformed has completely finished becuase it seems to be on single thread.
http://enos.itcollege.ee/~jpoial/docs/tutorial/essential/threads/timer.html

frame shows black screen

btnnew.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
System.out.println("Hello");
packetListener.listener();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
I get a black screen when it runs. But when the packetListener.listener(); calls in the constructor it shows.
Can you please explain why this is happening?
Code that is executed from a listener executes on the EDT. I'm guessing that the packetListner.listener() method blocks in which case the GUI will freeze. You should not be blocking the EDT.
Read the section from the Swing tutorial on Concurrency for a full description of this problem and a solution.
I think the packetListener.listener(); method performs some complex operation which blocks your UI.
Better create a thread for listening the packet.
ie,use it like this
try {
System.out.println("Hello");
new Thread(new Runnable() {
public void run() {
packetListener.listener();
}
}).start();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Hope this helps you

Categories

Resources