Rotate rectangle and move it in sin wave - Help using graphics2D

南楼画角 提交于 2019-12-02 05:40:58

问题


Hi!

I have the code below using previous Stackoverflow posts.

I want to just rotate the rectangle by some angle and make it move in sin wave.

This code rotates the whole sin wave too.

I understand why it is happening , but I don't know how to achieve my intention.

please help!!!

Thanks a lot for taking time.

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:


+1 for SSCCE

1) Dont forget to have call to super.paintComponent(); as first statement in your overridden paintComponent(..) method.

2) Swing UI should be created on EDT and used in conjunction with Swing Timers

3) Java variable naming convention for classes is uppercase letter for each new word i.e WithRotation.

4) No need for frame.getContentPane.add(..) simply use add(..) as all calls are forwarded to its contentPane.

Here is the example I made (basically your code with above fixes implemented), which only rotates the rectangle which follows the graph and not the whole graphics object using AffineTransform#createTransformedShape():

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


来源:https://stackoverflow.com/questions/13519449/rotate-rectangle-and-move-it-in-sin-wave-help-using-graphics2d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!