I want to make an image that I drew in the paint class move left across my JFrame as a timer ticks. But I don't know how to do that. Also, I am trying to get my program to make the image disappear when the image is clicked upon.
movingball class
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class movingball extends JPanel{
private int move=50;
private Timer timer = new Timer(move, new TimerListener());
private int radius = 10;
private int x = 300;
private int y = 0;
public movingball() {
timer.start();
}
private class TimerListener implements ActionListener{
public void actionPerformed(ActionEvent e){
x=x-20;
repaint(); }//trying to get the oval to move left 20
}
protected void paintComponent(Graphics2D g){
super.paintComponent(g);
g.fillOval(x, 100 , radius * 2, radius * 2); }
}
movingControl class
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
public class movingControl extends JPanel {
private movingball ball= new movingball();
public movingControl(){
JPanel panel = new JPanel();
ball.setBorder(new javax.swing.border.LineBorder(Color.red));
panel.addMouseListener(new movingballListener());
setLayout(new BorderLayout());
add(ball, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
}
}
SnniperGameApp class
I know I spelled sniper wrong
import javax.swing.JApplet;
public class SnniperGameApp extends JApplet {
static final long serialVersionUID = 2777718668465204446L;
//i dont know what this serial thing is. But my program wont start without it
public SnniperGameApp(){
add(new movingControl());
}
}
ClickingEvent class
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
class movingballListener extends MouseAdapter{
public void mouseReleased(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON1_DOWN_MASK) != 0) {
System.out.println( (e.getPoint()));}}
}
You haven't over-ridden paintComponent() properly.
From the javadoc, the signature of paintComponent() is:
protected void paintComponent(Graphics g)
but you have:
protected void paintComponent(Graphics2D g)
The method signatures must match - you can safely cast the Graphics to a Graphics2D inside the method if needed.
Adding the #Override annotation to a method is a good way to get the compiler to check that you really are over-riding a method, not just writing a method that looks the same!
Here's a working SSCCE (I have inlined some of the constants to save space, don't take that as good practice for real code!):
public class MovingBall extends JPanel
{
private Timer timer = new Timer(50, new TimerListener());
private int x = 300;
public MovingBall()
{
timer.start();
}
private class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
x -= 20;
repaint();
}
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillOval(x, 100, 20, 20);
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.add(new MovingBall());
frame.setSize(500, 500);
frame.setVisible(true);
}
}
Related
This is a word-for-word example straight out of the book Java How to Program by Paul and Harvey Deitel.
PaintPanel.java
// Using class MouseMotionAdapter
import java.awt.Point;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JPanel;
public class PaintPanel extends JPanel {
private int pointCount = 0;
// array of 10,000 java.awt.Point references
private Point[] points = new Point[10000];
// set up gui and register mouse event handler
public PaintPanel() {
addMouseMotionListener(new MouseMotionAdapter() {
// store drag coordinates and repaint
public void MouseDragged(MouseEvent e) {
if (pointCount < points.length) {
points[pointCount] = e.getPoint();
pointCount++;
repaint();
} // end if
}
}
);
}
// draw ovals in a 4 x 4 bounding box at specified location on the window
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // clear drawing area
g.setColor(Color.BLUE);
// draw all points in the array
for(int i = 0; i < pointCount; i++)
g.fillOval(points[i].x, points[i].y, 4, 4);
}
}
Driver program Painter.java
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Painter {
public static void main(String[] args) {
JFrame app = new JFrame("A Simple Paint Program");
PaintPanel pp = new PaintPanel();
app.add(pp, BorderLayout.CENTER);
app.add(new JLabel("Drag the rat to draw"), BorderLayout.SOUTH);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(400, 200);
app.setVisible(true);
}
}
When I run it, it shows the drawing panel but nothing happens when I try to draw on it with the mouse. All code is copied verbatim from the book. What gives?
Java is case sensitive. It's mouseDragged, not MouseDragged. This is why you should always use #Override on methods you "think" you're overriding, this way you get compile time protection.
Runnable example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new PaintPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPanel extends JPanel {
private int pointCount = 0;
// array of 10,000 java.awt.Point references
private Point[] points = new Point[10000];
// set up gui and register mouse event handler
public PaintPanel() {
addMouseMotionListener(new MouseMotionAdapter() {
// store drag coordinates and repaint
#Override
public void mouseDragged(MouseEvent e) {
if (pointCount < points.length) {
points[pointCount] = e.getPoint();
pointCount++;
repaint();
} // end if
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
// draw ovals in a 4 x 4 bounding box at specified location on the window
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // clear drawing area
g.setColor(Color.BLUE);
// draw all points in the array
for (int i = 0; i < pointCount; i++) {
g.fillOval(points[i].x, points[i].y, 4, 4);
}
}
}
}
I have written a Java code to draw a polygon on an image. When I put my cursor inside the polygon it prints "Inside" otherwise "Outside". So the detection of the points inside the polygon is working fine.
But I want to implement the effect of setToolTipText inside the polygon i.e. at the time of mouse hover inside the polygon, it will show the floating text "Inside".
Similar to the effect in this image:
http://www.java2s.com/Code/Java/Swing-JFC/WorkingwithTooltipText.htm
What are the minimal changes to be made in the following code to get the desired effect?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.image.*;
import java.awt.Graphics.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
class page1 extends JFrame implements MouseListener,MouseMotionListener ,ActionListener
{
JFrame f;
JLabel l;
JPanel p1;
ImageIcon ii;
Image img;
int height;
int width;
Container c;
int pixels[];
PixelGrabber pg;
JPanel panel;
Graphics2D gg;
Polygon pp1=new Polygon();
boolean startHovercurrent,startHoverprev=false;
page1()
{
f=new JFrame("Sample Page");
ii=new ImageIcon("sample.jpg");
img=ii.getImage();
height=ii.getIconHeight();
width=ii.getIconWidth();
pixels=new int[ii.getIconWidth()*ii.getIconHeight()];
pg=new PixelGrabber(img,0,0,ii.getIconWidth(),ii.getIconHeight(),pixels,0,ii.getIconWidth());
try
{
pg.grabPixels();
}
catch(InterruptedException k)
{
}
//add points of polygon
pp1.addPoint(300,300);
pp1.addPoint(380,300);
pp1.addPoint(380,220);
pp1.addPoint(300,220);
l=new JLabel(ii,JLabel.CENTER);
c=f.getContentPane();
JDesktopPane desk = new JDesktopPane();
JInternalFrame p = new JInternalFrame("Image Frame",false, false, true, false);
JScrollPane scroll = new JScrollPane(l);
p.setContentPane(scroll);
p.setBounds(0, 0, 740, 600);
desk.add(p);
p.setVisible(true);
l.addMouseListener(this);
l.addMouseMotionListener(this);
c.add(desk, BorderLayout.CENTER);
f.setSize(1024,738);
f.setVisible(true);
}
public static void main(String args[])
{
new page1();
}
public void mouseClicked(MouseEvent me)
{
}
public void mouseEntered(MouseEvent me)
{
}
public void mouseExited(MouseEvent me)
{
}
public void mousePressed(MouseEvent me)
{
}
public void mouseReleased(MouseEvent me)
{
}
public void mouseMoved(MouseEvent me)
{
boolean contain1;
int mx,my;
gg=(Graphics2D)l.getGraphics();
gg.setColor(new Color(255,0,0) );
gg.fillPolygon(pp1);
mx = me.getX();
my = me.getY();
//check if mouse cursor is inside polygon or not
// do not print anything if next cursor position is in same state
contain1=pp1.contains(mx,my);
if (contain1) {
startHovercurrent = true;
if(startHovercurrent!=startHoverprev)
System.out.println("Inside");
startHoverprev=startHovercurrent;
}
else {
startHovercurrent = false;
if(startHovercurrent!=startHoverprev)
System.out.println("Outside");
startHoverprev=startHovercurrent;
}
}
public void mouseDragged(MouseEvent me)
{
}
public void actionPerformed(ActionEvent ae)
{
}
}
For this usage, How to Use Tool Tips suggests overriding the getToolTipText() method of the enclosing JComponent. This answer outlines the approach for JMapViewer and ChartPanel. In the example below, getToolTipText() simply returns the name of any Shape that contains() the triggering mouse event. For comparison, the JLabel at window's bottom gets a conventional too tip via setToolTipText().
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.ToolTipManager;
/**
* #see https://stackoverflow.com/a/53609066/230513
* #see https://stackoverflow.com/a/25944439/230513
*/
public class ShapeToolTip {
private static class ShapePanel extends JPanel {
private final List<Shape> list = new ArrayList<>();
public ShapePanel() {
Polygon p = new Polygon();
p.addPoint(500, 100);
p.addPoint(500, 400);
p.addPoint(200, 400);
list.add(p);
list.add(new Ellipse2D.Double(100, 100, 200, 200));
ToolTipManager.sharedInstance().registerComponent(this);
}
#Override
public String getToolTipText(MouseEvent e) {
for (Shape shape : list) {
if (shape.contains(e.getX(), e.getY())) {
return shape.getClass().getName();
}
}
return "Outside";
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.blue);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(2));
for (Shape shape : list) {
g2d.draw(shape);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}
private void display() {
JFrame f = new JFrame("ShapeToolTip");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new ShapePanel());
JLabel title = new JLabel("Shape Tool Tip", JLabel.CENTER);
title.setToolTipText("Title");
title.setFont(title.getFont().deriveFont(Font.BOLD, 24));
f.add(title, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new ShapeToolTip()::display);
}
}
I'm coding a simple card-based game where the player has a hand of cards along the bottom of the screen. When they click on a card, the card moves across the window onto a 'discard pile' location.
I've got the movement animation working to my satisfaction, but the problem is the card button disappears when it moves across other panels. The hand of cards is in the PAGE_END section of a borderlayout for the content pane, and the discard pile is at the top of the screen - so the card has to move across the CENTER section to get to its destination. But it goes behind the CENTER panel, whereas I want it to go in front.
Is this possible? I've tried looking into LayeredPanes but that seems to require all of my components being directly inside one container, which they aren't (because I have another panel inside the bottom section of my content panel).
I've written up the simplest version of the problem that I can, using two classes.
The main class:
package moveButton;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class MoveButton extends JFrame implements ActionListener {
public JPanel view;
public MovingButton mover;
public static MoveButton instance;
public static void main(String[] args) {
instance = new MoveButton();
}
public MoveButton() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500,500);
this.setVisible(true);
view = new JPanel();
view.setLayout(new BorderLayout());
JPanel buttonPanel = new JPanel();
view.add(buttonPanel, BorderLayout.PAGE_END);
mover = new MovingButton("Move");
mover.addActionListener(this);
buttonPanel.add(mover);
this.setContentPane(view);
this.repaint();
this.revalidate();
}
#Override
public void actionPerformed(ActionEvent e) {
MoveButton.instance.mover.timer.start();
}
}
The button class:
package moveButton;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.Timer;
public class MovingButton extends JButton implements ActionListener {
public Timer timer;
public static final int X_INC = 5;
public static final int Y_INC = -5;
public int xPos;
public int yPos;
public MovingButton(String text) {
super(text);
timer = new Timer(30, this);
}
#Override
public void actionPerformed(ActionEvent e) {
this.move();
MoveButton.instance.repaint();
if(xPos == 100 || yPos == 100) {
timer.stop();
}
}
public void move() {
xPos = xPos + X_INC;
yPos = yPos + Y_INC;
}
public void paint(Graphics g) {
g.translate(xPos, yPos);
super.paint(g);
}
}
I want to draw a rectangle every time user clicks on the "Rectangle" button and then clicks on the JFrame based on the event x and y coordinates. I have a component class the draws the rectangle and I have another class that has JFrame mouse press listener.
My Code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JComponent;
public class RectangleComponent extends JComponent
{
Rectangle box;
RectangleComponent()
{
box = new Rectangle(5, 10, 20, 30);
repaint();
}
RectangleComponent(int x, int y)
{
box = new Rectangle(x, y, 20, 30);
}
public void paintComponent(Graphics g)
{
// Recover Graphics2D
Graphics2D g2 = (Graphics2D) g;
// Change the color
Color c = new Color(1.0F,0.0F,1.0F);
g2.setColor(c);
// Draw a rectangle
g2.draw(box);
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Test2
{
static boolean isPressed = false;
public static void main(String[] args)
{
final JFrame frame = new JFrame();
final int FRAME_WIDTH = 400;
final int FRAME_HEIGHT = 400;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("Test 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel panel = new JPanel();
frame.add(panel,BorderLayout.NORTH);
final JButton btnRectangle = new JButton("Rectangle");
panel.add(btnRectangle);
class RectangleButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
isPressed = true;
}
}
ActionListener rectButtonListener = new RectangleButtonListener();
btnRectangle.addActionListener(rectButtonListener);
class MousePressListener implements MouseListener
{
public void mousePressed(MouseEvent event)
{
int x = event.getX() ;
int y = event.getY() ;
if(isPressed)
{
RectangleComponent rc = new RectangleComponent(x, y);
frame.add(rc);
}
}
public void mouseReleased(MouseEvent event){}
public void mouseClicked(MouseEvent event){}
public void mouseEntered(MouseEvent event){}
public void mouseExited(MouseEvent event){}
}
MousePressListener mListener = new MousePressListener();
frame.addMouseListener(mListener);
frame.setVisible(true);
}
}
Now it seems to be doing what I want, but in very strange way. If I click rectangle and click on the frame I see nothing but then if I maximize the frame the rectangle appears where I click. Why is this happening and what is the fix?
To start off with, when using paintComponent() you need to Override it and call it's super method like so:
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
Secondly, Here is your RectangleComponent Class with some slight modifications:
public class RectangleComponent extends JComponent
{
int x, y;
RectangleComponent(int x, int y)
{
this.x = x;
this.y = y;
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Color c = new Color(1.0F,0.0F,1.0F);
g.setColor(c);
g.drawRect(x, y, 50, 50);
}
}
I took the x and y variables and made them member variables so we can access them in the paintComponent() method. I also removed the whole "box" idea and did all the drawing and such in the paintCompnent()
There's also some slight modifications that you should make to your Test2 Class;
Personal recommendation, I suggest switching your drawing code to the mouseReleased event. Along with calling revalidate() and repaint() on your JFrame.
public void mouseReleased(MouseEvent event)
{
int x = event.getXOnScreen();
int y = event.getYOnScreen();
if(isPressed)
{
RectangleComponent rc = new RectangleComponent(x, y);
frame.add(rc);
frame.revalidate();
frame.repaint();
}
}
My results:
Maximizing your frame calls repaint() automatically. It would probably be easiest to call repaint() after adding the RectangleComponent to the frame.
if(isPressed)
{
RectangleComponent rc = new RectangleComponent(x, y);
frame.add(rc);
rc.repaint();
}
I figured instead of adding new component upon click, why not just update a component that already exist by adding more content to it and then repainting it.
Here how this was fixed:
import javax.swing.JComponent ;
import java.awt.event.MouseListener ;
import java.awt.event.MouseEvent ;
import java.awt.Component;
import java.awt.Graphics2D ;
import java.awt.Graphics ;
import java.awt.Shape ;
import java.util.ArrayList ;
public class ShapeComponent extends JComponent
{
private ArrayList<Shape> shapes ;
public ShapeComponent(ArrayList<Shape> shapes1)
{
shapes = shapes1;
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
for (Shape shape : shapes)
{
g2.draw(shape);
}
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Test3
{
static boolean isPressed = false;
static ArrayList<Shape> shapes = new ArrayList<Shape>() ;
public static void main(String[] args)
{
final JFrame frame = new JFrame();
final int FRAME_WIDTH = 400;
final int FRAME_HEIGHT = 400;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("Test 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel panel = new JPanel();
frame.add(panel,BorderLayout.NORTH);
final JButton btnRectangle = new JButton("Rectangle");
panel.add(btnRectangle);
class RectangleButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
isPressed = true;
}
}
ActionListener rectButtonListener = new RectangleButtonListener();
btnRectangle.addActionListener(rectButtonListener);
final JComponent component = new ShapeComponent(shapes) ;
frame.add(component);
class MousePressListener implements MouseListener
{
public void mousePressed(MouseEvent event)
{
int x = event.getX() ;
int y = event.getY() ;
System.out.println("you have press the mouse at X : " + x + " and Y : " + y);
if(isPressed)
{
Rectangle rnew = new Rectangle(x, y, 20, 30);
shapes.add(rnew);
component.repaint();
System.out.println("the button is pressed");
}
else
{
System.out.println("the button is NOT pressed");
}
}
public void mouseReleased(MouseEvent event){}
public void mouseClicked(MouseEvent event){}
public void mouseEntered(MouseEvent event){}
public void mouseExited(MouseEvent event){}
}
MousePressListener mListener = new MousePressListener();
frame.addMouseListener(mListener);
frame.setVisible(true);
}
}
In an attempt to make a very simple bullet-hell game to learn about java, I ran into a roadblock: repaint() wasn't calling paintComponent().
Here is the entire program, which for now simply draws an image I created 50 times per second onto a JPanel, which rests on a JFrame.
/*
* Bullet hell, by Nematodes
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class bulletHell extends JFrame
{
private static final long serialVersionUID = 0L;
JPanel gamePanel = new JPanel();
int gameTimerDelay = 20;
int x, y = 0;
BufferedImage lightOrb;
javax.swing.Timer gameTimer;
public static void main(String[] args)
{
bulletHell createFrame = new bulletHell();
createFrame.frameConstructor();
}
public void frameConstructor()
{
// Construct frame and frame components
setTitle("Bullet hell");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
getContentPane().setLayout(new GridBagLayout());
setVisible(true);
GridBagConstraints gridConstraints;
gridConstraints = new GridBagConstraints();
gridConstraints.gridx = 0;
gridConstraints.gridy = 0;
gamePanel.setBackground(Color.BLACK);
gamePanel.setPreferredSize(new Dimension(700, 700));
getContentPane().add(gamePanel, gridConstraints);
pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds((int) (0.5 * (screenSize.width - getWidth())),
(int) (0.5 * (screenSize.height - getHeight())), getWidth(), getHeight());
try
{
lightOrb = ImageIO.read(new File("C:/Users/Owner/Downloads/orb.bmp"));
}
catch(IOException e)
{
System.out.println("An issue occurred while trying to read orb.bmp");
}
// Start timer that draws game objects 50 times per second (50 FPS)
gameTimer = new javax.swing.Timer(gameTimerDelay, gameTimerAction);
gameTimer.setInitialDelay(0);
gameTimer.start();
}
ActionListener gameTimerAction = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
repaint();
}
};
class GraphicsPanel extends JPanel
{
public GraphicsPanel()
{
}
// Draw all of the components
#Override
public void paintComponent(Graphics g)
{
Graphics2D g2D = (Graphics2D) g;
super.paintComponent(g2D);
g2D.drawImage(lightOrb, x, y, this);
g2D.dispose();
}
}
}
After some debugging with breakpoints and println methods, I can confirm that the correct image is being read, the timer in gameTimerAction is being called 50 times per second, and repaint() is not invoking paintComponent() at all.
I am somewhat new to Java programming, and might just be missing something simple.
Edit: Problem has been solved by changing gamePanel to a GraphicsPanel object. Unfortunately, this also means that my much larger pong project (which this project's flawed drawing logic was essentially copied from) only worked by a miracle, and might be unstable with certain code additions.
I can immediately see several problems:
Most Important: You never instantiate a GraphicsPanel object, nor do you add it to anything. The paintComponent(...) method will never be called on a JPanel that is neither rendered nor created. Why not make your gamePanel variable a GraphicsPanel object and not a JPanel object?
You never change x and y in your Timer, and so without change, no animation will occur.
Also you're calling dispose on a Graphics object given to you by the JVM, something you should never do. This breaks the Swing painting chain making the graphics of your GUI unstable.
So keep at it, you'll get there.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class BulletExample extends JPanel {
public static final String IMG_PATH = "http://www.i2clipart.com/cliparts/f/0/5/8/clipart-blue-circle-f058.png";
private static final int PREF_W = 700;
private static final int PREF_H = PREF_W;
private static final int TIMER_DELAY = 20;
private BufferedImage bullet;
private int bulletX;
private int bulletY;
public BulletExample() throws IOException {
URL imgUrl = new URL(IMG_PATH);
bullet = ImageIO.read(imgUrl);
new Timer(TIMER_DELAY, new BulletListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bullet != null) {
g.drawImage(bullet, bulletX, bulletY, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class BulletListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
bulletX++;
bulletY++;
repaint();
}
}
private static void createAndShowGui() throws IOException {
// create the drawing JPanel
BulletExample mainPanel = new BulletExample();
JFrame frame = new JFrame("BulletExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// add it to the JFrame
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}