使用Swing和Graphics2D在Java中旋转滚轮?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Swing和Graphics2D在Java中旋转滚轮?相关的知识,希望对你有一定的参考价值。

我正在研究一个可以围绕中心旋转轮子的课程。轮子是使用graphics2d创建的,但我无法弄清楚如何让轮子围绕中心旋转。目前,车轮旋转,但不完全是关于原点。

我的最终目标是制造轮子,使其成为多色的,以及围绕它的程序,但我的主要关注点是让旋转轮工作。如果你能指出我正确的方向,我将永远感激不尽!

这是我目前的代码:

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;


public class RotateApp {

private static final int N = 3;

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {

        public void run() {
            JFrame frame = new JFrame();
            frame.setLayout(new GridLayout(N, N, N, N));
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new RotatePanel());
            frame.pack();
            frame.setVisible(true);
            System.out.println();
        }
    });
}
}


class RotatePanel extends JPanel implements ActionListener {

private static final int SIZE = 256;
private static double DELTA_THETA = Math.PI / 90;
private final Timer timer = new Timer(25, this);
private Image image = RotatableImage.getImage(SIZE);
private double dt = DELTA_THETA;
private double theta;

public RotatePanel() {
    this.setBackground(Color.lightGray);
    this.setPreferredSize(new Dimension(
        image.getWidth(null), image.getHeight(null)));
    this.addMouseListener(new MouseAdapter() {

        @Override
        public void mousePressed(MouseEvent e) {
            image = RotatableImage.getImage(SIZE);
            dt = -dt;
        }
    });
    timer.start();
}


public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.translate(this.getWidth() / 2, this.getHeight() / 2);
    g2d.rotate(theta);
    g2d.translate(-image.getWidth(this) / 2, -image.getHeight(this) / 2);
    g2d.drawImage(image, 0, 0, null);
}

public void actionPerformed(ActionEvent e) {
    theta += dt;
    repaint();
}

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

}

class RotatableImage {

private static final Random r = new Random();

static public Image getImage(int size) {
    BufferedImage bi = new BufferedImage(
        size, size, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = bi.createGraphics();
    g2d.setRenderingHint(
        RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setPaint(Color.getHSBColor(r.nextFloat(), 1, 1));
    g2d.setStroke(new BasicStroke(10.0f));
    g2d.draw(new Line2D.Double(0, 100, 100, 100));
    g2d.draw(new Line2D.Double(100, 100, 200, 100));

    g2d.draw(new Line2D.Double(100, 0, 100, 100));
    g2d.draw(new Line2D.Double(100, 100, 100, 200));

    g2d.draw(new Line2D.Double(25, 25, 100, 100));
    g2d.draw(new Line2D.Double(100, 100, 175, 175));

    g2d.draw(new Line2D.Double(175, 25, 100, 100));
    g2d.draw(new Line2D.Double(100, 100, 25, 175));

    g2d.draw(new Ellipse2D.Double(0, 0, 200, 200));
    g2d.dispose();
    return bi;
}
}
答案

您可以使用Rotated Icon类为您进行旋转,这样您就不必担心所有旋转逻辑,并且旋转逻辑位于可重用的类中。

使用此类的一个示例是:

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.util.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;

public class Rotation4 extends JPanel
{
    private JLabel label;
    private Icon icon;
    private Icon rotated;
    private int degrees;

    public Rotation4(Image image)
    {
        icon = new ImageIcon( image );
        label = new JLabel(icon);
        label.setPreferredSize( label.getPreferredSize() );
        add( label );
        setDegrees( 0 );
    }

    public void setDegrees(int degrees)
    {
        this.degrees = degrees;
        double radians = Math.toRadians( degrees );
        rotated = new RotatedIcon(icon, degrees);
        label.setIcon(rotated);
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                Image bi = RotatableImage.getImage(210);
                final Rotation4 r = new Rotation4(bi);

                    final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
                    slider.addChangeListener(new ChangeListener()
                    {
                        public void stateChanged(ChangeEvent e)
                        {
                            int value = slider.getValue();
                            r.setDegrees( value );
                        }
                    });

                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.add(new JScrollPane(r));
                f.add(slider, BorderLayout.SOUTH);
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }

    static class RotatableImage
    {
        private static final Random r = new Random();

        static public Image getImage(int size)
        {
            BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = bi.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setPaint(Color.getHSBColor(r.nextFloat(), 1, 1));
            g2d.setStroke(new BasicStroke(10.0f));

            g2d.draw(new Line2D.Double(5, 105, 205, 105));
/*
            g2d.draw(new Line2D.Double(100, 100, 200, 100));

            g2d.draw(new Line2D.Double(100, 0, 100, 100));
            g2d.draw(new Line2D.Double(100, 100, 100, 200));

            g2d.draw(new Line2D.Double(25, 25, 100, 100));
            g2d.draw(new Line2D.Double(100, 100, 175, 175));

            g2d.draw(new Line2D.Double(175, 25, 100, 100));
            g2d.draw(new Line2D.Double(100, 100, 25, 175));
*/
            g2d.draw(new Ellipse2D.Double(5, 5, 199, 199));

            g2d.setColor(Color.BLACK);
            g2d.fillOval(100, 100, 10, 10);

            g2d.dispose();
            return bi;
        }
    }
}

注意我还必须对您的图像和绘画进行更改。无论您是使用RotatedIcon还是自己执行旋转代码,都需要进行以下更改:

  1. 图像大小更改为210.这是因为您的笔触大小为10,因此您需要考虑圆形轮廓中的额外像素。
  2. 您需要将圆的原始值改为笔划大小的一半。所以在这种情况下,原点变为(5,5)。
  3. 椭圆的大小需要改为199.这是因为椭圆的轮廓被绘制的方式。轮廓需要1个额外的像素。如果将尺寸保留为200,则轮廓的1个像素将丢失。当使用10的笔触大小时,这不是很明显,但如果使用1的大小,则右边和底边的轮廓将丢失。
  4. 您的线路位置需要更改。你不希望线条直接到圆的边缘,因为那样你将在边缘处得到一条扁平线而不是圆形线。所以我开始从开始的5个像素的行,并结束它从结束5像素。
另一答案

好的,只需要很少的修改和更少的“辐条”,我的轮子旋转为中心(1.)和多色(2.):


更新1.)要在您的(原始)代码中进行中心旋转,只需更改qazxsw posito 200!

SIZE

说明:

