旋转矩形并在sin波中移动它 - 使用graphics2D帮助 [英] Rotate rectangle and move it in sin wave - Help using graphics2D

查看:148
本文介绍了旋转矩形并在sin波中移动它 - 使用graphics2D帮助的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨!

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

I have the code below using previous Stackoverflow posts.

我想要旋转矩形按一定角度移动并使其在sin波中移动。

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

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

This code rotates the whole sin wave too.

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

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

请帮助!!!

非常感谢您花时间。

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 SSCCE

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

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

2)应在 EDT 并与 Swing Timers

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

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

4)不需要 frame.getContentPane.add(..)只需使用添加(..),因为所有呼叫都转发到 contentPane

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

以下是示例我做了(基本上你的代码实现了上面的修复),它只使用 AffineTransform #createTransformed Shape()

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

这篇关于旋转矩形并在sin波中移动它 - 使用graphics2D帮助的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