2013-07-26 2 views
0

Вот часть моего простого кода. Этот код содержит подвижные овальные и статические овалы с коордами newX=100,newY=100. Я пытаюсь добиться перемещения подвижного овала автоматически после нажатия левой кнопки мыши. Thread thread .Thrad действительно начинается с нажатия кнопки мыши, но ничего не происходит. Просто после того, как один шаг с помощью клавиш со стрелками, овал начинает двигаться. Я пробовал называть метод repaint() в разных местах, но он, похоже, не помогает. Все предложения? Спасибо!Java-start thread issue

public class Buffer extends JPanel implements Runnable,KeyListener,MouseListener{ 
public static int x; 
public static int y; 
public static int newX; 
public static int newY; 
public static Thread thread; 
public static boolean check; 
public static JFrame frame; 
public static int pointX; 
public static int pointY; 
public static boolean repaint; 


public void paintComponent(Graphics g){ 
    super.paintComponent(g); 

    g.drawOval(x, y, 20, 20); 

     newX=100; 
     newY=100; 
     g.fillOval(newX, newY, 20, 20); 

     if(repaint) 
      repaint(); 
} 
public static void main(String args[]){ 
    Buffer z=new Buffer(); 
    z.setBackground(Color.white); 

    frame=new JFrame(); 
    frame.setSize(500,500); 
    frame.addKeyListener(z); 
    frame.addMouseListener(z); 
    frame.add(z); 
    frame.setVisible(true); 
    frame.requestFocusInWindow(); 

    thread=new Thread(){ 
     public void run(){ 
      try{ 
       for(int i=0;i<=5;i++){ 
        x=x+i; 
        repaint=true; 
        thread.sleep(1000); 

       } 
      }catch(InterruptedException v){System.out.println(v);} 
      } 
     }; 

} 
public void keyPressed(KeyEvent e){ 
    if(e.getKeyCode()==KeyEvent.VK_LEFT){ 
     x=x-10; 
     repaint(); 
    } 
    if(e.getKeyCode()==KeyEvent.VK_RIGHT){ 
     x=x+10; 
     repaint(); 
    } 
    if(e.getKeyCode()==KeyEvent.VK_UP){ 
     y=y-10; 
     repaint(); 
    } 
    if(e.getKeyCode()==KeyEvent.VK_DOWN){ 
     y=y+10; 
     repaint(); 
    } 
} 

public void mouseClicked(MouseEvent e) { 
     thread.start(); 
    } 
} 

ответ

2

Вы изменяете общие переменные из потока и читаете их из другого, без какой-либо синхронизации. Это неверно. Каждый доступ к общей переменной должен выполняться синхронизированным способом или использовать поточно-безопасные объекты (например, AtomicInteger).

Кроме того, нить изменяет значение x в цикле, но никогда не вызывает repaint(), поэтому нет никакой причины, чтобы панель перекрашивала себя.

+0

Я не могу вызвать repaint() в статическом методе. Вот почему я использовал булевскую переменную repaint для запуска метода repaint() в методе paintComponent. –

+1

Изменение логического значения магическим способом не вызовет метод. Вам нужно вызвать repaint() в буфере. Итак, вызовите 'z.repaint()' (и сделайте final 'z' final возможным для этого из внутреннего класса). Тем не менее, все эти переменные и методы должны * не * быть статическими. У меня такое ощущение, что вы еще не понимаете основы OO. Сначала изучите основы, прежде чем использовать Swing и даже больше, потоки. Параллельное программирование * чрезвычайно * комплексно. –

+0

Я попробовал это, и теперь он работает. Я только ожидал, что изменение переменной boolean вызовет перерисовку из блока 'if (check) repaint();'. Давно спасибо вам большое. Ваше чувство не далеко от действительности. Я довольно новый для программирования. –

1

Я не знаю, если это возможно, вопрос здесь, но я собираюсь дать ему попробовать:

Попробуйте использовать AtomicInteger для x и y переменных, как код не поточно-безопасным.

Вы пытаетесь получить доступ к общей переменной для нескольких потоков и выполнить операцию приращения, которая не является атомарной и, следовательно, не является потокобезопасной.