-3

I have made a program to bounce two balls ,but on running the program it is just showing the two balls and they are not moving , I am not able to understand what is the problem? Is there any problem in start of runnable because when I run only single ball it ran whithout implementing Runnable interface but its not working for two why?

      import java.awt.Color;
        import java.awt.Graphics;
        import java.awt.Graphics2D;
        import java.awt.RenderingHints;

        import javax.swing.JFrame;
       import javax.swing.JPanel;



       public class Jpanel extends JPanel implements Runnable{


        Thread t1;
        Thread t2;
        JFrame frame;
        Jpanel jp;
        int x=0;
        int y=0;
        Ball ball=new Ball(this);
        Ball1 ball1=new Ball1(this);
        void move1(){
            ball.move();

        }
        void move2(){
            ball1.move();
        }
        public void paint(Graphics g){


            super.paint(g); 
            setBackground(Color.black);
            Graphics2D g2d=(Graphics2D)g;
             g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

            ball.paint(g);
            ball1.paint(g);
        //super.paint(g);//agar yaha to puri screen pehle jaisi saaf ho jaegi           
        }


    public static void main(String args[]) throws InterruptedException{

         Jpanel jp=new Jpanel();
       JFrame frame =new JFrame("Chota Bheem");
       frame.add(jp);
       frame.setBackground(Color.BLACK);
       frame.setSize(500,500);
       frame.setVisible(true);
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
       Jpanel t1=new Jpanel();
       Jpanel t2=new Jpanel();
       t1.start();
       t2.start();






         }
       public void start() {
        System.out.println("inside start");
        // TODO Auto-generated method stub
        if(t1==null){
            t1=new Thread(this,"first");
            t1.start();
        }
        if(t2==null){
            t2=new Thread(this,"second");
            t2.start();
        }

    }
     @Override
       public void run() {
        // TODO Auto-generated method stub
            System.out.println("inside run");
        while(true){
            jp.move1();
            jp.repaint();

            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        while(true){
        jp.move2();
        jp.repaint();

        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        }
    }
    }



      class Ball1{
       Jpanel jps;
      int x=0,y=0,xs=-1,ys=-1;
        public Ball1(Jpanel jpanel) {
        // TODO Auto-generated constructor stub
        this.jps=jpanel;

    }
        public void move(){
       if(x+xs<0){xs=1;}
       else if(y+ys<0){y=-1;}
       else if(x+xs>jps.getWidth()-30){xs=-1;}
       else if(y+ys>jps.getHeight()-30){ys=-1;}

       x=x+xs;
       y=y+ys;

     }
     void paint(Graphics g){
      g.setColor(Color.darkGray);  
      g.fillOval(x, y, 60, 60);
   }
    }




       class Ball{
    int x=0;
    int xs=-1,ys=-1;
    int y=0;
    JPanel jpn;
    Ball(JPanel jpn){
        this.jpn=jpn;
    }

    public void move() {


        if(x+xs<0){
            xs=1;
        }
        else if(y+ys<0){
            ys=1;
        }
        else if(x+xs>jpn.getWidth()-30){
            xs=-1;
        }
        else if(y+ys>jpn.getHeight()-30){
            ys=-1;
        }
        x=x+xs;
        y=y+ys;

    }
    public void paint(Graphics g) {

        jpn.setBackground(Color.black);
        g.setColor(Color.blue);
        g.fillOval(x, y, 50, 50);

    }
}
}
SuZure
  • 11
  • 1
  • The single ball ran without runnable because of the one thread. I don't understand why you create Ball1. Also, the title of the thread was incredibly misleading :) – Josef E. May 08 '14 at 21:08
  • Why do you have three Jpanel and four threads? – Peter Lawrey May 08 '14 at 21:12
  • Better separate the JPanel and the Runnables, give each part of your programm the lowest amount of exposure to all the other parts, otherwise you'll not be able to see through your own code very soon. Just give the Balls/JPanel as parameters to the Runnables. – NoDataDumpNoContribution May 08 '14 at 21:14
  • I'd just use a Swing Timer and get rid of the Threads. I'd also paint in the JPanel's `paintComponent` method not its `paint` method, and I'd not call `setBackground(...)` from within a painting method. Do that once and in the constructor. – Hovercraft Full Of Eels May 08 '14 at 21:17

1 Answers1

1
  1. This doesn't require multiple threads - I'm not sure why you're adding this complexity
  2. If threads were the right thing to use (but they aren't), making your own Jpanel class that is Runnable isn't the right way to do it. What you would want to do is have the Ball class be runnable, and have its position updated in a way that's completely separated from drawing stuff on the screen. Mixing your rendering and movement is not a good separation of concerns. Just have your ball worry about where it is and where it's moving, and let the UI worry about drawing where it is.
  3. Swing schedules repaints when it can get around to it, so you're bound to find out at some point that requests to redraw things won't always happen at a consistent frame rate, which may not be what you expect or actually need.
  4. If by any chance you're trying to make a game, Swing is going to be a massive waste of your time. What you need is more direct access to screen rendering. Building games with Swing will slowly kill your spirit and make you want to cry. Use something like Slick2D or libgdx instead.
  5. The Thread instances you're declaring in your custom Jpanel class aren't even used.
  6. Calling Thread.sleep(1) is pretty pointless. Why sleep at all if you're drawing balls on the screen and you're only going to wait about 1 millisecond between ball movements? If you weren't using multiple threads you could either sleep some reasonable amount of time (say, approximately 1/60th of a second) or you could just run at full speed all the time.
Community
  • 1
  • 1
jefflunt
  • 33,527
  • 7
  • 88
  • 126
  • He's not directly invoking `paint(...)` on a component. He's calling it on objects of the logical (non-GUI) class, Ball1, which does not extend any Swing or AWT component, so his code, in this regard is OK. He still should override paintComponent and not paint. I'm also not sure about your point number 2. above. – Hovercraft Full Of Eels May 08 '14 at 21:28
  • Someone edited the OP's post. There were no calls to `repaint` initially. Initially, inside the `Ball` class the OP was calling `.paint` on a `JPanel` instance variable. – jefflunt May 08 '14 at 21:29
  • I copied his code when it was initially posted, and the repaint calls were all there, so I disagree, but regardless, is direct calls to `paint(...)` are kosher since they are on Ball1 objects. Also Swing does do its painting and user interaction in the same thread. **Edit** I just when through the edit history of his original post, and I've confirmed that the `repaint()` calls were always there. – Hovercraft Full Of Eels May 08 '14 at 21:31
  • Whatever. Point #8 removed. – jefflunt May 08 '14 at 21:32
  • Ah, I'm confusing it with the event handling thread, aren't I? Hm. Point #2 removed. – jefflunt May 08 '14 at 21:40
  • I saw this code from edu4java.com and I am a complete beginner to make games, please let me know am I working in a correct way or not, because I have to develop a game within a month anyhow. – SuZure May 09 '14 at 06:44