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();
}
}
});
}
}
Related
I have a 3d-object composed of multiple polygons that I draw using graphics2D. When I rotate it it, it seems as if it has not enough time to draw the entire object at every frame since at some frames, some of the polygons are simply missing(not drawn). I don't understand how that can be since I in paintComponent first draw all the polygons onto the bufferedImage myImg, and then draw the finished image onto the screen. When I remove clearRect, this issue is resolved but then of course it doesn't remove the last frame's drawing before drawing the next.
Note: I'm an amateur but I've tried really hard understanding and so this is my last resort and would be really glad to get some help. The code (with unnecessary code removed is as follows) :
public class Main {
long temp = System.currentTimeMillis() + frameRate;
public static void main(String[] args) {
myGUI = new GUI(width, height);
while(true) {
if (System.currentTimeMillis() >= temp) {
temp += frameRate;
rotateObject();
myGUI.myCanvas.myLabel.repaint();
}
}
}
}
public class GUI extends JFrame {
public Canvas myCanvas;
public GUI(int w, int h) {
this.setSize(w, h);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myCanvas = new Canvas(w, h);
this.getContentPane().add(myCanvas);
this.setVisible(true);
this.pack();
}
}
public class Canvas extends JPanel {
public BufferedImage myImg;
public Graphics2D g2d;
public JLabel myLabel;
public Canvas(int w, int h) {
myImg = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
myLabel = new JLabel(new ImageIcon(myImg));
this.add(myLabel);
g2d = myImg.createGraphics();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g2d.clearRect(0, 0, myImg.getWidth(), myImg.getHeight());
g2d.setColor(Color.RED));
g2d.fillPolygon(pointsX, pointsY, 3);
g.drawImage(myImg, 0, 0, null);
}
}
This is how my object is flickering
You really need to take the time to read through:
Performing Custom Painting
Painting in AWT and Swing
2D Graphics
Concurrency in Swing
How to Use Swing Timers
These aren't "beginner" topics and a reasonable understanding of Swing in general and the language in particular would be very advantageous.
Don't, ever, use getGraphics on a component. This is simply a bad idea (and I have no idea why this method is public).
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TestPane extends JPanel {
private BufferedImage myImg;
private double rotation;
public TestPane() throws IOException {
myImg = ImageIO.read(getClass().getResource("/images/happy.png"));
Timer timer = new Timer(33, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
rotation += Math.toRadians(5);
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform at = AffineTransform.getTranslateInstance((getWidth() - myImg.getWidth()) / 2, (getHeight() - myImg.getHeight()) / 2);
at.rotate(rotation, myImg.getWidth() / 2, myImg.getHeight() / 2);
g2d.transform(at);
g2d.drawImage(myImg, 0, 0, this);
g2d.dispose();
}
}
}
package imgscoring;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import static java.lang.System.exit;
public class IMGSCORING
{
private JButton button1;
private JPanel main;
private JButton button2;
private JLabel lblLed;
private JButton button3;
private JLabel label;
private JLabel logo;
private static Image i;
public IMGSCORING() {
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
try {
runProgam();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
button2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
exit(1);
}
});
Image i = Toolkit.getDefaultToolkit().createImage("C:\\Users\\djuwo\\Desktop\\icon.jpg");
}
public static void paint(Graphics g)
{
g.drawImage(i, 0, 0, null);
}
public void runProgam() throws IOException, InterruptedException {
QrScanner run = new QrScanner();
run.runProgram();
}
public JPanel getMain() {
return main;
}
public void setMain(JPanel main) {
this.main = main;
}
public static void main(String[] args) {
JFrame frame = new JFrame(" IMG FORMING Label Generator");
frame.setContentPane(new IMGSCORING().main);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ImageIcon img = new ImageIcon("C:\\Users\\djuwo\\Desktop\\icon.jpg");
frame.setIconImage(img.getImage());
}
private void createUIComponents() {
// TODO: place custom component creation code here
logo = new JLabel(new ImageIcon("icon.jpg"));
}
}
I am very new to using the gui for Java and based on looking around and seeing others code I can definitely tell mine is way off from how it should look.. Would appreciate feedback on how to properly format my code as well as how to add a background. The program works and buttons respond, icon are changed, etc. But I am unable to change the background. At first I tried the following but that obviously didn't work.
frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:\\Users\\djuwo\\Desktop\\icon.jpg")))));
In the following solutions, you can see the following steps:
Override paintComponent of JPanel, in order to draw the image in its background.
Add any elements you want in the subclassed JPanel.
Add the subclassed JPanel to the content pane of the JFrame.
setOpaque(false) in the subclassed JPanel in order to show the background (where we paint the image).
In the first solution, I just paint the image once and not care about filling the frame when it is resized:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class RegularMain extends JPanel {
private final BufferedImage bimg;
public RegularMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
this.bimg = Objects.requireNonNull(bimg);
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
#Override
protected void paintComponent(final Graphics g) {
g.drawImage(bimg, 0, 0, this);
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new RegularMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
But, another approach is to resize the image to correspond to the panel's size:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TransformMain extends JPanel {
private final BufferedImage bimg;
public TransformMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
this.bimg = Objects.requireNonNull(bimg);
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
g2d.scale(getWidth() / (double) bimg.getWidth(), getHeight() / (double) bimg.getHeight());
g2d.drawImage(bimg, 0, 0, this);
g2d.dispose();
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TransformMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
And finally another approach is to make the image a TexturePaint, if you want the image to be repeated:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TextureMain extends JPanel {
private final TexturePaint paint;
public TextureMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
paint = new TexturePaint(bimg, new Rectangle2D.Double(0, 0, bimg.getWidth(), bimg.getHeight()));
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
g2d.setPaint(paint);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TextureMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
The difference in the solutions above is visible when the frame/panel is resized. In the first case, the frame is not supposed to be resized so we only draw the image once, without changing it in size. In the second case the image size follows the panel's size. And in the final case we repeat the image vertically and horizontally up to the panel's size (by using TexturePaint).
All the cases have in common that we paint the image in paintComponent before everything else and that we setOpaque to false.
I'm trying to make a 2d side scrolling game. I have been able to display the background but as soon as I add a sprite the only thing displayed on the frame is the sprite. (Sorry if this is a simple mistake but I am new to java)
Here is my main class
package com.projectelrond.main;
import javax.swing.JFrame;
import com.projectelrond.Sprites.Ranger;
public class Main {
public int WIDTH = 160, HEIGHT = WIDTH/12 *9, SCALE = 3;
public boolean running = false;
BackGround bg = new BackGround();
JFrame f = new JFrame("name");
public static void main(String[] args) {
new Main();
}
public Main() {
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(WIDTH * SCALE, HEIGHT * SCALE);
f.setResizable(false);
f.add(new BackGround());
f.add(new Ranger());
f.setVisible(true);
running = true;
run();
}
public void run() {
while (running) {
//handles in game events NPCs, Traps etc.
}
}
}
My Background class
package com.projectelrond.main;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class BackGround extends JPanel {
private static final long serialVersionUID = 1L;
public BufferedImage Bg;
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(Bg, 0, 0, null);
}
public BackGround() {
try {
Bg = ImageIO.read(new File("src/Images/BG.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
and last but not least the sprite that I am trying to add
package com.projectelrond.Sprites;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class Ranger extends JPanel{
private static final long serialVersionUID = 1L;
public BufferedImage RangerIm;
public Ranger() {
try {
RangerIm = ImageIO.read(new File("src/Images/Sprites/Ranger.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(RangerIm, 0, 0, null);
}
}
Thanks for all the help and if there are any tips that you wish to share they will be much obliged.
g.drawImage(RangerIm, 0, 0, null);
You are drawing the image at its actual size. There is no need to do custom painting for this. You would do custom painting if you want to scale the image.
Instead you can just use a JLabel with an ImageIcon:
BufferedImage rangerIm = ImageIO.read(new File("src/Images/Sprites/Ranger.png"));
JLabel ranger = new JLabel( new ImageIcon(rangerIm) );
ranger.setSize( ranger.getPreferredSize() );
BufferedImage backgroundIm = Bg = ImageIO.read(new File("src/Images/BG.png"));
JLabel background = new JLabel( new ImageIcon(rangerIm) );
background.add( ranger );
f.add(background, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setResizable(false);
f.pack();
f.setVisible(true);
Now the ranger is added to the background which is added to the frame. Also, you need to add the components to the frame BEFORE the frame is visible(). The pack() method will make the frame the size of the background image.
Eventually after I work out this small detail it will receive a building and room number to outline said building and room number so it is easy to locate but I can't get the rectangle to draw even close to acurately over a single room.
package programSTLApp;
/*
Program to request the classroom no. in STLCC and Display the location of
that classroom.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class STLApp extends JFrame
{
private JLabel imageLabel;
private JButton button;
private JPanel imagePanel;
private JPanel buttonPanel;
public STLApp()
{
super("My STLCC Class Locator");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
buildImagePanel();
buildButtonPanel();
add(imagePanel, BorderLayout.CENTER);
add(buttonPanel,BorderLayout.SOUTH);
pack();
setVisible(true);
}
private void buildImagePanel()
{
imagePanel = new JPanel();
imageLabel = new JLabel("Click the button to see the drawing indicating "
+ "the location of your class");
imagePanel.add(imageLabel);
}
private void buildButtonPanel()
{
buttonPanel = new JPanel();
button = new JButton("Get Image");
button.addActionListener(new ButtonListener());
buttonPanel.add(button);
}
private class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
ImageIcon SiteLayoutFV = new ImageIcon("D:\\B120.jpg");
imageLabel.setIcon(SiteLayoutFV);
imageLabel.setText(null);
pack();
}
}
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.RED);
g.fillRect(55,740,164,815);
}
public static void main(String[] args)
{
new STLApp();
}
}
As has already being pointed out, top level containers ain't a studiable class for performing custom painting, there is just to much going with these containers to make it easy to paint to.
Instead, create yourself a custom component, extending from something like JPanel, and override it's paintComponent method.
Once you have the floor pane rendered, you can render you custom elements over the top of it.
How you store this information is up to you, but basically, you need some kind of mapping that would allow you to take the floor/room and get the Shape that should be rendered.
Because the floor map might float (it may not always be rendered at 0x0 for example), you need to be able to translate the coordinates so that the Shape will always match.
Take a look at...
Performing Custom Painting
2D Graphics
For more details
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
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;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FloorPlan {
public static void main(String[] args) {
new FloorPlan();
}
public FloorPlan() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage floorPlan;
private Rectangle myOffice = new Rectangle(150, 50, 32, 27);
public TestPane() {
try {
floorPlan = ImageIO.read(new File("floorPlan.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return floorPlan == null ? new Dimension(200, 200) : new Dimension(floorPlan.getWidth(), floorPlan.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (floorPlan != null) {
int x = (getWidth() - floorPlan.getWidth()) / 2;
int y = (getHeight() - floorPlan.getHeight()) / 2;
g2d.drawImage(floorPlan, x, y, this);
g2d.setColor(Color.RED);
g2d.translate(x, y);
g2d.draw(myOffice);
}
g2d.dispose();
}
}
}
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);
}
}