Solved

Threads don't work with JFrame

Posted on 2000-04-08
12
268 Views
Last Modified: 2006-11-17
My program use JFrame and thread.  But the out put stop after a little while.

import java.awt.event.*;
import javax.swing.*;
import java.applet.*;
import java.awt.*;
import  java.net.URL;
import  java.util.*;


public class Tryit extends JFrame implements Runnable{

  Thread  thread = null;

  Train train1, train2;
   
  Position p1 = new Position( 100,200 ), p2 = new Position(110,80);

  Container c;
 
  public Tryit() {
   
     c = getContentPane();
     train1 = new Train( 1, p1 );
     train2 = new Train( 2, p2 );
     train1.start();
     train2.start();
     System.err.println( " after construct of try it ! ");
  }
   

  public void run(){
     
    System.err.println( " try it run begin! ");
   
    while (true) {
       
      repaint();

            try {
                Thread.sleep(10);
            } catch (InterruptedException e){
            // the VM doesn't want us to sleep anymore,
            // so get back to work
            }
     }

  }

   
  public static void main(String[] args) {

        Tryit frame = new Tryit();

        WindowListener l = new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        };

        frame.addWindowListener(l);
        frame.setSize(1200, 980);

        frame.show();
        System.err.println( " after show! ");
    }


  public void paint( Graphics g ){
   
    System.err.println( " tryit paint! ");
    train1.paint( g );
    train2.paint( g );

  }
}


/**
  Train.java
*/


class Train extends Thread {

  private  int  trainNo,  dx = 2, dy = 2 ;
  private  int  x, y;
  private  Position  currentPosition;
   
  public Train( int no, Position p ) {
    trainNo = no;
    currentPosition = p;
  }

  public void run(){
     
    while ( true ){

         
            try {
                Thread.sleep(1);
            } catch (InterruptedException e){
            // the VM doesn't want us to sleep anymore,
            // so get back to work
            }
             
       x = currentPosition.getX();
       y = currentPosition.getY();
 
       x = x + dx ;
       y = y + dy;
       if ( x < 0 ) dx/=-2;
       if ( x > 900 ) dx*=-2;
       if ( y < 0 ) dy/=-2;
       if ( y > 500 ) dy*=-2;
       
       currentPosition.setX( x );
       currentPosition.setY( y );


       System.err.println( " train while "+trainNo+" end once! ");
       
   }
  }

  public void paint( Graphics g ){

     g.drawOval( currentPosition.getX() -2, currentPosition.getY() - 2, 5, 5);
     System.err.println( " train paint "+trainNo+" end! ");
  }
}


/**
  Position.java
*/


class Position {

  private  int  x,y;

  public Position( int x1,  int y1 ) {
    x = x1;
    y = y1;
  }

  public  int  getX( ) {
    return  x;
  }

  public  int  getY( ) {
    return  y;
  }

  public  void  setX( int x1 ) {
    x = x1;
  }

  public  void  setY( int y1 ) {
    y = y1;
  }
}
 
0
Comment
Question by:flameonice
  • 6
  • 6
12 Comments
 
LVL 7

Expert Comment

by:Sasha_Mapa
ID: 2697466
A.
>> while (true){
>>    repaint();
>>    try{
>>      Thread.sleep();
>>    } catch (InterruptedException e) {}
>> }

This is just plain simple HORRIBLE. You should NEVER do such a thing. Whenever one of your objects updates, only then you should repaint it.
It's a good thing your forgot to run a new thread that would execute that code!!

B. The "Position" class is already implemented in java, it's named java.awt.Point.

C. Well, of course -- You shouldn't see any updates on the screen at all because you are changing the positions of your trains but never bother to repaint and your horrible code that I described in (A) is never executed (I assume it was intended to repaint) because you never run a new Thread with your class (which is Runnable) as the parameter for the constructor.
0
 

Author Comment

by:flameonice
ID: 2698373
Please tell me how to change my program.  I am not quite clear with that.  Thanks.
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
ID: 2698428
Well, something like this should work:


import java.awt.event.*;
import javax.swing.*;
import java.applet.*;
import java.awt.*;
import  java.net.URL;
import  java.util.*;


public class Tryit extends JFrame implements Runnable{

   private Thread  thread = null;
   private Train train1, train2;
   private boolean stop; //  set this to true when you want to stop the trains
   Container c;
   Position p1 = new Position( 100,200 ), p2 = new Position(110,80);                    
   public Tryit() {
       train1 = new Train( 1, new Point(100,200) );
       train2 = new Train( 2, new Point(110,180) );
   }
                         
   public void run(){
      while (!stop){
         train1.move();
         train2.move();
         repaint();
         try {
            Thread.sleep(10);
         } catch (InterruptedException e){return;}
      }
   }

   public static void main(String[] args) {
      Tryit frame = new Tryit();

      WindowListener l = new WindowAdapter() {
          public void windowClosing(WindowEvent e) {System.exit(0);}
       };

       frame.addWindowListener(l);
       frame.setSize(1200, 980);
       frame.show();
       thread = new Thread(frame);
       thread.start(); // This executes the run() method in another thread.
   }


   public void stopMovingTrains(){
      stop = true;
   }

   public void paint( Graphics g ){
       train1.paint(g);
       train2.paint(g);
   }
}


