Solved

Threads don't work with JFrame

Posted on 2000-04-08
12
298 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
The Ultimate Checklist to Optimize Your Website

Websites are getting bigger and complicated by the day. Video, images, custom fonts are all great for showcasing your product/service. But the price to pay in terms of reduced page load times and ultimately, decreased sales, can lead to some difficult decisions about what to cut.

 

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
 

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

MS Dynamics Made Instantly Simpler

Make Your Microsoft Dynamics Investment Count  & Drastically Decrease Training Time by Providing Intuitive Step-By-Step WalkThru Tutorials.

Question has a verified solution.

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

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.

691 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