Alright guys i'm trying to make an Asteroids type game and I need to be able to rotate an image around so that the front of the ship follows my mouse. I have looked for a few hours now and have found a couple of things but none that satisfy my needs.
If anyone knows how to do this please share!
thanks in advance
here is the code i have now
package Asteroids;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class Asteroids extends JFrame implements Runnable, MouseListener,
MouseMotionListener, KeyListener {
private Image dbImage;
private Graphics dbg;
int x, y, mx, my;
int a, b, c, degree;
double scale = 1.0;
ImageIcon shipIcon = new ImageIcon(this.getClass().getClassLoader()
.getResource("AstroidsShip.png"));
Image ship = shipIcon.getImage();
public static void main(String[] args) {
Asteroids frame = new Asteroids();
Thread thread = new Thread(frame);
thread.start();
}
public Asteroids() {
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
setTitle("Astroids");
setSize(500, 500);
setBackground(Color.WHITE);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
x = getWidth() / 2 - 10;
y = getHeight() - getHeight() / 2;
}
public void run() {
while (true) {
try {
} catch (Exception e) {
}
}
}
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent(Graphics g) {
g.drawString("POS: " + mx + ", " + my, 10, 40);
System.out.println(getAngle());
g.drawImage(ship, x, y, this);
g.drawLine(x + 12, y + 10, mx, my);
repaint();
}
public int getAngle() {
a = mx - (x + 12);
b = (y - 10) - my;
return degree = (int) Math.toDegrees(Math.atan2(b, a));
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
mx = e.getX();
my = e.getY();
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
You can use Java2D. It allows to rotate the image and do a lot lot of other cool operations on the image. It also have got hardware acceleration support (through DirectX or OpenGL).
Java2D is built-in in JRE.
Inside your paintComponent method, you could make the code look like:
public void paintComponent(Graphics g) {
g.drawString("POS: " + mx + ", " + my, 10, 40);
System.out.println(getAngle());
Graphics2D g2d = new (Graphics2D)g;
g2d.translate(X, Y);
g2d.rotate(DEGREES);
g2d.drawImage(ship, 0, 0, WIDTH, HEIGHT, this);
g.drawLine(x + 12, y + 10, mx, my);
repaint();
}
For more complex use, you could create a method with all of your ship drawing calculations:
public void paintComponent(Graphics g) {
g.drawString("POS: " + mx + ", " + my, 10, 40);
System.out.println(getAngle());
drawShip(g);
g.drawLine(x + 12, y + 10, mx, my);
repaint();
}
public void drawShip(Graphics g){
Graphics2D g2d = (Graphics2D)g;
g2d.translate(X, Y);
g2d.rotate(DEGREES);
g2d.drawImage(ship, 0, 0, WIDTH, HEIGHT, this);
}
One way is to use a rotate instance from one of the methods of AffineTransform that accepts anchors for the X,Y co-ordinates.
Related
It always works with images but rectangles and ovals never buffer right. I have a basic game loop in my gamepanel class that draws the player repeatedly. It doesn't remove the rectangle, just leaves a trace. I want to use a rectangle instead of an image for learning purposes. I tried using repaint in the game loop, but it flickered like crazy and still didn't work. I looked at another tutorial on this in this website but they used opengl witch is foreign to me and I don't want to take the time to figure it out.
JFrame:
import javax.swing.JFrame;
public class Game {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setTitle("OMG I MADE A GAME");
f.setResizable(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(new Panel());
f.pack();
f.setVisible(true);
}
}
JPanel Class:
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import javax.swing.JPanel;
import com.game.entity.Player;
public class Panel extends JPanel implements Runnable, KeyListener{
private static final long serialVersionUID = -5122190028751177848L;
// dimensions
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 2;
// game thread
private Thread thread;
private boolean running;
// image
private BufferedImage image;
private Graphics2D g;
private Player p;
public Panel() {
super();
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setFocusable(true);
requestFocus();
}
// DRAWS PANEL TO FRAME
public void addNotify() {
super.addNotify();
if(thread == null) {
thread = new Thread(this);
addKeyListener(this);
thread.start();
}
}
private void init() {
image = new BufferedImage(
WIDTH, HEIGHT,
BufferedImage.TYPE_INT_RGB );
g = (Graphics2D) image.getGraphics();
p = new Player(100, 100);
running = true;
}
public void run() {
init();
// game loop
while(running) {
update();
draw();
drawToScreen();
System.out.println("ELAPSED :" + System.nanoTime()/ 1000000 + " Seconds");
try {
Thread.sleep(10);
}
catch(Exception e) {
e.printStackTrace();
}
}
}
private void update() {
p.update();
}
private void draw(){
// NAME (remember it loops)
String name = "2014 Jay H.";
g.setFont(new Font("Name", 0, 12));
g.setColor(Color.WHITE);
g.drawString(name, 0, 10);
g.setColor(Color.BLUE);
g.fillRect( 0, 10, 65, 5);
//TITLE looks sexy :D
g.setColor(Color.GREEN);
g.setFont(new Font("Title", 0, WIDTH/ 10));
g.drawString("JAY'S GAME", WIDTH/ 5, 100);
//DRAW PLAYER
p.draw(g);
}
// SCREEN IMAGE (dont have to use. Just use this^)
private void drawToScreen() {
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0,
WIDTH * SCALE, HEIGHT * SCALE,null);
g2.dispose();
}
public void keyTyped(KeyEvent key) {}
// PUBLIC KEYRELEASES
public void keyPressed(KeyEvent key) {
int KeyCode = key.getKeyCode();
//EXIT SYSTEM
if(KeyCode == KeyEvent.VK_Q) {System.exit(0);
} //UP
if(KeyCode == KeyEvent.VK_W){p.setDY(-2);}
}
// PUBLIC KEYRELEASES
public void keyReleased(KeyEvent key) {
int KeyCode = key.getKeyCode();
//UP
if(KeyCode == KeyEvent.VK_W) {p.setDY(0);}
}
}
Player Class:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
//FOR NOW THE PLAYER IS A RECTANGLE
public class Player {
// PLAYER CORDINATES AND VELOCITY
int x,y,dx,dy;
public Player(int x, int y) {
//NEEDED TO USE THE X AND Y
this.x =x;
this.y = y;
}
public void update() {
x += dx;
y += dy;
}
// DRAW TO PANEL CLASS
public void draw(Graphics2D g) {
//BODY
g.setColor(Color.PINK);
g.fillRect(x, y, 20, 20);
//EYES
g.setColor(Color.BLACK);
g.fillRect(x+3, y+2, 5, 10);
g.fillRect(x+ 12, y+2, 5, 10);
//EYERIS
g.setColor(Color.WHITE);
g.fillRect(x+3, y+2, 2, 10);
g.fillRect(x+15, y+2, 2, 10);
//NOSE
g.setColor(Color.MAGENTA);
g.fillRect(x+5, y+13, 10, 5);
//NOSTRILLS
g.setColor(Color.red);
g.fillRect(x+6, y+15, 2, 2);
g.fillRect(x+12, y+15, 2, 2);
}
//GET METHODS FOR CORDINATES AND VELOCITY (Unused for now... i think)
public int getX() {return x;}
public int getY() {return y;}
public int getDX() {return dx;}
public int getDY() {return dy;}
//SET METHODS TO CHANGE
public void setX(int x) {this.x = x;}
public void setY(int y) {this.y = y;}
public void setDX(int dx) {this.dx = dx;}
public void setDY(int dy) {this.dy = dy;}
}
You need to "reset" the background of the buffer before you paint to it.
Remember, painting is accumilitive, that is, what ever you painted previously, will remain. You will need to rebuild each frame from scratch each time you paint to it
Flickering will occur for two reasons...
You are using AWT based components, which aren't double buffered
You are overriding paint of a top level container like JFrame, which isn't double buffered.
You should either use a BufferStrategy or override the paintComponent method of a Swing based component, like JPanel which are double buffered by default
I am trying to add a MouseListener to my custom JComponent. I just want the MouseListener to be triggered when pressing withing the bounds of the circle (the JComponent's painting method draws a circle). I have tried with the below code but I just cannot get it to work (loook especially in the mousePressed method). How can I tackle this problem?
The SSCCE:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class AffineTransformTest {
private static TransformingCanvas canvas;
public static void main(String[] args) {
JFrame frame = new JFrame();
canvas = new AffineTransformTest.TransformingCanvas();
TranslateHandler translater = new TranslateHandler();
canvas.addMouseListener(translater);
canvas.addMouseMotionListener(translater);
canvas.addMouseWheelListener(new ScaleHandler());
frame.setLayout(new BorderLayout());
frame.getContentPane().add(canvas, BorderLayout.CENTER);
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
private static class TransformingCanvas extends JComponent {
private double translateX;
private double translateY;
private double scale;
TransformingCanvas() {
translateX = 0;
translateY = 0;
scale = 1;
setOpaque(true);
setDoubleBuffered(true);
}
#Override
public void paint(Graphics g) {
AffineTransform tx = new AffineTransform();
tx.translate(translateX, translateY);
tx.scale(scale, scale);
Graphics2D ourGraphics = (Graphics2D) g;
ourGraphics.setColor(Color.WHITE);
ourGraphics.fillRect(0, 0, getWidth(), getHeight());
ourGraphics.setTransform(tx);
ourGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
ourGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
ourGraphics.setColor(Color.BLACK);
ourGraphics.fillOval(50, 50, 50, 50);
}
}
private static class TranslateHandler implements MouseListener,
MouseMotionListener {
private int lastOffsetX;
private int lastOffsetY;
public void mousePressed(MouseEvent e) {
lastOffsetX = e.getX();
lastOffsetY = e.getY();
double width = canvas.scale * 50;
double height = canvas.scale * 50;
double x = (AffineTransformTest.canvas.getWidth() - width) / 2;
double y = (AffineTransformTest.canvas.getHeight() - height) / 2;
Rectangle2D.Double bounds = new Rectangle2D.Double(x, y, width, height);
System.out.println(bounds + " " + e.getPoint());
if (bounds.contains(e.getPoint())) {
System.out.println("Click!");
}
}
public void mouseDragged(MouseEvent e) {
int newX = e.getX() - lastOffsetX;
int newY = e.getY() - lastOffsetY;
lastOffsetX += newX;
lastOffsetY += newY;
canvas.translateX += newX;
canvas.translateY += newY;
canvas.repaint();
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}
private static class ScaleHandler implements MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
canvas.scale += (.1 * e.getWheelRotation());
canvas.scale = Math.max(0.00001, canvas.scale);
canvas.repaint();
}
}
}
}
Here is the code. Some quick notes, there is still some debug in the code, and replace calls to LOGGER object with System.out.println().
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.event.MouseInputListener;
public abstract class LCARSComponent extends JComponent implements MouseInputListener {
/**
* A reference to the global Logger object.
*/
protected final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
protected int x;
protected int y;
protected int w;
protected int h;
protected double scaleFactor = 1.0;
protected Area area;
protected Area scaledArea;
protected int style;
protected Color color;
protected AffineTransform renderingTransform;
protected ActionListener actionListener;
public LCARSComponent(Container parent, int x, int y, int w, int h, int style) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.style = style;
setBounds(x,y,w,h);
addMouseListener(this);
}
#Override
protected void paintComponent(Graphics g) {
/**
* First, paint the background if the component is opaque. Required when
* JComponent is extended, and the paintCompnent() method is overridden.
*/
if(isOpaque()) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
/**
* Create a Graphics2D object so we can use Java 2D features.
*/
Graphics2D g2d = (Graphics2D) g.create();
/**
* Set the anti aliasing rendering hint and the color to draw with.
*/
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(color);
scaleComponent();
/**
* Draw the Area object of the LCARS component, and fill it.
*/
g2d.draw(scaledArea);
g2d.fill(scaledArea);
g2d.drawRect(scaledArea.getBounds().x, scaledArea.getBounds().y, scaledArea.getBounds().width, scaledArea.getBounds().height);
/**
* Clean up when the method has completed by disposing the Graphics2D object that was created.
*/
g2d.dispose();
}
protected void scaleComponent() {
double sw = (double)getParent().getWidth() / (double)getParent().getPreferredSize().width;
double sh = (double)getParent().getHeight() / (double)getParent().getPreferredSize().height;
LOGGER.info("scaledWidth = " + sw);
LOGGER.info("scaledHeight = " + sh);
double scaleFactor;
if(sh < sw) {
scaleFactor = sh;
}
else {
scaleFactor = sw;
}
LOGGER.info("scaleFactor = " + scaleFactor);
if(scaleFactor != this.scaleFactor) {
this.scaleFactor = scaleFactor;
scaledArea = new Area(area);
renderingTransform = new AffineTransform();
renderingTransform.scale(scaleFactor, scaleFactor);
scaledArea.transform(renderingTransform);
}
setBounds((int)(this.x*scaleFactor), (int)(this.y*scaleFactor), this.getWidth(), this.getHeight());
}
public Point screenToComponent(Point pt) {
if(renderingTransform == null) {
Graphics2D g2d = (Graphics2D)(this.getParent().getGraphics());
renderingTransform = g2d.getTransform();
}
Point2D pt2d = renderingTransform.transform(pt,null);
LOGGER.info("mouse click: " + pt.getX() + ", " + pt.getY() + " -- " + pt2d.getX() + ", " + pt2d.getY());
return new Point((int)Math.round(pt2d.getX()), (int)Math.round(pt2d.getY()));
}
public void setActionListener(ActionListener actionListener) {
this.actionListener = actionListener;
}
#Override
public void mouseClicked(MouseEvent e) {
Point pt = e.getPoint();
LOGGER.info("mouseClicked: " + this.getName() + " - " + pt.getX() + ", " + pt.getY());
if(area.contains(e.getPoint())) {
if(actionListener != null) {
actionListener.actionPerformed(new ActionEvent(e.getSource(), e.getID(), e.paramString()));
}
if(color.equals(Color.black))
color = Color.blue;
else
color = Color.black;
this.repaint();
}
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
if(area.contains(e.getLocationOnScreen()))
System.out.println("mousePressed()...");
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
if(area.contains(e.getLocationOnScreen()))
System.out.println("mouseReleased()...");
}
#Override
public void mouseEntered(MouseEvent e) {
Point pt = e.getPoint();
// TODO Auto-generated method stub
System.out.println("mouseEntered()...");
LOGGER.info("mouseEntered: " + this.getName() + " - " + pt.getX() + ", " + pt.getY());
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
Point pt = e.getPoint();
System.out.println("mouseExited()...");
LOGGER.info("mouseExited: " + pt.getX() + ", " + pt.getY());
}
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("mouseDragged()...");
}
#Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("mouseMoved()...");
}
}
Two points:
First, I would use a Shape or Area object and use its .contains() method. Bounds is always a Rectangle that surrounds your entire shape. Also, not sure why you are creating a bounds rectangle when you can simply use the setBounds() method of your JComponent.
Second, the bounds of a JComponent can be translated, but I haven't found anything built-in to scale them. Though, you can change the size dynamically. I am working on an identical problem. Right now I am considering dynamically changing the bounds when my JComponent scales. I am trying to understand correlation between screen coordinates and JComponent coordinates. The mouse coordinates always seem to be in unscaled frame/screen coordinates (might be an artifact of the full screen mode I am using. The solutions I have seen paint everything in a JPanel and do not use discrete JComponents to solve the scaling problem. The code is a little hard to follow, and not particularly modular, but it does work.
In any case, I am sure it can ultimately be done. It is simply a matter of getting the math right. I will post the code for the scalable JComponent extension when I have finished it and it works reliably. Hope this helps a little.
Okay, I give up. I've been a C++ programmer for a few years, but I tried learning Java because it's a popular language. As I studied I learn a lot, but eventually I started playing around and tried using the input system so that when I click this red diamond shape polygon it turns green, but after several frustrating days... nada. I still only have a red diamond. It's probably something very small but I just can't find it
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Vici extends Applet
{
/**
*
*/
private static final long serialVersionUID = 1L;
private Space castle;
public Vici()
{
castle = new Space();
castle.addMouseListener(new SpaceInput());
}
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D)g;
int width = getSize().width;
int height = getSize().height;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, width, height);
castle.paint(g2d);
}
class SpaceInput implements MouseListener
{
public void mouseEntered(MouseEvent m) { }
public void mouseExited(MouseEvent m) { }
public void mouseReleased(MouseEvent m)
{
switch(m.getButton())
{
case MouseEvent.BUTTON1:
castle.setColor(Color.GREEN);
castle.repaint();
repaint();
}
}
public void mouseClicked(MouseEvent m)
{
switch(m.getButton())
{
case MouseEvent.BUTTON1:
castle.setColor(Color.GREEN);
castle.repaint();
repaint();
}
}
public void mousePressed(MouseEvent m)
{
switch(m.getButton())
{
case MouseEvent.BUTTON1:
castle.setColor(Color.GREEN);
castle.repaint();
repaint();
}
}
}
}
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class Space extends Canvas
{
private Polygon poly;
private Color c;
private int[] polyX = { 0, 24, 0, -24 };
private int[] polyY = { 24, 0, -24, 0 };
public void init()
{
poly = new Polygon( polyX, polyY, polyX.length);
c = Color.red;
}
Space()
{
init();
}
void setColor(Color c)
{
this.c = c;
}
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D)g;
AffineTransform identity = new AffineTransform();
g2d.setTransform(identity);
g2d.translate(100, 100);
g2d.setColor(c);
g2d.fill(poly);
}
public void update( Graphics g )
{
paint( g );
}
}
I got rid of the extraneous "SpaceInput" class and added the mouse listener to the applet (not "castle"). And everything worked :)
public class Vici extends Applet implements MouseListener
{
private static final long serialVersionUID = 1L;
private Space castle;
public Vici()
{
castle = new Space();
// castle.addMouseListener(this);
addMouseListener (this);
}
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D)g;
int width = getSize().width;
int height = getSize().height;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, width, height);
castle.paint(g2d);
}
public void mouseEntered(MouseEvent m) {
System.out.println ("mouse entered...");
}
public void mouseExited(MouseEvent m) {
System.out.println ("mouse mouseExited...");
}
public void mouseReleased(MouseEvent m)
{
System.out.println ("mouse mouseReleased...");
switch(m.getButton())
{
case MouseEvent.BUTTON1:
castle.setColor(Color.GREEN);
castle.repaint();
repaint();
}
}
public void mouseClicked(MouseEvent m)
{
System.out.println ("mouse mouseClicked...");
switch(m.getButton())
{
case MouseEvent.BUTTON1:
castle.setColor(Color.GREEN);
castle.repaint();
repaint();
}
}
public void mousePressed(MouseEvent m)
{
System.out.println ("mouse mousePressed...");
switch(m.getButton())
{
case MouseEvent.BUTTON1:
castle.setColor(Color.GREEN);
castle.repaint();
repaint();
}
}
}
#Chaz Bertino -
I think the entire problem was using "Canvas" (obsolete since Java 1.2) vs "JPanel" (replaces the old "Panel" and "Canvas" combined since J2SE 2.0).
Here's another example that behaves like you expected. The main differences is that it uses a Swing JPanel instead of an AWT Canvas:
import java.applet.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class HelloAWT extends Applet {
private Diamond diamond;
private static final int height = 350;
private static final int width = 350;
public void init () {
setBackground(Color.green);
resize (width, height);
diamond = new Diamond ();
diamond.init (Color.green);
add(diamond);
}
public void paint(Graphics g)
{
System.out.println ("HelloAWT#paint()...");
String msg = "Hello AWT!";
g.setFont(new Font ("Arial", Font.BOLD, 18));
FontMetrics fm = g.getFontMetrics ();
int x = (getWidth() - fm.stringWidth(msg)) / 2;
int y = (getHeight() / 2) + 50;
g.drawString(msg, x, y);
diamond.repaint ();
}
}
class Diamond extends JPanel implements MouseListener {
private static final int height = 100;
private static final int width = 100;
private Color c = Color.red;
private Color bkgd;
private int[] polyX;
private int[] polyY;
private Polygon poly;
public void init (Color bkgd) {
System.out.println ("Diamond#init(): bkgd=" + bkgd + "...");
setPreferredSize (new Dimension(width, height));
this.bkgd = bkgd;
polyX = new int[] { width/2, width, width/2, 0 };
polyY= new int[] { 0, height/2, height, height/2 };
System.out.println ("polyX=" + polyX[0] + "," + polyX[1] + "," + polyX[2] + "," + polyX[3] + "...");
System.out.println ("polyY=" + polyY[0] + "," + polyY[1] + "," + polyY[2] + "," + polyY[3] + "...");
poly = new Polygon( polyX, polyY, polyX.length);
addMouseListener (this);
}
public void paint(Graphics g)
{
System.out.println ("Diamond()#paint(), bounds=" + getHeight() + "," + getWidth () + "...");
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(bkgd);
g2d.fillRect(0, 0, width, height);
g2d.setColor(c);
g2d.fill(poly);
}
public void mouseEntered(MouseEvent m) {
System.out.println ("mouseEntered()...");
}
public void mouseExited(MouseEvent m) {
System.out.println ("mouseExited()...");
}
public void mouseReleased(MouseEvent m) {
System.out.println ("mouseReleased()...");
}
public void mouseClicked(MouseEvent m) {
System.out.println ("mouseClicked(), current color=" + c + "...");
if (c == Color.red)
c = Color.blue;
else
c = Color.red;
repaint ();
}
public void mousePressed(MouseEvent m) {
System.out.println ("mousePressed()...");
}
}
I am having issues with my Applet not painting the required graphics.
For some reason, it updates the coloring in the graphics, as you can see this when it prints, it recognizes the mouse is being moved, the graphics are not null, but it still refuses to paint.
How can this be fixed?
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JApplet;
public class GameApplet extends JApplet implements MouseListener, MouseMotionListener{
/**
*
*/
private static final long serialVersionUID = -6796451079056583597L;
Graphics2D g;
Image image;
Point p = new Point(-100, -100);
public void init(){
init(1000, 900);
}
public void init(int x, int y){
setSize(x, y);
image = createImage(x, y);
g = (Graphics2D) image.getGraphics();
//if(Graphic.setGraphic(image.getGraphics())){
if(g != null)
System.out.println("Graphics made");
//}
g.setColor(Color.GREEN);
g.fillRect(0, 0, x, y);
System.out.println(g+", "+ (g != null));
addMouseListener(this);
addMouseMotionListener(this);
//Graphic.paint();
setVisible(true);
}
#Override
public void paint(Graphics g){
g.setColor(Color.red);
g.fillRect(0, 0, 500, 500);
}
public void update(Graphics g){
paint(g);
}
#Override
public Graphics getGraphics(){
return g;
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e);
}
#Override
public void mousePressed(MouseEvent e) {
p = e.getPoint();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
showStatus(e.toString());
g.fillOval(e.getPoint().x - 5, e.getPoint().y - 5, 10, 10);
p = e.getPoint();
repaint();
}
}
As per my recommendations, do all drawing in a JPanel or JComponent's paintComponent method. Get the image's Graphics object only when you need it and dispose of it when you're done with it. For example:
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
#SuppressWarnings("serial")
public class GameApplet2 extends JApplet {
protected static final int APP_WIDTH = 1000;
protected static final int APP_HEIGHT = 900;
#Override
public void init() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
GameAppletPanel panel = new GameAppletPanel(GameApplet2.this);
getContentPane().add(panel);
panel.init(APP_WIDTH, APP_HEIGHT);
setSize(APP_WIDTH, APP_HEIGHT);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
#SuppressWarnings("serial")
class GameAppletPanel extends JPanel {
Image image;
Point p = new Point(-100, -100);
private JApplet applet;
public GameAppletPanel(JApplet applet) {
this.applet = applet;
}
public void init() {
init(1000, 900);
}
public void init(int x, int y) {
setSize(x, y);
image = createImage(x, y);
Graphics2D g = (Graphics2D) image.getGraphics();
g.setColor(Color.GREEN);
g.fillRect(0, 0, x, y);
g.dispose();
System.out.println(g + ", " + (g != null));
MyMouseAdapter mmAdapter = new MyMouseAdapter();
addMouseListener(mmAdapter);
addMouseMotionListener(mmAdapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
g.setColor(Color.red);
g.fillRect(0, 0, 500, 500);
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e);
}
#Override
public void mousePressed(MouseEvent e) {
p = e.getPoint();
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
applet.showStatus(e.toString());
Graphics2D g2 = (Graphics2D) image.getGraphics();
g2.fillOval(e.getPoint().x - 5, e.getPoint().y - 5, 10, 10);
p = e.getPoint();
g2.dispose();
repaint();
}
}
}
The "don't paint in top-level containers" still needs attending to, but it was not the immediate source(s) of the problem. Try this simpler code.
// <applet code='GameApplet' width=400 height=200></applet>
import java.awt.*;
import java.awt.event.*;
import javax.swing.JApplet;
public class GameApplet extends JApplet
implements MouseListener, MouseMotionListener{
Point p = new Point(-100, -100);
public void init(){
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public void paint(Graphics g){
g.setColor(Color.red);
g.fillRect(0, 0, 500, 500);
g.setColor(Color.blue);
g.fillOval(p.x - 5, p.y - 5, 10, 10);
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e);
}
#Override
public void mousePressed(MouseEvent e) {
p = e.getPoint();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseDragged(MouseEvent e) {}
#Override
public void mouseMoved(MouseEvent e) {
showStatus(e.toString());
p = e.getPoint();
repaint();
}
}
I'm trying to display mouse coordinates (math coordinates) in my JPanel , but i get each coordinates on top of the other ,can' figure out why .
here's my code :
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.applet.*;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;
public class drawarea extends JPanel {
int n;
private Point mouseCoords = null;
int UNIT = 20;
drawarea() {
super();
setBackground(Color.white);
addMouseMotionListener(new MouseInputAdapter() {
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
mouseCoords = new Point(e.getX(), e.getY());
repaint();
}
/**
* #see java.awt.event.MouseListener#mouseExited(MouseEvent)
*/
public void mouseExited(MouseEvent e) {
super.mouseExited(e);
mouseCoords = null;
repaint();
}
});
setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
}
public void paint(Graphics g) {
//draw axis x and y
g.setColor(Color.red);
g.drawLine(0, r.height / 2, r.width, r.height / 2);
g.drawLine(r.width / 2, 0, r.width / 2, r.height);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
dessinBoule(g2);
}
private void dessinBoule(Graphics2D g) {
// if mouse isnt inside the ara where
// i want the coordinates to bes displayed
if (mouseCoords == null) {
return;
}
g.setColor(Color.BLACK);
int decPolice = 15;
g.drawString("x = " + getFormatedString("" + mouseCoords.x)
+ " , y = " + getFormatedString("" + mouseCoords.y), 2, 15);
}
private String getFormatedString(String s) {
if (s.length() > 4) {
return s.substring(0, 3);
}
return s;
}
}
thanks.
You're drawing on your graphics area, so g.drawString(...) draws a string on top of what is already there. You must either erase what is there first, by drawing a rectangle in the background colour, or use a separate component that you can manage with a separate paint(...) method.
An example of #richj's suggestion is shown below. Note that in Swing you should override paintComponent(). Also, the implementation of MouseInputAdapter is empty, so you don't need to invoke super().
import java.awt.*;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
public class DrawArea extends JPanel {
private Point mouseCoords = new Point();
DrawArea() {
super();
this.setPreferredSize(new Dimension(320, 240));
setBackground(Color.white);
addMouseMotionListener(new MouseInputAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
mouseCoords = e.getPoint();
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
mouseCoords = null;
repaint();
}
});
setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.clearRect(0, 0, getWidth(), getHeight());
g2.setColor(Color.red);
if (!(mouseCoords == null)) {
g2.drawString(mouseCoords.toString(), 10, getHeight() - 10);
}
}
private static void create() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new DrawArea());
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
create();
}
});
}
}