Message Boxes wont' stop appearing - java

I'm honestly not sure if the title fits the question completely, but here it is anyway. I'm making a simple game in java where alien spaceships fall down from the top of the screen and if you don't kill them and they get to the bottom of the screen, the space station takes damage. But whenever the space station gets destroyed, the message-box that should tell the player that they died, won't stop appearing, it just keeps popping up over and over again. And in the console I get an error message that won't stop getting bigger! This is the code I have for the space station's health:
public class SpaceStation extends Entity {
public static int stationHealth = 100;
public SpaceStation(int x, int y) {
super(x, y);
}
public void update() {
}
public void draw(Graphics2D g2d) {
g2d.drawImage(ImageLocator.getSpaceStation(), 0, 595, null);
// HEALTH BAR
g2d.fillRect(5, 25, stationHealth, 10);
if(stationHealth <= 0) {
try{
JOptionPane.showMessageDialog(null, "You died on level "
+ GameFrame.level + ". Better luck next time!");
GameFrame.mainTimer.stop();
System.exit(0);
}
catch(Exception e){
JOptionPane.showMessageDialog(null, e.getMessage());
System.exit(0);
}
}
}
public Rectangle getBounds() {
return new Rectangle(x, y, 600, 200);
}
}
Apparently the line that the error is on is the JOptionPane.showMessageDialog(null, "You died on level "
Here's the error message:
at java.lang.Thread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.InternalError: The current process has used all of its system allowance of handles for Window Manager objects.
at sun.awt.windows.WToolkit.eventLoop(Native Method)
at sun.awt.windows.WToolkit.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.InternalError: The current process has used all of its system allowance of handles for Window Manager objects.
Thank you for your time.

Don't open a dialog from within the paint method! Or perhaps more domain specific, don't do that in a method that might be called from the paint method of another class, as the draw(Graphics2D) suggests.
I can only presume your code has a timer that calls repaint(), which in turn might cause a call to paint(Graphics) or paintComponent(Graphics). But that is also done by the JRE itself whenever it knows a component might have an element appear over the top, ..like a JOptionPane. Hence 'infinite loop'.

Related

JavaFX, problem with Platform.runLater(), delayed rendering of Canvas graphic

I am trying to make a simple event driven TicTacToe game using JavaFX. Currently I am struggling with termination once certain conditions are met. To put it into more details, the player can click on the GridPane elements, which are Canvas Objects, and then they are filled with "X" or "O" shapes respectively (I am using strokeLine and strokeOval methods of GraphicsContext). Code below:
private static void placeX(Canvas square){
GraphicsContext gc = square.getGraphicsContext2D();
gc.setLineWidth(10.0f);
gc.setStroke(Color.CORNFLOWERBLUE);
gc.strokeLine(square.getWidth()*0.2, square.getHeight()*0.2, square.getWidth()*0.8, square.getHeight()*0.8);
gc.strokeLine(square.getWidth()*0.8, square.getHeight()*0.2, square.getWidth()*0.2, square.getHeight()*0.8);
}
Once 3 of the same shapes appear in line or diagonally the program should terminate. I am doing this using Platform.exit(). Code below:
class HandleGame implements EventHandler<MouseEvent>{
#Override
public void handle(MouseEvent e){
Canvas can = (Canvas)e.getTarget();
//function to check if the canvas is clear
placeX(can);
if(game.isEnded()){ //checks if the same shape appears three times
Platform.runLater(new Runnable() {
#Override
public void run(){
try {
Thread.sleep(5000);
}
catch(InterruptedException exc){
System.out.println("Got something: " + exc.getMessage());
}
Platform.exit();
}
});
}
}
}
This event handler is attached to every Canvas object in GridPane and triggers on mouse release. The problem I am having is that once the last Canvas is clicked, before the shape appears on the Canvas the specified Runnable is executed and the rendering is unnaturally delayed (the "X" shape appears only for a second before closing). Strangely enough 1 out of 10 runs it executes as expected. How can I make the rendering trigger before the Thread.sleep() and following Platform.exit()? Why on rare occasions the rendering is actually performed before Thread.sleep()? I did a little research but could not find anything decisive, I am newbie when it comes to JavaFx. Appreciate your help.
Based on #Slaw and #VGR comments I managed to solve the problem using two different methods, one utilizing PauseTransition and second Thread. Code below:
Using PauseTransition:
if(game.isEnded()){
PauseTransition termination = new PauseTransition(Duration.seconds(1d));
termination.setOnFinished(event -> Platform.exit());
termination.play();
}
Using Thread:
if(game.isEnded()){
new Thread(() -> {
try{
Thread.sleep(2000);
}
catch(InterruptedException exc){
; //exception handling code here
}
Platform.exit();
}).start();*/

System.out.println() with a simple getter inside makes swing repaint not work as intended

Short version:
This works and changes the color of a rectangle in the screen:
public void test(){
tilePointer.setIcon(Color.RED);
}
This doesn't:
public void test(){
System.out.println("color: " + tilePointer.getIcon());
tilePointer.setIcon(Color.RED);
}
Long version:
While testing something with Arraylists and objects, I noticed some pretty weird behavior.
I have a 2D array of Tiles (the class Tile just has a Color attribute called icon).
That 2D array of Tiles is drawn to the screen using a class that extends JPanel and overrides drawComponent(). That class has another 2D array, this time of Colors. It draws a rectangle for each Color in that array.
The following method is used to give the icon from a Tile to the extended JPanel. The method call is just something like panel.place(x,y,tiles[y][x].getIcon()).
public void place(int x, int y, Color color){
colors[y][x] = color;
}
I have another object from the class Tile, tilePointer, which is a "pointer" to one of the Tiles in the array (something like tilePointer = tiles[y][x]).
The following simple snippet of code works just fine and does exactly what it looks. It just changes the color of tilePointer, and the rectangle in the screen corresponding.
public void test(){
tilePointer.setIcon(Color.RED);
}
Now here comes the really weird part. If I change the test method to this:
public void test(){
System.out.println("color: " + tilePointer.getIcon());
tilePointer.setIcon(Color.RED);
}
The rectangle simply just doesn't change the color. However, if do another System.out.println("color: " + tilePointer.getIcon()) after the setIcon(), I can see that the value actually changed.
No, there's nothing weird on the methods getIcon() and setIcon(). they are just
public Color getIcon() {
return icon;
}
public void setIcon(Color icon) {
this.icon = icon;
}
Does anyone know what could possibly be causing that? Thanks in advance.
[EDIT] I forgot to mention something important:
That test() method is called in another Thread. The reason for that is that test() was supposed to have a much more bigger job than just recoloring a single Tile.
public void startup() {
new Thread(() -> {
qtd = test();
}).start();
}
If I make it run on the same thread as the rest of the application does fix it.
public void startup() {
qtd = test();
}
But still, that doesn't explain what causes the problem. However, it is likely related to that. My apologies for not mentioning that earlier.
I'm just chiming in with my experiences here (and by no means should you consider this an well researched answer). My experiences with Swing (and most other frameworks) is that you once you step outside a single thread you're going to need to manage that state yourself. Swing doesn't really know if it needs to update until the event loop has something that causes it to update.
Without a full example this will be hard to reproduce, but since you're already jumping into multithreading you should read up on Swing patterns one of which is SwingUtilities.invokeLater(Runnable)
In the case of your code if your change to the GUI happens on another thread you need to rejoin the Main Swing thread via SwingUtilities to ensure that your code is happening on that event loop.
I suspect that if you were to add a handler that changed something else (like a button) and then hit it you would see your red icon appear with that button change.
Long story short you probably want something similar to this:
/* Forgive me, I'm jumping between five languages
right now and this might not be the correct syntax for
creating an anonymous threads */
SwingUtilities.invokeLater( ()-> {
//All this code will run on the Swing Thread
System.out.println("color: " + tilePointer.getIcon());
tilePointer.setIcon(Color.RED);
})

Asynchronous Multithreading: Error compiling shader. (libgdx)

I'm writing an application with the libgdx api for Android, and I'm running into issues concerning changing states and multithreading.
What I initially want is two asynchronous threads running at the same time, one being the game render thread, and the other being the game logic thread. I then want to be able to change the state of the game, which changes the update/render methods on their respective objects. Obviously, the render thread is running per frame (which is taken care of by libgdx already). This is my code modeling my attempt to do so:
public final class StateManager {
private static State gameState = State.START;
private static StateObject stateObject = new StartScreen();
private static final Object syncObjectUpdate = new Object();
private static final Object syncObjectRender = new Object();
public static void update(float elapsedTime){
if (!stateObject.isCreated){
//pause this thread until render thread stops
synchronized(syncObjectUpdate) {
try {
// Calling wait() will block this thread until another thread
// calls notify() on the object.
syncObjectUpdate.wait();
} catch (InterruptedException ignored) {} // Happens if someone interrupts your thread.
}
//once the render thread stops-
stateObject.dispose();
switch (gameState){
//note: creating a new object here sets isCreated to true,
//so the if statements gets called only once per state change.
case START:
stateObject = new StartScreen();
break;
case GAME:
stateObject = new GameScreen();
break;
case LOADING:
//stateObject = new LoadingScreen();
break;
default:
System.out.print("ERROR IN STATE!");
break;
}//end switch
//-change the state and resume render thread
//what if this happens before wait? surround in while loop?
synchronized(syncObjectRender) {
syncObjectRender.notify();
}
}//end if
stateObject.update(elapsedTime);
}
public static void render(){
stateObject.render();
//if update thread is waiting
if (MyGdxGame.logicThread.getState() == Thread.State.WAITING){
//then resume that one,
synchronized(syncObjectUpdate) {
syncObjectUpdate.notify();
}
// and pause this one
synchronized(syncObjectRender) {
try {
syncObjectRender.wait();
} catch (InterruptedException ignored) {}
}
}//end if
}//end render
public static void changeState(State state){
stateObject.isCreated = false;
gameState = state;
}
public static void dispose(){
stateObject.dispose();
}
public static void resize(int width, int height){
stateObject.resize(width, height);
}
public static void pause(){
stateObject.pause();
}
public static void resume(){
stateObject.resume();
}
}//class
This runs well, until I call changeState(), and it throws the error:
E/AndroidRuntime(19094): java.lang.IllegalArgumentException: Error compiling shader
I THINK this happened because stateObject.render() got called (which changes the spritebatch and such) while there was no StateObject present.
[BTW, if it isn't clear already, a StateObject is something like a start screen, or game screen, which has a render() and update() method inside that are called by two different threads. Also, I wrote this program before without multithreading, and the state changing mechanism worked perfectly.]
Here's my thought process:
1. When I change the state, the update thread gets the notification. This pauses the update thread. (Render is still running)
2. When the render thread sees that the update thread is paused, it resumes the update thread and pauses the render thread. This is so the stateObject.render() method doesn't get called before it tries to call render() on something that is disposed.
3. At this point, the update thread is notified to start up again, so it disposes of the StateObject and creates a new one.
4. Now that a new state object is initialized, stateObject.render() should have no problem. It then resumes the render thread. Both threads should be running, and peace in the universe is restored.
Now there's obviously something wrong with my implementation or that logic, because I'm getting that error. So... why?
Any help is greatly appreciated. If something isn't clear, let me know in the comments. Thanks!
Through hours of experimenting, I was able to solve this by putting the switch-case in the render method, and deleting the line stateObject.dispose();. That's it, no waiting on threads and locking objects. This now calls the appropriate render method for the state without issues of changing the spritebatch (because its in the same OpenGL thread). Deleting the dispose method means that whenever I attempt to change the state, the update method always has something to update.
This is rather a work around because changing the sate is now handed in the render method, but the performance impact is very minimal.
Here are the working render and update methods with the changes (same class):
public static void update(float elapsedTime){
stateObject.update(elapsedTime);
}
public static void render(){
stateObject.render();
if (!stateObject.isCreated){
switch (gameState){
case START:
stateObject = new StartScreen();
break;
case GAME:
stateObject = new GameScreen();
break;
case LOADING:
//stateObject = new LoadingScreen();
break;
default:
System.out.print("ERROR IN STATE!");
break;
}//end switch
}//end if
}//end render
I hope this helps someone!

First attempt at understanding applet and runnable in Java

I'm new to Java. I need help figuring out some of the code I'll be displaying below. The point of the code is to simply create an applet which displays a ball moving from left to right using a change in X position. I have began following a tutorial for applets from a website which made this code available to me (http://www.javacooperation.gmxhome.de/BallBewegungEng.html). Basically, I need someone to explain to the following methods and their contents: the start method (what is a thread? I'm aware it's an object, but what purpose does it serve here?). The run method (what exactly am I doing when I set the thread priority to MIN/MAX? Why does this method call the repaint() method even when no such method has been created?). Lastly, the paint method (what exactly is the g.fillOval line doing and how?). I've tried googling these things, but I'm having a hard time understanding understand the jargon that I see with most answers. I need things explained in a more simplistic way so that I may understand the jargon later on.
Thanks for any help in advance. The code:
import java.applet.*;
import java.awt.*;
public class MovingBall extends Applet implements Runnable
{
int x_pos = 10;
int y_pos = 150;
int radius = 20;
public void init()
{
setBackground (Color.blue);
}
public void start()
{
Thread th = new Thread(this);
th.start();
}
public void stop()
{
}
public void destroy()
{
}
public void run()
{
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
while(true)
{
x_pos++;
repaint();
try
{
Thread.sleep (20);
}
catch(InterruptedException ex)
{
}
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
}
public void paint (Graphics g)
{
g.setColor (Color.red);
g.fillOval (x_pos - radius, y_pos - radius, 2 * radius, 2 * radius);
}
}
A thread is something you use when you want to run multiple pieces of code at the same time, without interrupting the other threads. In this case you use the thread to repaint the screen and pause the loop without affecting the rest of the program.
The run method is overriding from the Runnable object that you pass to the thread to run. When you create a thread, you pass it a runnable object with a run method defined, which will run when the thread starts.
The repaint method is not defined in this class, however it is defined in the parent class(Applet), so you can call it in this class just fine.
The paint method is overriding from Applet as well, so you are defining what the applet will do when it runs the paint method.

Updating GUI gives a flickering effect

I currently have a JFrame where on it's content pane I draw images on from a game loop at 60 frames per second. This works fine, but at the right side, I now have more Swing elements on which I want to display some info on when selecting certain parts of the content pane. That part is a static GUI and does not make use of a game loop.
I'm updating it this way:
public class InfoPanel extends JPanel implements Runnable {
private String titelType = "type: ";
private String type;
private JLabel typeLabel;
private ImageIcon icon;
public void update() {
if (this.icon != null)
this.typeLabel.setIcon(this.icon);
if(this.type != null || this.type != "")
this.typeLabel.setText(this.titelType + this.type);
else
this.typeLabel.setText("");
}
public void run() {
try {
Thread.sleep(150);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.update();
}
(this method is only called when the player has actually moved, so it's just called once - not 60 times per second)
I noticed that, when calling this update()-method from the game loop, I get flickering effects. I assume this is because updating the UI takes some time, so I decided to put it in a new thread. This reduced the flickering, but didn't solve it.
Next, I decided to give the new thread low priority as the part of the screen which is redrawed 60 times a second is far more important. This reduced the flickering again, but it still happened. Then, I decided to use Thread.sleep(150); in the new thread before calling the update()-method, which solved the flickering effect on my system completely.
However, when running it on other systems, it still happens. Not as often as before (maybe one time per 20 seconds), but it's still pretty annoying. Apparantly, just updating the UI in another thread doesn't solve the problem.
Any ideas how to completely eleminate the flickering?
Call the update() in SwingUtilities.invokeAndWait() which stops the thread and updates UI in EDT.
Problem is that you are use Thread.sleep(int), that stop and freeze GUI during EventDispatchTread more in the Concurency in Swing, example demonstrating freeze GUI by using Thread.sleep(int), example for Runnable#Thread
If you want to delay whatever in Swing then the best way is implements javax.swing.Timer

Categories