旋转矩形并以正弦波移动 - 使用graphics2D帮助

时间:2012-11-22 20:15:34

标签: java swing jpanel graphics2d rotatetransform

嗨!

我使用之前的Stackoverflow帖子获得了以下代码。

我想将矩形旋转一定角度,然后让它在sin波中移动。

此代码也会旋转整个sin波。

我明白为什么会这样,但我不知道如何实现我的意图。

请帮助!!!

非常感谢您花时间。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Withrotation {

    public static int i = 1;
    public static Ticker t;
    public static Repainter r;
    public static int newx, newy;

    public static void main(String[] args) {
        final JFrame frame = new JFrame("Wavy!");
        final WavyPanel wp = new WavyPanel();
        frame.getContentPane().add(wp, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        t = new Ticker(wp);
        r = new Repainter(wp);
        frame.pack();
        frame.setVisible(true);
        final Timer tickTimer = new Timer();
        final Timer paintTimer = new Timer();
        paintTimer.schedule(r, 1000, 50);
        tickTimer.schedule(t, 1000, 10);
    }

    private static class WavyPanel extends JPanel {

        private final Dimension size = new Dimension(640, 480);
        private int amplitude = 50;
        private int frequency = 5;
        private double x1 = 0;
        private double y1 = 500;
        private int yBase = 0;

        WavyPanel() {
            super(true);
        }

        @Override
        protected void paintComponent(final Graphics g) {
            final Graphics2D g2 = (Graphics2D) g;
            AffineTransform old = g2.getTransform();
            g2.rotate(Math.toRadians(-30));

            g2.clearRect(0, 0, this.getSize().width, this.getSize().height);
            g2.setColor(Color.BLACK);
            g2.fillRect((int) x1, (int) y1, 20, 80);
            g2.setTransform(old);


        }

        @Override
        public Dimension getPreferredSize() {
            return size;
        }

        @Override
        public Dimension getMinimumSize() {
            return size;
        }

        @Override
        public Dimension getMaximumSize() {
            return size;
        }

        public void tick() {
            x1 = x1 + 1;
            final int waveLength = size.width / frequency;
            yBase = (++yBase) % waveLength;
            final double normalized = (double) yBase / (double) waveLength;
            final double radians = normalized * Math.PI * 2;
            final double sine = Math.sin(radians);
            y1 = (int) (sine * amplitude);




        }
    }

    private static class Ticker extends TimerTask {

        private final WavyPanel panel;

        Ticker(final WavyPanel panel) {

            this.panel = panel;

        }

        @Override
        public void run() {
            panel.tick();
        }
    }

    private static class Repainter extends TimerTask {

        private final WavyPanel panel;

        Repainter(final WavyPanel panel) {

            this.panel = panel;

        }

        @Override
        public void run() {
            panel.repaint();

        }
    }
}

1 个答案:

答案 0 :(得分:5)

+1 SSCCE

1)不要忘记在被覆盖的super.paintComponent();方法中调用paintComponent(..)作为第一个语句。

2)应在EDT上创建Swing UI,并与Swing Timers

一起使用

3)类的Java变量命名约定是每个新单词的大写字母,即WithRotation

4)frame.getContentPane.add(..)无需使用add(..),因为所有呼叫都会转发到 contentPane

以下是我所做的示例(基本上是您的代码已实现上述修复),它只使用AffineTransform#createTransformedShape()旋转图形后面的矩形而不是整个图形对象:

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class WithRotation {

    private JFrame frame;
    private WavyPanel wp;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new WithRotation();
            }
        });
    }

    public WithRotation() {
        initComponents();
    }

    private void initComponents() {
        frame = new JFrame("Wavy!");
        wp = new WavyPanel();
        frame.add(wp, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

        createAndStartTimers();
    }

    private void createAndStartTimers() {
        new Timer(50, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {

                wp.repaint();
            }
        }).start();
        new Timer(10, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {

                wp.tick();
            }
        }).start();
    }

    class WavyPanel extends JPanel {

        private final Dimension size = new Dimension(640, 480);
        private int amplitude = 50;
        private int frequency = 5;
        private double x1 = 0;
        private double y1 = 500;
        private int yBase = 0;

        WavyPanel() {
            super(true);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;

            g2.clearRect(0, 0, this.getSize().width, this.getSize().height);
            g2.setColor(Color.BLACK);

            Rectangle rect = new Rectangle((int) x1, (int) y1, 20, 80);

            AffineTransform transform = new AffineTransform();
            transform.rotate(Math.toRadians(-30), rect.getX() + rect.width / 2, rect.getY() + rect.height / 2);

            Shape transformed = transform.createTransformedShape(rect);
            g2.fill(transformed);
        }

        @Override
        public Dimension getPreferredSize() {
            return size;
        }

        @Override
        public Dimension getMinimumSize() {
            return size;
        }

        @Override
        public Dimension getMaximumSize() {
            return size;
        }

        public void tick() {
            x1 = x1 + 1;
            final int waveLength = size.width / frequency;
            yBase = (++yBase) % waveLength;
            final double normalized = (double) yBase / (double) waveLength;
            final double radians = normalized * Math.PI * 2;
            final double sine = Math.sin(radians);
            y1 = (int) (sine * amplitude);
        }
    }
}