Trouble translating a line (shape) - java

For an assignment we were asked to modify existing code to include more than one shape, more than one color, and to have the shapes move. I got a little carried away and started adding in more things but now we have an issue. All was going well until I added the left arm(as viewed on the screen). I am having a problem with a piece of the arm remaining in the previous place when moving the figure to the right. Up, down, and left are all working well, it is only to the right where I hit the problem. I have added a screenshot of what it looks like after I move the figures to the right two times. Thanks for any assistance you may be able to provide.
roboMan output
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.Color;
import java.awt.Polygon;
import java.util.Scanner;
import java.awt.geom.Ellipse2D;
public class SwingBot1 {
public static void main(String[] args) {
// contruction of new JFrame object
JFrame frame = new JFrame();
// mutators
frame.setSize(400,400);
frame.setTitle("SwingBot");
// program ends when window closes
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Robot r = new Robot();
frame.add(r);
// voila!
frame.setVisible(true);
// your Scanner-based command loop goes here
Scanner in = new Scanner(System.in);
boolean active = true;
while(active){
System.out.println("Enter \"up\", \"down\", \"left\", or \"right\" "
+ "to move.\nClose the window to quit.");
String direction = in.nextLine();
switch(direction){
case "up":
r.moveBot(0, -20);
break;
case "down":
r.moveBot(0, 20);
break;
case "right":
r.moveBot(20, 0);
break;
case "left":
r.moveBot(-20, 0);
break;
}
}
}
public static class Robot extends JComponent
{
private Rectangle rect = new Rectangle(45, 30, 20, 20);
int x = 30;
int y = 50;
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
// set the color
g2.setColor(Color.RED);
// draw the shape`
g2.fill(rect);
Graphics2D g3 = (Graphics2D) g;
g3.setColor(Color.BLUE);
g3.draw(new Ellipse2D.Double(30, 50, 50, 100));
g3.fillOval(30, 50, 50, 100);
Graphics2D g4 = (Graphics2D) g;
g4.setColor(Color.GREEN);
g4.draw(new Line2D.Double(70, 141, 90, 190));
g4.draw(new Line2D.Double(39, 141, 30, 191));
Graphics2D g5 = (Graphics2D) g;
g5.setColor(Color.RED);
g5.draw(new Line2D.Double(80, 85, 125, 70));
//arm, left as viewed
g5.draw(new Line2D.Double(0, 70, 30, 85));
}
public void moveBot(int x, int y)
{
setX(getX()+x);
setY(getY()+y);
repaint();
}
public int getX()
{
return x;
}
public void setX(int x)
{
this.x = x;
}
public int getY()
{
return y;
}
public void setY(int y)
{
this.y = y;
}
/* public void moveBot(int x, int y)
{
// move the rectangle
rect.translate(x,y);
// redraw the window
poly.translate(x, y);
repaint();
}*/
}
}

It looks like you need to repaint the frame.

Related

Drawing Lines to JLabel Icon in Java Swing

