-2

我想用Java制作一个程序。我想做的是,当用户单击屏幕时,会绘制一个小方块。一个又一个的十个方格以前一个方格为中心显示。绘制第六个方块时,第一个方块消失,绘制第七个方块时,第二个方块消失,依此类推,直到所有方块都消失。

这是主活动:

import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainActivity {
    public static int width = 900;
    public static int height = width / 16 * 9;

    static HandlerClass handler = new HandlerClass();

    static JFrame window;
    static JPanel windowInner;

    public static void main(String[] args) {
        window = new JFrame("Squarmony 1.0");
        window.setSize(width, height);
        window.setVisible(true);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        windowInner = new JPanel();
        windowInner.setSize(width, height);
        windowInner.setBackground(Color.BLACK);

        window.add(windowInner);
        windowInner.addMouseListener(handler);
    }

    private static class HandlerClass implements MouseListener {
        @Override
        public void mouseClicked(MouseEvent e) {
            // TODO Auto-generated method stub
            GraphicsActivity g = new GraphicsActivity();
            g.drawRectRipple(window.getGraphics(), e);
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mousePressed(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub

        }
    }
}

这是GraphicsActivity:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;

public class GraphicsActivity {
    public void drawRectRipple(Graphics g, MouseEvent e) {
        g.setColor(Color.WHITE);

        for (int i = 0; i <= 10; i++) {
            for (int j = 0; j <= 250; j += 10) {
                g.drawRect(e.getX() + j / 2, e.getY() - j / 2, j - j / 2, j + j / 2);
                try {
                    Thread.sleep(250);
                } catch (InterruptedException e1) {

                }
            }
        }
    }
}

我怎样才能将矩形(如波纹)一张一张地绘制到屏幕上?

谢谢,

约翰

4

1 回答 1

1

所以可能有很多方法可以实现这一点,有些更容易,有些更难。

背景:

动画是随时间变化的幻觉。这意味着在一段时间内,预计会发生某种变化。在您的情况下,有些正方形会被绘制,有些则不会。

现在,这表明我们需要一些方法来定期更新我们的 UI。现在您可以使用 a Thread,但坦率地说,还有更简单的方法。

Swing 提供了一个Timer按固定时间间隔提供事件的类,这允许我们在事件调度线程的上下文中安全地更改 UI。

这很重要,因为预计 UI 的所有更新和修改都发生在 EDT 的上下文中。此外,任何阻止 EDT 的操作都会阻止 UI 更新。查看Swing 中的并发以获取更多详细信息。

现在,您可以设置一个计时器,以符合您需要的预定义时间间隔进行计时。即,您需要在n秒内进行 10 次更新,但这开始使您处于不利地位,因为您的所有计算都将基于一些已知的音乐会值...虽然您当然可以这样做,但我更喜欢更灵活的解决方案。

因此,相反,我选择使用基于“百分比”的方法。也就是说,我所有的动画都是基于知道在循环的给定百分比上,需要发生一些事情。这使得在不对绘制算法产生不利影响的情况下具有可变的时间范围成为可能。

为了实现这一点,我们需要知道周期何时开始以及周期有多长。通过这种方式,我们可以计算一个周期正在运行的持续时间和完成的周期的百分位数,例如

Timer timer = new Timer(40, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // Check to see if the cycle has being completed...
        if (cycleStartedAt == -1) {
            // The time that this cycle started
            cycleStartedAt = System.currentTimeMillis();
        }
        // The amount of time this cycle has being running
        long duration = System.currentTimeMillis() - cycleStartedAt;
        // The progress through this cycle...
        progress = (double)duration / (double)runningTime;
        // Check for the completion of this cycle...
        if (progress > 1.0d) {
            // Reset..
            cycleStartedAt = -1;
            progress = 0;
        }
        repaint();
    }
});
timer.setRepeats(true);
timer.start();

这实际上为我们提供了什么?这使我们能够根据时间百分比对动画进行建模。例如...

private double[][] squares = {
    {0, 0.30},
    {0.075, 0.375},
    {0.15, 0.45},
    {0.225, 0.525},
    {0.30, 0.60},

    {0.30, 0.675},
    {0.375, 0.75},
    {0.45, 0.825},
    {0.525, 0.90},
    {0.6, 0.975},
};

这是 10 个方格的列表,每个方格都有一个开始和结束百分比,指示每个方格何时应该可见。

最后,一个可运行的例子......

在此处输入图像描述

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Squares {

    public static void main(String[] args) {
        new Squares();
    }

    public Squares() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private int runningTime = 5000;
        private long cycleStartedAt = -1;
        private double progress = 0;

        private double[][] squares = {
            {0, 0.30},
            {0.075, 0.375},
            {0.15, 0.45},
            {0.225, 0.525},
            {0.30, 0.60},

            {0.30, 0.675},
            {0.375, 0.75},
            {0.45, 0.825},
            {0.525, 0.90},
            {0.6, 0.975},
        };

        public TestPane() {
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (cycleStartedAt == -1) {
                        cycleStartedAt = System.currentTimeMillis();
                    }
                    long duration = System.currentTimeMillis() - cycleStartedAt;
                    progress = (double)duration / (double)runningTime;
                    if (progress > 1.0d) {
                        cycleStartedAt = -1;
                        progress = 0;
                    }
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics g2d = (Graphics2D) g.create();
            int width = getWidth() - 1;
            int height = getHeight() - 1;

            int hGap = width / squares.length;
            int vGap = height / squares.length;

            int index = 0;
            for (double[] square : squares) {                
                if (progress >= square[0] && progress <= square[1]) {                    
                    int sWidth = hGap * (index + 1);
                    int sHeight = vGap * (index + 1);
                    int x = (width - sWidth) / 2;
                    int y = (height - sHeight) / 2;
                    g2d.drawRect(x, y, sWidth, sHeight);

                }
                index++;                
            }            
            g2d.dispose();
        }        
    }    
}

查看执行自定义绘画2D 图形了解更多详细信息

于 2013-09-15T07:48:10.210 回答