This week's book giveaway is in the Open Source forum.
We're giving away four copies of Programmers Guide to Apache Thrift and have Randy Abernethy on-line!
See this thread for details.
Win a copy of Programmers Guide to Apache Thrift this week in the Open Source forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Devaka Cooray
  • Knute Snortum
  • Paul Clapham
  • Tim Cooke
Sheriffs:
  • Liutauras Vilda
  • Jeanne Boyarsky
  • Bear Bibeault
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Ron McLeod
  • Piet Souris
  • Frits Walraven
Bartenders:
  • Ganesh Patekar
  • Tim Holloway
  • salvin francis

JFrames wont work as expected when invoked from other code  RSS feed

 
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello, I am new to swing. I was trying to make a pac man game project using swing. I have made the individual class like a Main Menu , Player name entry , Level 1, level 2 ,etc.
Now the problem is all these classes work as expected when I run them individually but whenever a function from one class calls another function of a different class they don't run as expected.

For example when user click the button "New Game" on the main menu class it should call the Player Name Entry class which it does correctly but the problem is while the Player Name Entry class
is working the Main menu class's methods keep running which I don't want. System.exit(0) will stop the entire program so I have to call frame.dispose() to dispose() the main menu frame but that doesn't stop the other
methods from continuing to run like the music playing in the main menu keeps playing. The only way I can figure out to get rid of this is Thread.currentThread().stop() which is a bad idea but it works...

Next as I said before... frames don't display correctly when called from methods other than methods of their own class... For example there is frame which shows a count down before starting each level in the game like 3...2...1

Now this frame works correctly when I run it directly from the programs own main() method but when a different method from somewhere else(a different class) calls the same code it doesn't display correctly that is
it displays the frame but does not display the label inside the frame containing the countdown image.

Again when a level is over I want to give the user a prompt to proceed to the next level this works correctly when I run that level code directly from its main() but when that level is called from some other code then it wont work...
Below is the code that I use to display prompt to user...


 
Marshal
Posts: 64471
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Arpan Ghoshal wrote:Hello, I am new to swing. I was trying to make a pac man game project using swing. . . .

If you are new, you should probably start with something simple. You should be able to run the application, whatever it is, with no hint of a GUI. You  should go for an incomplete implementation if like Pacman, you are writing something where the display is an essential part of the app. It isn't possible to diagnose the problem from the information you have given us.
I suggest you start with a very simple GUI and gradually add functionality to it.

You must never, never use Thread#stop().
 
Saloon Keeper
Posts: 10206
216
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It sounds like you're calling into Swing code from threads other than the event dispatch thread. And if you do run it on the event dispatch thread, your Thread.stop() call will make sure that your application stops behaving correctly.

Can you show us your StartingCountDown class?
 
Rancher
Posts: 3040
22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Use a Swing Timer if you want to schedule some event.

You can schedule the event to first every second.

When the Timer fires you decrement the time remainting.

When the Timer remaining reaches 0, you stop the time and do your other processing.
 
Arpan Ghoshal
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:
Can you show us your StartingCountDown class?





The StartingCountDown class needs to show a 3...2...1 countdown which it does by usingf a countdown.gif image. A audio reading the countdown is played along with it, the current thread waits for 6 seconds for the process to finish after which it
disposes off the frame and calls the code for the next level...

The problem is when the control() method for StartingCountDown is called from its main() it works as expected but if I call it from somewhere else like another class "NameEntry" it wont work , it just displays an empty frame does not display the gif image
the frame hangs that is the close and minimize buttons on the window wont respond but I can hear the countdown audio being played and after 6 seconds the frame correctly calls the next the level code frome PacMan_Level1.control(p);

I don't understand why it works when called from its own main() but does not work when called from else where.

Here is the code which calls the StartingCountDown and this is when the above problem happens...



Can anyone help ?
 
Campbell Ritchie
Marshal
Posts: 64471
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Don't double‑space code; that makes it harder to read.
Remove extraneous things like setFont(); that isn't relevant to the current problem.
Why are you using Thread#sleep() and dispose()?
 
Arpan Ghoshal
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:
Why are you using Thread#sleep() and dispose()?



Its because I want the current thread to sleep for 6 seconds so that the countdown.gif image in the frame showing the 3....2....1 countdown gets enough time to complete after which it is disposed off by a call to frame.dispose().
 
Campbell Ritchie
Marshal
Posts: 64471
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But what you want and what you get turn out to be two different things. Don't call sleep on the event dispatch thread. Calling dispose will probably terminate your application altogether.
 