Hi Everyone I want to draw lines to Jlabel Icon with DrawLines() class but the program isn't drawing .When I use to frame.add(m) the program is drawing lines to frame .....
DrawLine m = new DrawLine();
frame.add(m);
but when I use to label.add(m) method .The program isn't working .I need to figure out this problem Why can't I draw lines to jlabelIcon and How can I fix this ?
This is my DrawLine Class
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Line2D;
public class DrawLine extends JComponent {
public void paint(Graphics g) {
super.paintComponents(g);
g.drawLine(300, 152, 63, 185);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
g.drawLine(63, 185, 120, 198);
}
}
This is my main class
package com.company;
import com.sun.source.tree.Tree;
import jdk.swing.interop.SwingInterOpUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.awt.geom.Line2D;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
public class Main extends JFrame {
public static void main(String[] args) {
JFrame frame = new JFrame("Display Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = (JPanel) frame.getContentPane();
frame.setSize(1000,560);
JLabel label = new JLabel();
label.setSize(1000,560);
label.setIcon(new ImageIcon("myimage path"));
DrawLine m = new DrawLine();
label.add(m);
panel.add(label);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
If your goal is to draw lines and images together, then your best bet for the money is to get rid of ImageIcon and JLabel and instead is to draw them all within a single paintComponent. The images can be drawn as image sprite, and the lines as lines by calling Graphics#drawLine(...) or as Line2D objects as you have using Graphics2D#draw(...)
For example, say we had two BufferedImage objects, upImg and dnImg, and two Point objects that determined the location of these sprites, upPt and dnPt
public class Foo01 extends JPanel {
// .....
private Point upPt = new Point(300, 100);
private Point dnPt = new Point(700, 650);
private BufferedImage upImg, dnImg;
And say we wanted to draw a line that connected the two image sprites, then these could all be draw within the paintComponent method like so:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // tell the JPanel to do its house-keeping painting
// make sure that neither image is null
if (upImg != null && dnImg != null) {
// draw both images at their respective locations
g.drawImage(upImg, upPt.x, upPt.y, this);
g.drawImage(dnImg, dnPt.x, dnPt.y, this);
// to get a smooth line, use rendering hiints
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// to give the line some thickness
g2.setStroke(new BasicStroke(5f));
// calculate the end-points of the line
int x1 = upPt.x + upImg.getWidth() / 2;
int y1 = upPt.y + upImg.getHeight() / 2;
int x2 = dnPt.x + dnImg.getWidth() / 2;
int y2 = dnPt.y + dnImg.getHeight() / 2;
// and then draw it
g.drawLine(x1, y1, x2, y2);
}
}
Here is an example program that does just this -- draws two images with a line connecting. I've also added a MouseAdapter to allow the user to move the first image, the green up-arrow, showing that the line will move as well, since it is calculated within the painting method:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.URL;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class Foo01 extends JPanel {
private static final String UP_IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/7/7d/Green_circle_icon.jpg";
private static final String DN_IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/b/bc/Red_circle_icon.jpg";
private static final int GUI_W = 1000;
private static final int GUI_H = 800;
private Point upPt = new Point(300, 100);
private Point dnPt = new Point(700, 650);
private BufferedImage upImg, dnImg;
public Foo01() {
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
setBackground(Color.WHITE);
try {
URL url = new URL(UP_IMG_PATH);
upImg = ImageIO.read(url);
url = new URL(DN_IMG_PATH);
dnImg = ImageIO.read(url);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(GUI_W, GUI_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (upImg != null && dnImg != null) {
g.drawImage(upImg, upPt.x, upPt.y, this);
g.drawImage(dnImg, dnPt.x, dnPt.y, this);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(5f));
int x1 = upPt.x + upImg.getWidth() / 2;
int y1 = upPt.y + upImg.getHeight() / 2;
int x2 = dnPt.x + dnImg.getWidth() / 2;
int y2 = dnPt.y + dnImg.getHeight() / 2;
g.drawLine(x1, y1, x2, y2);
}
}
private class MyMouse extends MouseAdapter {
private Point p1 = null;
#Override
public void mousePressed(MouseEvent e) {
if (e.getX() < upPt.x || e.getX() > upPt.x + upImg.getWidth()) {
return;
}
if (e.getY() < upPt.y || e.getY() > upPt.y + upImg.getHeight()) {
return;
}
p1 = new Point(e.getX(), e.getY());
}
#Override
public void mouseReleased(MouseEvent e) {
if (p1 != null) {
moveSprite(e);
p1 = null;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (p1 != null) {
moveSprite(e);
}
}
private void moveSprite(MouseEvent e) {
Point p2 = new Point(e.getX(), e.getY());
int x = upPt.x + p2.x - p1.x;
int y = upPt.y + p2.y - p1.y;
upPt = new Point(x, y);
p1 = p2;
repaint();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()-> {
Foo01 foo01 = new Foo01();
JFrame frame = new JFrame("Draw Sprites");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(foo01);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
If the need is to add custom painting to a JLabel you can override its paintComponent:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
public class Main extends JFrame {
private static final String BUG = "https://www.growtopiagame.com/forums/attachment.php?attachmentid=141847&d=1477126665";
public static void main(String[] args) throws MalformedURLException {
JFrame frame = new JFrame("Display Image");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DrawLine m = new DrawLine("A crossed bug", new ImageIcon(new URL(BUG)));
frame.add(m);
frame.pack();
frame.setVisible(true);
}
}
class DrawLine extends JLabel {
DrawLine(String text, Icon icon) {
super(text, icon, SwingConstants.CENTER);
setVerticalTextPosition(SwingConstants.BOTTOM);
setHorizontalTextPosition(SwingConstants.CENTER);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.YELLOW);
g2d.setStroke(new BasicStroke(10));
int w = getWidth(); int h = getHeight();
g2d.drawLine(0, 0, w, h); //draw right to left diagonal
g2d.drawLine(0, h, w, 0); //draw left to right diagonal
}
}
Swing is a single Thread library. All painting tasks are executed in the Event Dispatcher Thread (EDT).
Running long processes (such as sleep) on the EDT makes keeps this thread busy, so it does not do other things like updating the gui. The gui becomes unresponsive (freezes).
If you want to add a line after a certain delay, use swing Timer for the job:
public class Main extends JFrame {
private static final String BUG = "https://www.growtopiagame.com/forums/attachment.php?attachmentid=141847&d=1477126665";
public static void main(String[] args) throws MalformedURLException {
JFrame frame = new JFrame("Display Image");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DrawLine m = new DrawLine("A crossed bug", new ImageIcon(new URL(BUG)));
frame.add(m);
frame.pack();
frame.setVisible(true);
}
}
class DrawLine extends JLabel {
private static final int DELAY = 1500; //millies
private boolean isDrawSecondDialgonal = false;
DrawLine(String text, Icon icon) {
super(text, icon, SwingConstants.CENTER);
setVerticalTextPosition(SwingConstants.BOTTOM);
setHorizontalTextPosition(SwingConstants.CENTER);
//use timer to enable painting of a second diagonal
javax.swing.Timer timer = new javax.swing.Timer(DELAY, e-> {
isDrawSecondDialgonal = true;
repaint();
});
timer.setRepeats(false);
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.YELLOW);
g2d.setStroke(new BasicStroke(10));
int w = getWidth(); int h = getHeight();
g2d.drawLine(0, 0, w, h); //draw right to left diagonal
if(isDrawSecondDialgonal) {
g2d.drawLine(0, h, w, 0);//draw left to right diagonal
}
}
}

Color fading in java

I have finished working on a path finding visualizer recently. I was wondering if it was possible to use the graphics package for the colors to start off as white and then fade to their respective color like cyan or black. Right now I have it where the color just appears instantly and would think it would look nicer if the colors were able to fade from one another. Here is the code I have so far and a picture of the output
Path finding Visualizer
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int x = 0; x < cells; x++) { //coloring each node
for (int y = 0; y < cells; y++) {
switch (map[x][y].getType()) {
case 0: //start node
g.setColor(Color.GREEN);
break;
case 1: //end node
g.setColor(Color.RED);
break;
case 2: //wall node
g.setColor(Color.BLACK);
break;
case 3: //empty node
g.setColor(Color.WHITE);
break;
case 4: //visited nodes
g.setColor(Color.CYAN);
break;
case 5: //path
g.setColor(Color.YELLOW);
break;
}
g.fillRect(x * CSIZE, y * CSIZE, CSIZE, CSIZE);
g.setColor(Color.BLACK); //grid color
g.drawRect(x * CSIZE, y * CSIZE, CSIZE, CSIZE);
}
}
}
Here is one way. It uses a timer to periodically decrement the red component in the rgb color scheme.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ColorFadingDemo extends JPanel implements ActionListener {
Color color = new Color(255,0,0);
final static int height = 500;
final static int width = 500;
final static String title = "default title";
JFrame frame = new JFrame(title);
public static void main(String[] args) {
SwingUtilities.invokeLater(
() -> new ColorFadingDemo().start());
}
public void start() {
Timer timer = new Timer(0, this);
timer.setDelay(20);
timer.start();
}
public void actionPerformed(ActionEvent ae) {
int rgb = color.getRGB();
rgb -= 0x10000;
color = new Color(rgb);
repaint();
}
public ColorFadingDemo() {
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
frame.add(this);
setPreferredSize(
new Dimension(width, height));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(color);
g2d.fillRect(100,100,300,300);
g2d.dispose();
}
}
Easy:
int transparency = 0; // Transparency value;
int R = 255, G = 0, B = 0; //Enter your RGB values
Color c; // The color that you can then use in your paint method
Thread t = new Thread() {
public void run() {
while (transparency < 255) {
int transparency = 0;
c = new Color(R,G,B,transparency); // By creeting a custom color you can define the R, G, B and transparency values
transparency++;
try {
int fadeTime = 1000; // How long the fading process should go
Thread.sleep(255/fadeTime);
} catch (Exception e) {}
}
}
};
t.start(); // The thread will continue to run in the background until the transparency reaches 255

java graphics variables giving wrong value

Hello I wonder if anyone can help me , I have declared 2 values x1, y1 both as 120 and trying to use these in the following method:
private void drawDot(int x, int y, Graphics2D twoD) {
twoD.fillOval(x-50, y-50, 100, 100);
}
However when I use drawDot(120,120,twoD) it paints the filled oval in the wrong place compared to when I manually use
twoD.fillOval(70,70,100,100);
Shouldn't these 2 statements do the exact same thing? Is there something I am missing? I have added an image to show the issue, the oval on the left is the oval drawn by my drawDot method and the oval on the right is the oval in the correct place as it should be. If anyone has any advice it would be greatly appreciated. Thanks
click this link to see how both ovals are drawn
the entire class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DieFace extends JPanel {
int x1,y1 = 120;
int x2,y2 = 300;
int x3,y3 = 480;
private BufferedImage bufferedImage;
public DieFace() {
this.init();
this.frameInit();
updateVal(1);
}
private void init() {
this.setPreferredSize(new Dimension(600,600));
}
private void frameInit() {
JFrame window = new JFrame("Dice Simulation");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setContentPane(this);
window.pack();
window.setVisible(true);
window.setLocationRelativeTo(null);
}
public void paintComponent(Graphics g) {
Graphics2D twoD = (Graphics2D) g;
twoD.drawImage(bufferedImage,0,0,null);
}
private void drawDot(int x, int y, Graphics2D twoD) {
twoD.fillOval(x-50, y-50, 100, 100);
}
public void updateVal(int dieRoll) {
bufferedImage = new BufferedImage(600,600,BufferedImage.TYPE_INT_ARGB);
Graphics2D twoD = bufferedImage.createGraphics();
twoD.setColor(Color.WHITE);
twoD.fillRect(0, 0, 600, 600);
twoD.setColor(Color.BLACK);
if(dieRoll==1) {
drawDot(x1,y1,twoD);
twoD.fillOval(70, 70, 100, 100);
}
repaint();
}
}
Shouldn't these 2 statements do the exact same thing? Is there something I am missing?
Because you made a mistake in your variable initializations on x1, y1:
int x1,y1 = 120; //This means x1 = 0, y1 = 120
What you actually wanted is:
int x1 = 120, y1 = 120;
Since x1 is not 120, when you invoke
drawDot(x1,y1,twoD);
drawDot(0, 120, twoD); is being invoked
Hence both elipses will appear on the same y-axis, but different on the x-axis.

Gif image only moves when pressing buttons in java

The problem is that my gif called "grrass" in the program was supposed to move automatically, however it only moves when I press a button.
This is my main class which creates the Frame and things I need to create a window:
import java.awt.Graphics;
import java.awt.Image;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class mainCalss {
public static void main (String args[]) {
JFrame f = new JFrame();
second d = new second();
f.add(d);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1200 , 900);
}
}
This is my method class, which contains my gif image and my main running process:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.Random;
public class second extends JPanel implements ActionListener , KeyListener {
Image img = Toolkit.getDefaultToolkit().createImage("images/grrass.gif");
Timer t = new Timer(90, this);
int x = 0 , y = 0 , velx = 0 , vely = 0 ;
public second () {
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent (Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(img, 0,0, null);
g2.fill(new Ellipse2D.Double(100+x , 100+y, 30 , 30));
g2.drawRect(x+100, y+100, 30, 30);
g2.fillRect(x+115, y+112, 50 , 2);
g2.fillRect(x+115, y+118, 50 , 2);
g2.setColor(Color.yellow);
g2.fillOval(x-10, 10+y, 50, 50);
g2.fillRect(x-10, y+8, 70, 40);
g2.setColor(Color.black);
g2.drawRect(x-10, y+8, 70, 40);
g2.drawOval(x-10, 10+y, 50, 50);
g2.setColor(Color.yellow);
g2.fillOval(x, y, 200, 100);
g2.setColor(Color.black);
g2.drawOval(x, y, 200, 100);
g2.drawLine(x+0,y+50,x+200,y+50);
g2.drawOval(x, 20+y, 200, 60);
}
public void actionPerformed(ActionEvent e) {
if(x<0)
x+=35;
if(y<0)
y+=35;
if(x>1100)
x-=135;
if(y>650)
y-=30;
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN: y += 20; break;
case KeyEvent.VK_UP: y += -20; break;
case KeyEvent.VK_LEFT: x += -20; break;
case KeyEvent.VK_RIGHT: x += 20; break;
}
repaint();
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
}
}

Rotation with Graphics2D

I am currently experimenting with the Graphics2D and the KeyListener, and I am currently testing out rotating objects (in this case a pentagon). Now, it's working in the sense that it rotates, except it is supposed to rotate by 1 radian each time VK_RIGHT or VK_LEFT are pressed.
However, currently it does that for the first key press only. From then on, it creates a pattern of rotating it by 1, 2, 3, 4, 5... and so on radians each time (the nth keypress rotates it by nth radians) instead of just 1 radian per keypress.
Creating the JFrame:
import javax.swing.JFrame;
public class Main {
public Main() {
JFrame window = new JFrame("Rotating Hexagons");
window.setSize(800,600);
window.setLocationRelativeTo(null);
window.setResizable(false);
window.setContentPane(new RotatingHexagon());
window.pack();
window.setVisible(true);
}
public static void main(String[]args) {
new Main();
}
}
RotatingHexagon Class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class RotatingHexagon extends JPanel implements KeyListener {
private Polygon poly;
private int[] xpoints = { 0, -10, -7, 7, 10 };
private int[] ypoints = { -10, -2, 10, 10, -2 };
private int rotation = 0;
public RotatingHexagon() {
setPreferredSize(new Dimension(800,600));
setFocusable(true);
requestFocus();
}
public void init() {
poly = new Polygon(xpoints, ypoints, xpoints.length);
addKeyListener(this);
}
public void paint(Graphics g) {
init();
Graphics2D g2d = (Graphics2D) g;
int width = getSize().width;
int height = getSize().height;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, width, height);
g2d.setColor(Color.WHITE);
g2d.drawString(rotation + " radians", 10, 20);
g2d.translate(width / 2, height / 2);
g2d.scale(20, 20);
g2d.rotate(Math.toRadians(rotation));
g2d.setColor(new Color(255, 100, 100));
g2d.fill(poly);
g2d.setColor(Color.WHITE);
g2d.draw(poly);
}
public void keyPressed(KeyEvent k) {
switch(k.getKeyCode()) {
case KeyEvent.VK_LEFT:
rotation--;
if (rotation < 0) rotation = 359;
repaint();
break;
case KeyEvent.VK_RIGHT:
rotation++;
if (rotation > 360) rotation = 0;
repaint();
break;
}
}
public void keyReleased(KeyEvent k) {}
public void keyTyped(KeyEvent k) {}
}
I really don't have any idea why it isn't just rotating 1 radian each time, so any help is appreciated.
Thanks.
the reason is calling the init() function in the paint() method again and again. So the KeyListener is added multiple times, causing that it is called multiple times, incrementing your counter more every time you press the key.
Move it to the constructor:
public RotatingHexagon() {
setPreferredSize(new Dimension(800,600));
setFocusable(true);
requestFocus();
addKeyListener(this);
}
public void init() {
poly = new Polygon(xpoints, ypoints, xpoints.length);
}
Andy
You should probally just use a persistant AffineTransform to do the rotation. They are a lot more powerfull.
I also saw several issues in your code, you are calling the init method each frame - this could be 60 times per second. In this you are adding a new keylistener each frame. You are also creating a new polygon which would slow down performance.
I've made some changes to your code and and i've used AffineTransforms as an example. Have a look and see if this helps.
package com.joey.testing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class AffineTransformTest extends JPanel implements KeyListener {
private Polygon poly;
private int[] xpoints = { 0, -10, -7, 7, 10 };
private int[] ypoints = { -10, -2, 10, 10, -2 };
private int rotation = 0;
AffineTransform transform;
AffineTransform rotationTransform;
AffineTransform translateTransform;
public AffineTransformTest() {
setPreferredSize(new Dimension(800,600));
setFocusable(true);
requestFocus();
//Do Init here - no point in creating new polygon each frame.
//It also adds the key listener each time
init();
updateTransforms();
}
public void init() {
poly = new Polygon(xpoints, ypoints, xpoints.length);
transform = new AffineTransform();
rotationTransform = new AffineTransform();
translateTransform = new AffineTransform();
addKeyListener(this);
}
//Use Paint Compoent
#Override
public void paintComponent(Graphics g) {
//Always call super to clear the screen
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int width = getSize().width;
int height = getSize().height;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, width, height);
g2d.setColor(Color.WHITE);
g2d.drawString(rotation + " radians", 10, 20);
//Store old transform so we can apply it
AffineTransform old = g2d.getTransform();
//Add Transform and move polygon
g2d.setTransform(transform);
g2d.setColor(new Color(255, 100, 100));
g2d.fill(poly);
g2d.setColor(Color.WHITE);
g2d.draw(poly);
g2d.setTransform(old);
}
public void keyPressed(KeyEvent k) {
switch(k.getKeyCode()) {
case KeyEvent.VK_LEFT:
rotation--;
if (rotation < 0) rotation = 359;
repaint();
break;
case KeyEvent.VK_RIGHT:
rotation++;
if (rotation > 360) rotation = 0;
repaint();
break;
}
updateTransforms();
}
public void updateTransforms(){
//Resets transform to rotation
rotationTransform.setToRotation(Math.toRadians(rotation));
translateTransform.setToTranslation(getWidth()/2, getHeight()/2);
//Chain the transforms (Note order matters)
transform.setToIdentity();
transform.concatenate(translateTransform);
transform.concatenate(rotationTransform);
}
public void keyReleased(KeyEvent k) {}
public void keyTyped(KeyEvent k) {}
public static void main(String input[]){
JFrame f= new JFrame("AffineTransform");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(100, 100);
f.setResizable(true);
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(new AffineTransformTest());
f.show();
}
}

Categories

Resources