Correctly handling a Reload and Restart from the AppletViewer - java

When my applet starts up the first time from a clean environment, things work the way I expect them to. I spawn two threads, one for generic processing, and one for graphics. I do all GUI manipulation calls from the event dispatching thread. Start/Stop is handled correctly from the appletviewer, but Restart/Reload is not. I have a Canvas called drawCanvas as the only Component in my Applet's content pane, and I use double buffering to draw to it.
I observe the problem here:
public void start() {
/* ... some stuff */
executeOnEDTAndWait(
new Thread() {
#Override
public void run() {
/* ... more stuff ... */
setupDrawCanvas();
if( drawCanvas.isDisplayable() ) {
drawCanvas.createBufferStrategy(2);
/* ... some more stuff */
} else {
/* This is where it runs into difficulties */
}
/* ... */
Where setupDrawCanvas is defined like this:
private void setupDrawCanvas() {
setVisible(false);
setIgnoreRepaint(true);
getContentPane().removeAll();
drawCanvas = new Canvas();
drawCanvas.setName("drawCanvas");
drawCanvas.setSize(
newDrawCanvasDimension.width,
newDrawCanvasDimension.height);
drawCanvas.setIgnoreRepaint(true);
getContentPane().add(drawCanvas);
getContentPane().setVisible(true);
drawCanvas.setVisible(true);
setVisible(true);
}
Also, here's the relevant code in destroy()
public void destroy() {
/* .. some stuff .. */
/* dispose of drawCanvas */
drawCanvas.setVisible(false);
if( drawCanvas.getBufferStrategy() != null ) {
drawCanvas.getBufferStrategy().dispose();
}
/* reset and disable the applet's GUI */
setVisible(false);
getContentPane().removeAll();
removeAll();
/* .. some more stuff */
The first time through, everything works fine. When I do a restart from the appletviewer, first stop() is called which causes all my threads to enter into wait states. Then destroy() is called which wakes all my threads up again and lets them exit, as well as do and invokeAndWait() on the EDT to clean up my widgets and do a setVisible(false). So after destroy completes the appletviewer calls init/start again and the process repeats exactly as before, except it fails in start() at the region I noted above.
Something that I noticed which made very little sense to me was that if I cloned the applet using the appletviewer and then reloaded the clone, everything would work as expected when I attempted to restart or reload the clone the first time, but would crash with an exception the second time.
Something else I noticed while trying to debug this problem is that the appletviewer and a browser act completely differently as hosts to my applet; they don't even call init() and start() under the same conditions. Also, restart and reload seem to be nothing more than a call to stop() -> destroy() -> init() -> start() but with subtle modifications to the execution environment.
So my question is, what is the significance of the restart and reload operations (i.e. when are they used) and is it a problem that my applet fails in the appletviewer when they occur?

Nice Question.
To answer this question we need understand the blocks of java code first.
we have a anonymous, static blocks before construtor that will be executed.
package com.test;
import java.applet.Applet;
import java.awt.*;
public class AppletTest extends Applet {
{
System.out.println("I m Anonymous block");
}
static {
System.out.println("I m static block");
}
public AppletTest()
{
System.out.println("I m constructor");
}
public void init()
{
System.out.println("init");
}
public void start()
{
System.out.println("start");
}
public void stop()
{
System.out.println("stop");
}
public void destroy()
{
System.out.println("destory");
}
public void paint(Graphics g)
{
g.drawString("test Applet",10,10);
}
}
invocation:
<applet code="AppletTest.class" height=300 width=300></applet>
when running this class using appletviewer you can note the difference.
Applet running for the first time you will get
I m static block
I m Anonymous block
I m constructor
init
start
while doing applet restart -
stop
destory
init
start
and on applet reload
stop
destory
I m Anonymous block
I m constructor
init
start
for your second question, applet does not guarantee the same output on different OS, network and hardware components.

Related

Java GUI Thread not closing

I have a plugin for an application containing a GUI (Swing) and is started as a thread. The GUI starts a thread that does some processing on a buttonevent, right after disposing itself. While processing, a dialog window functions as a logger. Everything works fine, the GUI and dialog window will close and the threads terminate, when calling window.dispose() after the processing finished.
Threads are started as Threads, not via SwingUtilities (I tried many times, but i just can't get that to work).
Basicly the entry class for the application:
public void calledByApplication(){
RunnableClass.startGui(this);
}
public void doStuff(){ //GUI actually gets created here
gui.setVisible(true);
}
public void calledWhenSaveButtonPressed(){
//Process some stuff
gui.dispose(); //works, thread terminates
}
RunnableClass (implements Runnable):
ApplicationEntryClass aec;
public RunnableClass(ApplicationEntryClass aec){
this.aec = aec;
}
public void run(){
aec.doStuff();
}
public static void startGui(ApplicationEntryClass aec){
Thread guiThread = new Thread(new RunnableClass(aec));
guiThread.start();
}
Gui Class:
public void calledWhenSaveButtonPressed(){
aec.calledWhenSaveButtonPressed();
}
public void calledWhenCancelButtonPressed(){
this.dispose(); //doesn't work
}
My problem:
When trying to dispose the GUI via button event (or the x with JFrame.DISPOSE_ON_CLOSE), it closes, but the thread doesn't terminate. After looking at the stack i noticed, that the EventDispatchThread gets stuck on EventDispatchThread.pumpEventForFilter(...).
I'm well aware, that the issue could be, that the thread doesn't get automatically destroyed. But since i'm new to threading i don't really know where to start troubleshooting. Any suggestions?
Edit: The dialog window is not the problem. Also, i can't use System.exit() or else the application calling the plugin will terminate.

Display an image using EventDispatchThread vs without

So I'm trying to display an image(ball) which I'll eventually control with user input. For know, the image just gets displayed over intervals using thread's sleep method.
I've made 2 classes, one that extends JPanel and the other extends JFrame.
The JPanel subclass looks like this:
public class BallPanel extends JPanel {
private Image ball;
private int x,y;
public BallPanel(){
try {
ball=ImageIO.read(new File("C:\\Users\\Owner\\Desktop\\ball.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
x=10;
y=10;
Thread thread = new Thread() {
#Override
public void run(){
loop();
}
};
thread.start();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(ball,x,y,null);
}
public void loop(){
while(true){
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
In the loop method I call the sleep method to allow repaint to be called over intervals. Then, loop() is called in the constructor.
The JFrame subclass looks like this:
public class BallFrame extends JFrame {
public BallFrame(){
setVisible(true);
setSize(800,800);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setContentPane(new BallPanel());
}
public static void main(String args[]){
//SwingUtilities.invokeLater(new Runnable() {
// #Override
// public void run() {
new BallFrame();
// }
//});
}
}
Now the interesting, or perhaps confusing thing, is that when I run the code as it is shown here, with the anonymous inner class commented out, the ball doesn't always appear. Sometimes I need to re-size the frame (i.e call repaint) before the ball is shown. However, when I call it through the even dispatch thread using the anonymous inner class the ball appears every time I run the code. What is the reason for this?
It has little to do with starting the UI from within the EDT or not (although you should cause that can cause lots of other weird and interesting issues) and more to do with the fact that you've called setVisible before you've established the contents of the UI.
This is possibly an example of a race condition between the system trying to get the EDT up and running and the OS calls responding before it's established.
In either case you SHOULD start the UI from within the EDT and call setVisible last.
Swing can be lazy about updating the UI, this is actually a deliberate design choice as well as a good idea. You don't always want the UI updated after each and every change you make (like adding/removing components), so it hands over some of the control to the developer to decided when it's best to revalidate container hierarchy and request repaints
I would also avoid using a Thread to update the state of the UI as this could cause dirty paints as Swing uses a passive rendering approach (painting when it feels it's required) and consider using a Swing Timer which updated from within the EDT OR use a BufferStrategy and employ a active rendering approach, which you can then control

Program displays filenames in a JTextArea as it walks the directory tree but I don't know how to stop it via a keypress

There are two windows: a GUI for user input and Output window for list of filenames found. Execution must be user-stoppable via a keypress and must leave both windows open because the program processes subdirectories, so it can run a long time, possibly stepping thru 100_000 files, either producing tons of output or none at all, depending on how user's filename pattern matches files encountered in the selected starting node.
Here's my question:
How do I look for a keypress (e.g., ESC or CTRL-C) to allow user to terminate? (Clicking red X isn't an option since that closes windows; user needs to see what's been found before termination. Doing so does not close either window anyway since all buttons are disabled once tree walk begins.)
I've tried putting keyListeners in several places, but once the "Start" button is clicked, all the swing components are disabled.
This seems like such a common situation that I'm surprised I can't find any textbook, thread, or Google info that directly answers the question. So I'm afraid it's not gonna be at all easy. That would be no surprise. I may have found a clue here but I can't get it to compile and the link contained there doesn't lead to that code snippet.
The search begins when the Search button is clicked:
private void jbSearchActionPerformed(ActionEvent evt) {
SearchyGUI.doIt();
}
The doIt() method walks the directory tree by an extension of SimplefileVisitor:
public class OverriddenFileVisitor extends SimpleFileVisitor<Path> {
...
}
public static void doIt(){
try {
visitor = new OverriddenFileVisitor();
info.setVisible(true);
Files.walkFileTree(SearchyGUI.p , visitor);
}
catch (Exception e) { }
}
}
Output is written to jTextArea1 via the report() method:
public static void report(String s){
Output.jTextArea1.append(s + "\n");
}
This is done primarily in the visitFile() method of SimpleFileVisitor:
public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException {
report(foundkt + "--" + f.getFileName().toString());
return FileVisitResult.CONTINUE;
}
Here's the main class:
public class SearchyGUI {
static Output info;
static Path p ;
static FileVisitor visitor ;
static GUI gui
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
gui = new GUI();
gui.setVisible(true);
}
});
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
info = new Output();
}
});
}
The problem is you are hogging the GUI thread, so the GUI thread can't process any events originating from the user.
You need to create a new Thread and do the work in there. Then, to display output from that thread, you can use SwingUtilities.invokeLater or something like that.
The Key Bindings API is probably the best choice for monitoring key strokes.
I would also add a [Cancel] button to the UI, which shared the same action...
public class CancelAction extends AbstractAction {
public CancelAction() {
putValue(NAME, "Cancel");
}
public void actionPerformed(ActionEvent evt) {
// Perform the cancel operation...
}
}
Then some where else in your code...
CancelAction cancelAction = new CancelAction();
JButton cancelButton = new JButton(cancelAction);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Cancel");
am.put("Cancel", am);
Now the other problem you're going to have is the fact that you look like you are running a long running task within the context of the Event Dispatching Thread. This is going to prevent your program from being able to update the UI or allow the user to interact with the UI.
If you need to make changes to the UI (ie, show the output of the file processing), you should try a SwingWorker.
The main reason being is that it allows you to execute the long running task in another thread, but provides the mechanism for re-syncing updates back to the EDT, where it is safe to make changes to the UI.
Take a look at Concurrency in Swing for more details.
Regardless of which direction you take, you're going to need to supply a reference to the object that is carrying out the task and provide some kind of "cancel" flag, which the "task" object will need to monitor
The way I had left this program last night was unsatisfactory since Exit resulted in user not being able to see the output so far displayed (it could be useful). So I established window listeners and used the close event to set a boolean aborted to true to prevent further output to the window, but the thread kept running, which led to intermittent problems if another search was started before the thread ended.
Here's how I fixed it.
The FileVisitor interface has 4 methods to implement to walk the tree--two for each file visited, two for each directory. Each returns a FileVisitResult which is normally FileVisitResult.CONTINUE. By changing the return value to FileVisitResult.TERMINATE in the file visitor thread, it terminates appropriately! That is, I set a flag that the thread could check and take appropriate action, which is exactly what #MadProgrammer suggested.
public static FileVisitResult disposition = FileVisitResult.CONTINUE;
...
private static void report(String s){
if (! aborted)
try{
Output.jTextArea1.append(s + "\n");
}
catch (Exception e){
aborted = true ;
disposition = FileVisitResult.TERMINATE;
}
}
...
#Override
public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException {
f1 = new File(f.getParent().toString() + "\\" + f.getFileName().toString());
long filesize = f1.length();
report(f.getFileName().toString() + "\t found in " + f.getParent().toString());
return disposition;
}
I am one happy camper! Thank you BOTH for your ideas and input.
Well, I made it stop. I guess if you wander the woods long enough you'll find a gnome. I read Robin's hint last week and sort of gave up. Then I read some more and more. And then more. But Robin assured me that gnomes DO exist in these here woods!
The code I used was a modification of some I found for a MatLab/Java app. (Why'd I even look at it?? Best apparent Google hint.)
I made the "file visitor" (directory tree walker component) startable as a thread as Robin advised:
public class OverriddenFileVisitor extends SimpleFileVisitor<Path> implements Runnable{
// ................................................................^^^^^^^^^^^^^^^^^^^
In doIt() I made a couple of changes, moving the lines that process the directory to the now-runnable class and started the file visitor as its own thread in doIt():
public static void doIt(){
try {
new OverriddenFileVisitor().startTh();
//^^^^^^^^^^
//(moved) Files.walkFileTree(SearchyGUI.p , visitor);
...
I added the new method in the previous line to OverriddenFileVisitor class: (This is the main part of the MatLab/Java code that made sense to me so I used and modified it.)
public void startTh() {
Thread t = new Thread(this);
t.start();
}
And I inserted the overridden run() method for the class:
public void run() {
try {
Files.walkFileTree(SearchyGUI.p , this); // Used to be in doIt().
}
catch (IOException ex) { }
}
It ran and gave correct results and stopped when I hit Exit button, which "became" enabled after revising the file visitor to run in its own thread, which is what #Robin Green was saying. I almost feel like I know what I've done.
P.S. Note that I already was able to get my output via invokeLater()--last several lines of original question.
It's not finished but it's much more satisfactory.

Multiple JFrame application, how do I bring them all to front together?

My users like having multiple JFrames; it allows them to resize the different components and place them wherever they want on the screen. However, I have a request to make all the child windows come to the front together... in other words, lets say they maximize another window in front of all the windows, and then use the task bar to click on just one of the JFrames. How can I set it so that they all come to the front? Note: it is also possible to close the child windows; if they are actually hidden, I do not want them to come to the front. I have a class ApplicationModel that keeps track of whether a window is hidden or not.
Things I've tried:
Using windowActivated() and focusGained() to try to bring them all to the front. This usually results in an infinite loop. The problem is that my eventing framework sends these requests off the Event Dispatch Thread, so any sort of blocking with an AtomicBoolean doesn't last long enough.
The main problem is not that I can't make them come to the front... I have made them come to the front. The problem is that they KEEP trying to come to the front, as bringing a window to the front throws the focusGained and windowActivated events, which creates an endless loop...
Making one window the master, and making the others a JDialog. Unfortunately, either the windows are modeless (and therefore don't come to front with the master window), or they are modal, (and therefore block the master window).
How can I fix either of these problems, or is there an entirely different third solution?
You can use a boolean field as a flag to prevent the infinite loop:
private boolean movingAllFramesToFront;
public void windowActivated(WindowEvent event) {
if (movingAllFramesToFront) {
return;
}
movingAllFramesToFront = true;
List<Frame> frames = getAllApplicationFrames();
for (Frame frame : frames) {
if (!applicationModel.isHidden(frame)) {
frame.toFront();
}
}
event.getWindow().toFront();
event.getWindow().requestFocus();
EventQueue.invokeLater(new Runnable() {
public void run() {
movingAllFramesToFront = false;
}
);
}
Another thing you can try is the new autoRequestFocus property introduced in Java 1.7. I have never tried using it, but here's my understanding of how it works:
public void windowActivated(WindowEvent event) {
final List<Frame> frames = getAllApplicationFrames();
for (Frame frame : frames) {
if (!applicationModel.isHidden(frame)) {
frame.setAutoRequestFocus(false);
frame.toFront();
}
}
EventQueue.invokeLater(new Runnable() {
public void run() {
for (Frame frame : frames) {
if (!applicationModel.isHidden(frame)) {
frame.setAutoRequestFocus(true);
}
}
}
);
}
I have an application with a lot of windows and had a problem similar to yours. My workaround is:
#Override
public void windowActivated(WindowEvent e) {
if (e.getOppositeWindow() == null) {
//front every window
}
}
First I created a class "SlveFrame" (Slve being the name of my app), a child of "JFrame".
public class SlveFrame extends JFrame implements WindowListener {
static ArrayList<SlveFrame> frames = new ArrayList<SlveFrame>();
public SlveFrame () {
addWindowListener(this); / /to make JFrame fire WindowListener's method
}
/ /... every method added from WindowListener
#Override
public void windowActivated(WindowEvent e) {
if (e.getOppositeWindow() == null) { // return null if window is not from my (or Your) work
for (SlveFrame frame : frames) { // if you have no idea what this is, look for "for each loop java" in google
frame.toFront();
}
}
}
/**
* The use of SlveFrame is almost the same as Jframe
*/
#Override
public void setVisible (boolean b) {
if (b)
frames.add(this);
else
frames.remove(this); // may raise an exception if you're not careful
super.setVisible(b); // or your window will simply not be visible.
}
#Override
public void dispose () {
frames.dispose(this) // may raise an exception you'll want to handle
}
}
The trick being that WindowEvent.getOppositeWIndow() returns a Jframe if the JFrame (or child class) is from your own program, meaning that if you switch to another program or app (such as eclipse, Firefox or a text editor) then back to any of your windows, then a call to getOppositeWindow() will return a 'null'. A simple if (e.getOppositeWindow()) makes it fairly easy to determine whether your window gain focus in condition that would require you to bring every window to the front, or rather to let everything be.
The overriding of setVisible (boolean b) and dispose () are optional but allow the dev to use it as a regular window.
I hope i could be of some help. Sincerly ~a lama

Problems with ActionListener and SystemUtil.invokeLater

I have look all over the web, and found no solution to my problem. For a AP Comp Sci project, I am making a Set of games, that will be run from a JFrame with JButtons. I have the games all ready, along with action listeners, but the games dont launch properly. The JFrame and JButtons are all setup correctly too.
private static class TetListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
GameCenter.quit();
GameCenter.startTetris();
}
}
GameCenter.quit() does nothing but run JFrame.dispose(), and GameCenter.startTetris(); constructs a new Tetris object, then run the play() method to start the game. All of Tetris is coded properly and works correctly when it is run in the main method (outside the actionlistener). But as soon as I put it in the ActionListener, it fails to be constructed properly. I tracked the problem down to:
public BlockDisplay(BoundedGrid<Block> board)
{
this.board = board;
grid = new JPanel[board.getNumRows()][board.getNumCols()];
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() // <<<<<<<<<<------------------- Problem Here
{
public void run()
{
createAndShowGUI(); // <<<<<<<<<<<<-------- Never Run
}
});
//Wait until display has been drawn
try
{
while (frame == null || !frame.isVisible()) // <<<<<<<-------- Never Resolved
{
Thread.sleep(1);
}
}
catch(InterruptedException e)
{
e.printStackTrace();
System.exit(1);
}
}
So the program always hangs. I also made a Pacman game that uses this SwingUtilities.invokeLater, so it doesnt work either. I cant figure out why this is happening or how to fix it.
Any help is appreciated. Let me know if you need any more info.
If the thread that runs SwingUtilities.invokeLater is already the swing event thread and you run in this while loop, yup, your application will hang.
Get rid of the while loop.

Categories