Question

I have made a GUI that uses a slider to scale an object up and down.(in this case a rectangle). I was wondering if there was a way to also use a slider to specify a degree of rotation. So there would be 2 sliders one to control scale and another to control the rotation. If anyone could help me make this that would be great here is what I have so far with just the scale slider.

import javax.swing.*;


public class Parker
{
    public static void main(String[] args)
    {

        TheWindow w = new TheWindow();
        w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //X wont close the window with out this line
        w.setSize(1280,720);
        w.setVisible(true);
    }

}



import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;


public class TheWindow extends JFrame
{
    private JSlider slider; //declare slider
    private drawRect myPanel; //declare/ create panel


    public TheWindow()
    {
        super("Slider Example"); //make title
        myPanel = new drawRect();
        myPanel.setBackground(Color.cyan); //change background color

        slider = new JSlider(SwingConstants.VERTICAL, 0, 315, 10);// restrains the slider from scaling square to 0-300 pixels
        slider.setMajorTickSpacing(20); //will set tick marks every 10 pixels
        slider.setPaintTicks(true); //this actually paints the ticks on the screen

        slider.addChangeListener
        (
            new ChangeListener()
            {
                public void stateChanged(ChangeEvent e)
                {
                    myPanel.setD(slider.getValue()); //Wherever you set the slider, it will pass that value and that will paint on the screen
                }
            }

        );

        add(slider, BorderLayout.WEST); //similar to init method, adds slider and panel to GUI
        add(myPanel, BorderLayout.CENTER);


    }



import java.awt.*;
import javax.swing.*;

public class drawRect extends JPanel
{

    private int d = 20; //this determines the beginning size of the rect. 

    public void paintComponent(Graphics g)//paints obj on the screen
    {
        super.paintComponent(g); //prepares graphic object for drawing

       // ImageIcon i = new ImageIcon("A:\\Capture.png"); //location of Image
       // i.paintIcon(this, g, d, d); //paints icon on screen

        int originX = getWidth() / 2; //this is subtracting half of 'd' from the center point to scale it form the center
        int originY = getHeight() / 2;

        int x = originX - (d / 2);
        int y = originY - (d / 2);
        System.out.println(x + "x" + y);

        g.fillRect(x, y, d, d); //paints rectangle on screen
        //x , y, width, height      
    }           
Was it helpful?

Solution

Okay, I've been playing around with this for a while I would normally use a AffineTransform for this, but it was giving me weird results I couldn't resolve...

ZoomSpin

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class Parker {

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

    public Parker() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

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

    public class ControlPane extends JPanel {

        private JSlider slider; //declare slider
        private DrawPane myPanel; 
        public ControlPane() {
            setLayout(new BorderLayout());
            myPanel = new DrawPane();
            myPanel.setBackground(Color.cyan); //change background color

            slider = new JSlider(SwingConstants.VERTICAL, 0, 400, 100);// restrains the slider from scaling square to 0-300 pixels
            slider.setMajorTickSpacing(20); //will set tick marks every 10 pixels
            slider.setPaintTicks(true); //this actually paints the ticks on the screen

            slider.addChangeListener(
                    new ChangeListener() {
                        @Override
                        public void stateChanged(ChangeEvent e) {
                            myPanel.setScale(slider.getValue()); //Wherever you set the slider, it will pass that value and that will paint on the screen
                        }
                    }
            );

            JSlider rotate = new JSlider(SwingConstants.VERTICAL, 0, 720, 0);
            rotate.setMajorTickSpacing(20); //will set tick marks every 10 pixels
            rotate.setPaintTicks(true); //this actually paints the ticks on the screen

            rotate.addChangeListener(
                    new ChangeListener() {
                        @Override
                        public void stateChanged(ChangeEvent e) {
                            JSlider slider = (JSlider) e.getSource();
                            myPanel.setAngle(slider.getValue()); 
                        }
                    }
            );
            add(slider, BorderLayout.WEST);
            add(rotate, BorderLayout.EAST);

            add(myPanel);

            myPanel.setScale(400);
        }

    }

    public class DrawPane extends JPanel {

        private double scale = 1;
        private double angle = 0;

        private final int rectWidth = 20;
        private final int rectHeight = 20;


        @Override
        protected void paintComponent(Graphics g)//paints obj on the screen
        {
            super.paintComponent(g); //prepares graphic object for drawing

            int originX = getWidth() / 2; 
            int originY = getHeight() / 2;

            int xOffset = -(rectWidth / 2);
            int yOffset = -(rectHeight / 2);

            g.setColor(Color.BLACK);
            Graphics2D g2d = (Graphics2D) g.create();

            g2d.translate(originX, originY);
            g2d.scale(scale, scale);
            g2d.rotate(Math.toRadians(angle), 0, 0);

            g2d.fill(new Rectangle2D.Double(xOffset, yOffset, rectWidth, rectHeight));
            g2d.dispose();

            g.setColor(Color.RED);
            g.drawRect(originX + xOffset, originY + yOffset, rectWidth, rectWidth);
        }

        public void setAngle(double angle) {
            this.angle = angle;
            repaint();
        }

        public void setScale(int scale) {
            // Scaling is normalized so that 1 = 100%
            this.scale = (scale / 100d);
            repaint();
        }

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

    }

}

Basically this uses the Graphics APIs capabilities, for simplicity (in particular with the spinning), the Graphics context is translated to the origin point. The rectangle is then paint around this origin point to allow it to be zoomed and rotate about it's center

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top