Arpan Ghoshal
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I understand your point...but calling Thread.sleep() does the job... Can you suggest any better way to make the thread wait for 6 seconds (for the .gif image to complete) before disposing off the frame other than using Thread.sleep() ?
 
Campbell Ritchie
Marshal
Posts: 64471
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am still not convinced you want to dispose the frame, but, you can set up a Swing timer to fire an action in 6″ (=6000ms). That will not necessitate any sleeping or anything like that.
 
Stephan van Hulst
Saloon Keeper
Posts: 10206
216
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell, there is nothing wrong with disposing a frame. As a matter of fact, it's the most straightforward way I know to close a form.

You're right though. Thread.sleep() should not be used, and least of all on the event dispatch thread.

Anyway, the reason why it works when calling from the main() method is because the setVisible() method starts up the event dispatch thread, which will then lay out and show the user interface. When you trigger the countdown as a reaction to a button click, you are already on the event dispatch thread, and calling Thread.sleep() will just freeze everything.

The solution is to perform background operations in a different thread than the event dispatch thread, and avoiding the use of Thread.sleep() in general (not just in Swing code). Check out SwingWorker or Timer, as Rob proposed. You also need to write more object oriented code. The fact that your code is full of static methods is an indication that your design is off.
 
Arpan Ghoshal
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for replying. I really don't know much about SwingWorker so I will learn about it when I have time and will try to avoid Thread.sleep().

Stephan van Hulst wrote:
Anyway, the reason why it works when calling from the main() method is because the setVisible() method starts up the event dispatch thread, which will then lay out and show the user interface. When you trigger the countdown as a reaction to a button click, you are already on the event dispatch thread, and calling Thread.sleep() will just freeze everything.



I understand what you are saying here but I still don't understand why this works in main() but does not work from elsewhere.
Well to avoid this this problem when calling StartingCountDown from elsewhere I have done this...
Instead of directly calling StartingCountDown.control(p,x); I call it in a different thread this seems to solve the problem and StartingCountDown is displayed properly.



Stephan van Hulst wrote:
You also need to write more object oriented code. The fact that your code is full of static methods is an indication that your design is off.


I also feel the same thing but since I need only one copy of the methods I made them static that is I don't find any need of unnecessarily making objects when the same thing can be achieved by using static methods.
 
Campbell Ritchie
Marshal
Posts: 64471
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:. . . the setVisible() method starts up the event dispatch thread . . . .

I never knew that: thank you.
 
Stephan van Hulst
Saloon Keeper
Posts: 10206
216
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It works in main(), because you start on a different thread than the event dispatch thread. When the main thread hits frame.setVisible(true), the event dispatch thread starts up, which Swing uses to lay out all the components and react to user interaction. The main thread then hits Thread.sleep(), but because the event dispatch thread is still running the program remains responsive.

However, when you click a button, Swing uses the event dispatch thread to handle the event. So when you start your timer from an action listener, the current thread IS the event dispatch thread, and telling it to sleep will make Swing unresponsive.

Starting up a new thread to display your form is a bad idea. All interaction with the user interface must happen on the event dispatch thread. The fact that you're creating your GUI from main() directly may already lead to subtle problems that you haven't noticed yet. The solution is to perform tasks that take a long time (like doing nothing for 6 seconds) in a background thread, which may periodically trigger the event dispatch thread to update the user interface.

Using static methods everywhere just to avoid object creation is the complete opposite of how object oriented languages are supposed to be used. There's a reason that languages like C are not being used much outside of low level applications. The first step is to name your classes after things, not actions.

Here's an example of a countdown form:
 
Stephan van Hulst
Saloon Keeper
Posts: 10206
216
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

Stephan van Hulst wrote:. . . the setVisible() method starts up the event dispatch thread . . . .

I never knew that: thank you.


So does pack().

Never call setVisible() or pack() from a constructor, directly or indirectly. Call them in a separate method after the object has been constructed.
 
Campbell Ritchie
Marshal
Posts: 64471
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I knew that if you start the EDT you can write this sort of thing:-Then the main thread will crash because of the arithmetic exception but the GUI remains visible. Obviously because they are on different threads. I didn't know about not calling setVisible()/pack() in the constructor however.
 
Arpan Ghoshal
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for the explanation and example Stephan I will try to study them and improve my code.
 
If you live in a cold climate and on the grid, incandescent light can use less energy than LED. Tiny ad:
ScroogeXHTML - small and flexible RTF to HTML converter library
https://coderanch.com/t/710903/ScroogeXHTML-RTF-HTML-XHTML-converter
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!