2013-05-30 3 views
1

Следующий код - это анимация часов.Почему часы мерцают?

Какие изменения должны были быть внесены в программу, чтобы она не мерцала?

Почему инициирование поля должно выполняться в функции addNotify() для отображаемых рук?

Вы можете скопировать все его в один .java-файл, и он должен работать (мерцание;)).

import java.awt.*; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.util.Calendar; 
import java.util.GregorianCalendar; 

public class ac extends Frame implements Runnable { 

    // for double buffering 
    Graphics og; 
    Image oi; 
    Thread t = null; 
    int width, height; 
    int timeH, timeM, timeS, radius = 50, lenH, lenM, lenS, 
     lenIn, cx, cy, x1, y1, x2, y2; 
    private boolean timeToQuit; 

    ac() { 

     addWindowListener(new WindowAdapter() { 

      public void windowClosing(WindowEvent we) { 
       stopRunning(); 
       dispose(); 
      } 

     }); 

     setMinimumSize(new Dimension(300, 300)); 

     EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       setVisible(true); 
      } 
     }); 
    } 

    public void addNotify() { 
     super.addNotify(); 

     width = getBounds().width; 
     height = getBounds().height; 
     setSize(width, height); 

     lenH = 5 * radius/10; 
     lenM = 6 * radius/10; 
     lenS = 7 * radius/10; 
     lenIn = 8 * radius/10; 
     cx = width/2; 
     cy = height/2; 

     // for double buffering 
     oi = createImage(width, height); 

     og = oi.getGraphics(); 

    } 

    public static void main(String [] args) { 
     ac clock = new ac(); 
     clock.start(); 
    } 

    public void start() { 
     if (t == null) { 
      t = new Thread(this); 
      t.start(); 
     } 
    } 

    public void stopRunning() { 
     timeToQuit = true; 
    } 

    public void run() { 

     Thread.currentThread().setPriority(Thread.NORM_PRIORITY - 1); 
     do { 
      repaint(); 
      try { 
       Thread.sleep(500); 
      } 
      catch (InterruptedException e) { 
      } 
     } 
     while (!timeToQuit); 
     System.out.println("Quitting"); 

    } 

    public void paint(Graphics g) { 
     og.setColor(new Color(170, 170, 170)); 
     og.fillRect(0, 0, width, height); 
     Calendar cal = new GregorianCalendar(); 
     timeH = cal.get(Calendar.HOUR); 
     timeM = cal.get(Calendar.MINUTE); 
     timeS = cal.get(Calendar.SECOND); 

     if (timeH >= 12) 
      timeH -= 12; 

     for (int i = 1 ; i < 13 ; i++) { 
      og.setColor(new Color(20, 20, 20)); 
      x2 = (int) (cx + radius * Math.sin(i * 2 * 3.14159f/12)); 
      y2 = (int) (cy - radius * Math.cos(i * 2 * 3.14159f/12)); 
      if (i % 3 != 0) { 
       x1 = (int) (cx + 0.9f * radius * Math.sin(i * 2 * 3.14159f/12)); 
       y1 = (int) (cy - 0.9f * radius * Math.cos(i * 2 * 3.14159f/12)); 
      } 
      else { 
       x1 = (int) (cx + 0.8f * radius * Math.sin(i * 2 * 3.14159f/12)); 
       y1 = (int) (cy - 0.8f * radius * Math.cos(i * 2 * 3.14159f/12)); 
      } 
      og.drawLine(x1, y1, x2, y2); 
      og.setColor(new Color(230, 230, 230)); 
      og.drawLine(x1 - 1, y1 - 1, x2 - 1, y2 - 1); 
     } 

     og.setColor(new Color(20, 20, 20)); 
     x2 = (int) (cx + lenH * Math.sin((timeH + timeM/60.0f + timeS/3600.0f) 
      * 2 * 3.14159f/12)); 
     y2 = (int) (cy - lenH * Math.cos((timeH + timeM/60.0f + timeS/3600.0f) 
      * 2 * 3.14159f/12)); 
     og.drawLine(cx, cy, x2, y2); 
     og.setColor(Color.red); 
     og.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1); 

     og.setColor(new Color(20, 20, 20)); 
     x2 = (int) (cx + lenM * Math.sin((timeM + timeS/60.0f) * 2 * 3.14159f 
      /60)); 
     y2 = (int) (cy - lenM * Math.cos((timeM + timeS/60.0f) * 2 * 3.14159f 
      /60)); 
     og.drawLine(cx, cy, x2, y2); 
     og.setColor(Color.green); 
     og.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1); 

     og.setColor(new Color(20, 20, 20)); 
     x2 = (int) (cx + lenS * Math.sin(timeS * 2 * 3.14159f/60)); 
     y2 = (int) (cy - lenS * Math.cos(timeS * 2 * 3.14159f/60)); 
     og.drawLine(cx, cy, x2, y2); 
     og.setColor(Color.blue); 
     og.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1); 

     og.setColor(new Color(20, 20, 20)); 
     og.drawOval((width - 2 * radius)/2, (height - 2 * radius)/2, 
      2 * radius, 2 * radius); 
     og.setColor(new Color(230, 230, 230)); 
     og.drawOval((width - 2 * radius)/2 - 1, (height - 2 * radius)/2 - 1, 
      2 * radius, 2 * radius); 

     g.drawImage(oi, 0, 0, this); 
    } 
} 
+0

нарисуйте его дважды на тех же габаритах, и он не будет фикнуть –

+0

Извините, что вы имеете в виду дважды в тех же измерениях? – user2433771

ответ

1

Верьте или нет, эта проблема была решена путем добавления функции:

public void update(Graphics g) 

     { 

      paint(g); 

     } 

Но остается вопрос, почему? И почему не отображаются руки при инициализации полей класса вне функции addNotify()?

+0

Обновление по умолчанию очищает экран, а затем вызывает краску. Это в awt книгах 101. Забыли об этом все эти годы. поэтому он побеждает двойную буферизацию. когда вы это делаете, содержимое текущего экрана остается до тех пор, пока вы не подготовите новый экран в буфере экрана и не нарисуете его в одном изображении с рисунком. – tgkprog

+0

http://www.oracle.com/technetwork/java/painting-140037.html#awt_summary – tgkprog

1

Это использует AWT, который стар и рисует на главной раме - не самый лучший способ, чтобы сделать качели UI. Вы можете попробовать это:

  1. сделать таймер - количество сна, чтобы меньше или больше, попробуйте 300 или 800
  2. использовать панель рисовать, добавьте панель к раме
  3. использовать свинг (использовать JComponent, это двойной буфер автоматически, и JFrame

для 2 и 3 вы можете сохранить исходный класс, чтобы сделать Рам/JFrame и новый класс для java.awt.Panel или javax.swing.JComponent, которая добавляется к первому.

Не мерцает на моей Mac-системе, поэтому я думаю, что ее OS + раз обновляет ее. Значение предложения 1 может работать - попробуйте это первым. Говоря о строке кода:

Thread.sleep(800); 
+0

Спасибо за ответ, я решил сделать это в awt, чтобы лучше понять его механизмы. Смена таймера - сон не работал. Если он не мерцает в вашей системе, попробуйте увеличить окно, переместиться и т. Д., И это, вероятно, будет. – user2433771

Смежные вопросы