/**
   Train.java
*/

class Train {

   private  int  trainNo,  dx = 2, dy = 2 ;
   private  Point  currentPosition;
                         
   public Train( int no, Point p ) {
       trainNo = no;
       currentPosition = p;
   }

   public void move(){
       int x = currentPosition.getX(); // x and y should be local variables.
       int y = currentPosition.getY();
                       
       x = x + dx ;
       y = y + dy;
       if ( x < 0 ) dx/=-2;
       if ( x > 900 ) dx*=-2;
       if ( y < 0 ) dy/=-2;
       if ( y > 500 ) dy*=-2;
       currentPosition.move(x,y);
   }

   public void paint( Graphics g ){
      g.drawOval( currentPosition.x -2, currentPosition.y - 2, 5, 5);
   }
}


There might still be some small bugs in this code here and there :-)
0
 

Author Comment

by:flameonice
ID: 2698455
Please tell me how to change my program.  I am not quite clear with that.  Thanks.
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
ID: 2698518
Just did that, didn't I?
0
 

Author Comment

by:flameonice
ID: 2698612
Yes.  It work now.  Is that possible for me to erase previous painted oval before repaint?  Thanks.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:flameonice
ID: 2698843
Yes.  It work now.  Is that possible for me to erase previous painted oval before repaint?  Thanks.
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
ID: 2699091
It is not needed, it should get erased by itself, because repaint() asks the system to call update(Graphics) which clears the component with the background color and then calls paint(Graphics) so if you don't override update(Graphics), it should erase whatever you painted last time.

I'm going away until Friday so I won't be able to answer any questions until then, sorry.
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
ID: 2699093
Generally, if you want to erase something, you would use g.setColor(getBackground()) and g.fillRect(x,y,width,height) to fill a rectangle with the background color.
0
 

Author Comment

by:flameonice
ID: 2709455
I debugged the program you gave me.  It works, but can not erase previous painted oval.  I append it below.


import java.awt.event.*;
import javax.swing.*;
import java.applet.*;
import java.awt.*;
import  java.net.URL;
import  java.util.*;


public class Tryit2 extends JFrame implements Runnable{

   private Thread  thread = null;
   private Train train1, train2;
   private boolean stop; //  set this to true when you want to stop the trains
   Container c;
   Position p1 = new Position( 100,200 ), p2 = new Position(110,80);                    
   public Tryit2() {
       train1 = new Train( 1, new Position(100,200) );
       train2 = new Train( 2, new Position(110,180) );
   }
                         
   public void run(){
      while (!stop){
         train1.move();
         train2.move();
         repaint();
         try {
            Thread.sleep(100);
         } catch (InterruptedException e){return;}

         System.err.println( " tryit run end! ");
      }
   }

   public static void main(String[] args) {
      Tryit2 frame = new Tryit2();

      WindowListener l = new WindowAdapter() {
          public void windowClosing(WindowEvent e) {System.exit(0);}
       };

       frame.addWindowListener(l);
       frame.setSize(1200, 980);
       frame.show();
       frame.thread = new Thread(frame);
       frame.thread.start(); // This executes the run() method in anotherthread.
   }


   public void stopMovingTrains(){
      stop = true;
   }

   public void paint( Graphics g ){
       train1.paint(g);
       train2.paint(g);
       System.err.println( " tryit paint end! ");
   }
}


/**
   Train.java
*/

class Train {

   private  int  trainNo,  dx = 1, dy = 1;
   private  Position  currentPosition;
                         
   public Train( int no, Position p ) {
       trainNo = no;
       currentPosition = p;
   }

   public void move(){
       int x = currentPosition.getX(); // x and y should be local variables.
       int y = currentPosition.getY();
                       
       x = x + dx ;
       y = y + dy;
       if ( x < 0 ) dx/=-1;
       if ( x > 900 ) dx*=-1;
       if ( y < 0 ) dy/=-1;
       if ( y > 500 ) dy*=-1;
       
       currentPosition.setX( x );
       currentPosition.setY( y );
       System.err.println( " train "+trainNo+" x "+x+" y "+y);

   }

   public void paint( Graphics g ){
     g.drawOval( currentPosition.getX() -2, currentPosition.getY() - 2, 5, 5);
     System.err.println( " train paint "+trainNo+" end! ");
   }
}


/**
  Position.java
*/


class Position {

  private  int  x,y;

  public Position( int x1,  int y1 ) {
    x = x1;
    y = y1;
  }

  public  int  getX( ) {
    return  x;
  }

  public  int  getY( ) {
    return  y;
  }

  public  void  setX( int x1 ) {
    x = x1;
  }

  public  void  setY( int y1 ) {
    y = y1;
  }
}
0
 
LVL 7

Accepted Solution

by:
Sasha_Mapa earned 50 total points
ID: 2716145
Sorry for answering so late, I was away.
I'm not sure why JFrame's update method doesn't paint the background, but this should solve the problem:
Add the following lines to the beginning of the paint(Graphics) method in class Tryit2:

g.setColor(getBackground());
Rectangle r = getBounds();
g.fillRect(0,0,r.width,r.height);

I hope this code is self explanatory :-)
0
 

Author Comment

by:flameonice
ID: 2718573
Thank you.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now