I have a program where I have to use internal Timer event to rotate a star in circular motion. There is a button in the frame that changes the direction of the star and a slider which changes the speed of the star rotation.
This is my Main Class
import javax.swing.JFrame;
public class Main {
public static void main(String args[]) {
// Making an instance of the class that makes the frame
MainFrame frame = new MainFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setVisible(true);
}
}
MainFrame Class that makes the frame.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@SuppressWarnings("serial")
public class MainFrame extends JFrame{
private StarGraphics frameStar;
private JButton starToggle;
public JSlider starSpeed;
public MainFrame() {
// Setting some properties of the frame
setTitle("Star Moving with Internal Events");
setLayout(new BorderLayout());
// Initializing the panel which has rotating star
frameStar = new StarPainter(this);
// Adding the bottom toggle button and slider
addToggler();
}
// Getter for the slider value
public int sliderSpeed() {
return starSpeed.getValue();
}
// Adds Button to change the direction of the star
private void addToggler() {
// Adding another jpanel which has layout set to null so i can add button of my size
JPanel panel = new JPanel();
panel.setLayout(null);
panel.setPreferredSize(new Dimension(20,80));
panel.setBackground(Color.WHITE);
// Initializing button and its action listener to change star direction
starToggle = new JButton("Toggle");
starToggle.setBounds(190, 0, 80, 20);
starToggle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == starToggle) {
frameStar.ChangeDirections();
}
}
});
// Adding button to panel
panel.add(starToggle);
// Adding slider to the panel
addSlider(panel);
// Adding panel to the main Panel at the bottom
add(panel, BorderLayout.SOUTH);
}
private void addSlider(JPanel panel) {
// Adding Slider and it's properties
starSpeed = new JSlider(JSlider.HORIZONTAL, 0, 20, 5);
starSpeed.setMajorTickSpacing(10);
starSpeed.setMinorTickSpacing(1);
starSpeed.setPaintTicks(true);
starSpeed.setPaintLabels(true);
starSpeed.setBounds(70,30,400, 45);
// Adding Slider-ChangeListener to change the rotation speed of the star
starSpeed.addChangeListener(new ChangeListener() { // anonymous inner class
// handle change in slider value
@Override
public void stateChanged(ChangeEvent e) {
frameStar.ChangeSpeed(starSpeed.getValue());
}
}
);
// Adding label besides the slider
JLabel label = new JLabel("Speed : ");
label.setBounds(10 , 10, 80, 80);
panel.add(label);
panel.add(starSpeed);
}
}
Class to create the panel that has star rotation
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
@SuppressWarnings("serial")
public class StarGraphics extends JPanel{
private boolean toggleDir = false;
private int speed = 10;
private Timer timer;
protected double angleOfStarRotation = 0;
public StarGraphics(JFrame frame) {
setPreferredSize(new Dimension(500, 470));
setBackground(Color.BLACK);
setLayout(new BorderLayout());
frame.add(this, BorderLayout.CENTER);
startTimer();
}
public void startTimer() {
timer = new Timer(speed, new ActionListener() {
public void actionPerformed(ActionEvent e){
// System.out.println(angleOfStarRotation);
if(!toggleDir) //rotates clockwise
angleOfStarRotation = angleOfStarRotation + 1;
else //rotates counterclockwise
angleOfStarRotation = angleOfStarRotation - 1;
// if (angleOfStarRotation == 360 || angleOfStarRotation == -360) // If there is a full circle, it will reset the angle to zero
// angleOfStarRotation = 0;
repaint();
}});
timer.start();
}
public void ChangeSpeed(int newSpeed) {
this.speed = newSpeed;
timer.setDelay(speed);
}
public void ChangeDirections() {toggleDir = !toggleDir; }
}
And a class that paints the star into the panel
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.security.SecureRandom;
import javax.swing.JFrame;
@SuppressWarnings("serial")
public class StarPainter extends StarGraphics{
private int[] starXPoints = {55, 67, 109, 73, 83, 55, 27, 37, 1, 43};
private int[] starYPoints = {0, 36, 36, 54, 96, 72, 96, 54, 36, 36};
GeneralPath starDesign = new GeneralPath();
public StarPainter(JFrame frame) {
super(frame);
}
public void drawStar(GeneralPath path) {
path.moveTo(starXPoints[0], starYPoints[0]);
for(int i=0; i<10; i++)
path.lineTo(starXPoints[i], starYPoints[i]);
path.closePath();
}
public void starActions(Graphics2D g) {
int startAngle = 360;
// For Random Color
SecureRandom random = new SecureRandom();
// rotate around origin and draw stars in random colors
for (int count = 1; count <= 1; count++)
{
double angle = startAngle - 90;
// rotate coordinate system
g.rotate(angleOfStarRotation * Math.PI / angle); //rotates as per the rotated angle //
// set random drawing color
g.setColor(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
// draw filled star
g.fill(starDesign);
// dispose the star
g.dispose();
}
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
drawStar(starDesign);
g2d.translate(250,150);
starActions(g2d);
}
}
After running the code, the output will show a frame with coloring star rotating around the panel in circular motion, but after 2 full rotation, the star rotation slow down automatically. Does anyone know why that happens?