  1. 所以你的解决方案中的“摆动”来自于这样一个事实:你将图像和容器/面板尺寸设置为256x256,但仅仅基于200x200的车轮布局。我修正了所有的尺寸,画了一个正确的十字架,然后import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.Image; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.image.BufferedImage; import java.util.Random; import javax.swing.*; public class RotateApp { private static final int N = 3; public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new JFrame(); frame.setLayout(new GridLayout(N, N, N, N)); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new RotatePanel()); frame.pack(); frame.setVisible(true); System.out.println(); }); } } class RotatePanel extends JPanel implements ActionListener { private static final int SIZE = 256; private static final double DELTA_THETA = Math.PI / 90; private final Timer timer = new Timer(25, this); private Image image = RotatableImage.getImage(SIZE); private double dt = DELTA_THETA; private double theta; public RotatePanel() { this.setBackground(Color.lightGray); this.setPreferredSize(new Dimension(SIZE, SIZE)); this.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { dt = -dt; image = RotatableImage.getImage(SIZE); } }); timer.start(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.rotate(theta,128,128); g2d.drawImage(image, 0, 0, null); } @Override public void actionPerformed(ActionEvent e) { theta += dt; repaint(); } @Override public Dimension getPreferredSize() { return new Dimension(SIZE, SIZE); } } class RotatableImage { private static final Random r = new Random(); static public Image getImage(int size) { BufferedImage bi = new BufferedImage( size, size, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = bi.createGraphics(); g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); final Color c1 = Color.getHSBColor(r.nextFloat(), 1, 1); final Color c2 = Color.getHSBColor(r.nextFloat(), 1, 1); g2d.setPaint(c1); g2d.setStroke(new BasicStroke(10.0f)); g2d.draw(new Line2D.Double(0, size/2, size, size/2)); g2d.setPaint(c2); g2d.draw(new Line2D.Double(size/2, 0, size/2, size)); g2d.setPaint(c1); g2d.draw(new Ellipse2D.Double(0, 0, size, size)); g2d.dispose(); return bi; } } (!)与中心相关联。
  2. 多色(简单):你可以在每个形状之间调用g2d.rotate(theta,128,128);! ;)

以上是关于使用Swing和Graphics2D在Java中旋转滚轮?的主要内容,如果未能解决你的问题,请参考以下文章

Java程序设计图形用户界面

如何在 Java Swing 中创建投影、内发光和外发光?

Java Graphics2D 画出文字描边效果

java绘图

有关Java的awt或者swing实现在图片上添加文字的处理(像素和字符串长度单位转换的问题)

Java中的Graphics2D类基本使用教程