2013-07-26 2 views
0

Heres часть моего простого кода. Я хочу добиться перемещения овала до курсора. Расположение оси X после нажатия левой кнопки. Проблема заключается в том, что я могу видеть только последнюю позицию овала (когда это уже останавливается). Я думаю, что метод repaint во время блокировки не работает, как хотелось бы. Я хотел бы видеть каждый ход овала как его попадание в позицию cursor.Thank вас для предложений.Java repaint проблемные овалы каждый ход

import java.awt.*; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import javax.swing.*; 

public class Testfile extends JPanel implements Runnable,MouseListener{ 
public static JFrame frame; 
public int x; 
public int y; 
public int pointX; 
public int pointY; 

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

    g.fillOval(x, y, 20, 20); 
} 

public static void main(String args[])throws InterruptedException{ 
    Testfile z=new Testfile(); 
    z.setBackground(Color.cyan); 

    frame=new JFrame("Test"); 
    frame.setSize(500,500); 
    frame.add(z); 
    frame.addMouseListener(z); 
    frame.setVisible(true); 
} 
public void mouseClicked(MouseEvent e){ 
    pointX=(int)MouseInfo.getPointerInfo().getLocation().getX(); 
    pointY=(int)MouseInfo.getPointerInfo().getLocation().getY(); 

    try{ 
    while(x!=pointX){ 
     x=x+1; 
     Thread.sleep(10); 
     repaint(); 
     } 
    } 
     catch(InterruptedException v){System.out.println(v);} 
} 
+0

Почему у вас есть тег 'multithreading'? Я не вижу многопоточности в вашем коде. – Jashaszun

+1

вы блокируете 'EDT' – nachokk

ответ

3

.Я думаю перекрасить метод в то время как блок не работает, как я хотел бы

Ваша проблема не имеет ничего общего с перекрашивание «не работает», и все, чтобы сделать с вашим завязывания вверх по Качание событий. Если вы запускаете длительный процесс в потоке отправки событий Swing (или EDT), потоке, ответственном за рисование графического интерфейса пользователя и взаимодействии с пользователем, ваш графический интерфейс зависает и не будет рисовать себя или отвечать до тех пор, пока EDT не будет выпущен.

Решение: не используйте цикл while (true) или Thread.sleep(...) в потоке событий Swing. Также:

  • Используйте таймер Swing вместо того, чтобы действовать как «цикл» анимации.
  • Еще одно возможное решение - использовать фоновый поток, чтобы сделать Thread.sleep(...), но, на мой взгляд, это не стоит проблем, так как Swing Timer будет работать так хорошо и его проще реализовать правильно.

также:

  • Не добавляйте MouseListener в JFrame, а к чертежу JPanel. В противном случае вы обнаружите, что вы будете в направлении y по высоте строки заголовка.
  • Использовать метод mousePressed(...) не mouseClicked(...), так как первый более прощающий.
  • Получите deltaX и deltaY на mousePressed, направление, в котором должен проходить круг, вычитая x из pointX и y из pointY.
  • Я получил ваш код для работы, проверив расстояние Манхэттена между x и y и pointX (manHattanDistance = Math.abs(x - pointX) + Math.abs(y - pointY);) и pointY и остановив таймер, если он достигнет минимума. Я также сохранил предыдущее расстояние в Манхэттене и проверил различия между старым и новым, чтобы убедиться, что овал не переборщил, как отказоустойчивость.
  • Используйте удвоения, чтобы удерживать ваши x, y, pointX, pointY и т. Д., И бросать в int при рисовании.
  • Не забудьте нанести свой графический объект на Graphics2D и использовать RenderingHints, чтобы включить сглаживание. Это создаст более красивую графику.
  • Избегайте «волшебных» чисел. Вместо этого используйте константы.
  • Рассмотрите возможность использования x и y для центра вашего круга, а не левого верхнего угла.

Например, мой paintComponent(...) метод может выглядеть следующим образом:

public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2 = (Graphics2D) g; 
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
     RenderingHints.VALUE_ANTIALIAS_ON); 

    // RADIUS is an int const and = 10 
    g.fillOval((int) x - RADIUS, (int) y - RADIUS, 2 * RADIUS, 2 * RADIUS); 
} 
+1

+1 сегодня я вижу, что вы отвечаете на ту же проблему примерно за 5 раз xD – nachokk

0

Как указано выше. вам нужно делать это на отдельных потоках.

Иногда вам нужно уменьшить x, чтобы проверить, если он уже больше, чем точка нажата, или программа будет продолжать увеличивать ее на неопределенный срок. Также вы, вероятно, захотите сделать то же самое с y