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);
    }
}
4

2 回答 2

1

信不信由你,通过添加功能解决了问题:

    public void update(Graphics g)

       {

            paint(g);

       }

但问题仍然存在,为什么?为什么在 addNotify() 函数之外启动类字段时不显示手?

于 2013-05-31T10:18:44.977 回答
1

这使用了旧的 awt 并且它在主框架上绘制 - 这不是制作摆动 UI 的最佳方式。你可以试试这个:

  1. 使计时器 - 睡眠量减少或增加,尝试 300 或 800
  2. 使用面板进行绘制,将面板添加到框架
  3. 使用 swing(使用 JComponent,它会自动双倍缓冲,以及一个 JFrame

对于 2 和 3,您可以保留原始类来制作 Frame/JFrame 和添加到前者的 java.awt.Panel 或 javax.swing.JComponent 的新类。

在我的 mac 系统上不闪烁,所以我认为它是一个 OS + 次它的刷新问题。意思是建议 1 可能会起作用 - 先尝试一下。谈论代码行:

Thread.sleep(800);
于 2013-05-30T14:38:00.850 回答