Painting to a panel using threads in Java - java

do not know why there is not printing going on here in my run method. I call repaint and override it in the horsethread class. here is my code. When I run the program and hit Run Race it doesnt draw anything to the panel, any ideas?
import javax.swing.JFrame;
public class HorseTester {
public static void main(String[] args)
{
JFrame frame = new HorsePanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.JButton;
import java.awt.GridLayout;
import java.util.ArrayList;
public class HorsePanel extends JFrame
{
private JPanel panel;
private JButton reset;
private JButton quit;
private JButton run;
private ActionListener listener;
private static final int NUM_OF_HORSES = 5;
public static final int FRAME_WIDTH = 400;
public static final int FRAME_HEIGHT = 400;
private ArrayList<Thread> allThreads = new ArrayList<Thread>();
private ArrayList<HorseThread> horses = new ArrayList<HorseThread>();
public HorsePanel()
{
//Allocating the memory for horses
for(int i=0;i<NUM_OF_HORSES;i++)
horses.add(new HorseThread(i+1));
//Adding them to thread pool
for(int i=0;i<NUM_OF_HORSES;i++)
allThreads.add( new Thread(horses.get(i)));
createPanel();
createRunRace();
createQuit();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
public void createRunRace()
{
class RunRace implements ActionListener
{
public void actionPerformed(ActionEvent rightEvent)
{
run.setEnabled(false);
for(int i=0;i<NUM_OF_HORSES;i++)
allThreads.get(i).start();
}
}
ActionListener a = new RunRace();
this.run.addActionListener(a);
}
public void createQuit()
{
class QuitRace implements ActionListener
{
public void actionPerformed(ActionEvent rightEvent)
{
System.exit(0);
}
}
ActionListener b = new QuitRace();
this.quit.addActionListener(b);
}
public void createPanel()
{
panel = new JPanel(new BorderLayout());
JPanel drawingPanel = new JPanel();
this.run = new JButton("Run Race");
this.quit = new JButton("Quit");
this.reset = new JButton("Reset");
JPanel topPanel = new JPanel();
topPanel.setLayout(new GridLayout(1, 3));
topPanel.add(run);
topPanel.add(reset);
topPanel.add(quit);
panel.add(topPanel, BorderLayout.NORTH);
panel.add(drawingPanel, BorderLayout.SOUTH);
add(panel);
}
}
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JComponent;
public class HorseThread extends JComponent implements Runnable
{
public static final int X_START = 10;
public static final int Y_START = 20;
private Horse horse;
private int xpos, ypos;
public HorseThread(int offset)
{
xpos = X_START;
ypos = Y_START * offset;
horse = new Horse(xpos, ypos);
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
horse.draw(g2);
}
/**
* Run method that thread executes and makes horses go across
* the screen racing.
*/
public void run()
{
repaint();
}
}
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
public class Horse
{
private int xTop;
private int yTop;
public static final int RING_WIDTH = 20;
public Horse(int x, int y)
{
xTop = x;
yTop = y;
}
public void setXY(int dx, int dy)
{
xTop = dx;
yTop = dy;
}
public void draw(Graphics2D g2)
{
Ellipse2D.Double horse = new Ellipse2D.Double(xTop, yTop, RING_WIDTH, RING_WIDTH);
g2.setColor(Color.BLUE);
g2.fill(horse);
g2.setColor(Color.WHITE);
g2.fill(horse);
}
}

The main problem is, HorseThread extends from JComponent, but you never actually add it to anything, therefore it never gets painted.
If, instead, you created a TrackPane and painted each of the horses within the paintComponent method (there's no need for HorseThread to extend from JComponent), you might have better luck.
Also note, that once a Thread has completed, it can not be restarted...
For example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class HorseTester {
public static void main(String[] args) {
new HorseTester();
}
public HorseTester() {
JFrame frame = new HorsePanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public class HorsePanel extends JFrame {
private JPanel panel;
private JButton reset;
private JButton quit;
private JButton run;
private ActionListener listener;
public static final int FRAME_WIDTH = 400;
public static final int FRAME_HEIGHT = 400;
private TrackPane trackPane;
public HorsePanel() {
createPanel();
createRunRace();
createQuit();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
public void createRunRace() {
class RunRace implements ActionListener {
public void actionPerformed(ActionEvent rightEvent) {
run.setEnabled(false);
trackPane.start();
}
}
ActionListener a = new RunRace();
this.run.addActionListener(a);
}
public void createQuit() {
class QuitRace implements ActionListener {
public void actionPerformed(ActionEvent rightEvent) {
System.exit(0);
}
}
ActionListener b = new QuitRace();
this.quit.addActionListener(b);
}
public void createPanel() {
panel = new JPanel(new BorderLayout());
trackPane = new TrackPane();
this.run = new JButton("Run Race");
this.quit = new JButton("Quit");
this.reset = new JButton("Reset");
JPanel topPanel = new JPanel();
topPanel.setLayout(new GridLayout(1, 3));
topPanel.add(run);
topPanel.add(reset);
topPanel.add(quit);
panel.add(topPanel, BorderLayout.NORTH);
panel.add(trackPane, BorderLayout.CENTER);
add(panel);
}
}
public class TrackPane extends JPanel {
private static final int NUM_OF_HORSES = 5;
private ArrayList<HorseThread> horses = new ArrayList<HorseThread>();
private ArrayList<Thread> threads = new ArrayList<Thread>(25);
public TrackPane() {
setBackground(Color.GREEN);
reset();
}
public void reset() {
// Should dispose of any running threads...
horses.clear();
//Allocating the memory for horses
for (int i = 0; i < NUM_OF_HORSES; i++) {
horses.add(new HorseThread(this, i + 1));
}
}
public void start() {
// Should dispose of any running threads...
threads.clear();
for (int i = 0; i < horses.size(); i++) {
Thread thread = new Thread(horses.get(i));
thread.start();
threads.add(thread);
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (HorseThread horse : horses) {
horse.paint(g);
}
}
}
public class HorseThread implements Runnable {
public static final int X_START = 10;
public static final int Y_START = 20;
private Horse horse;
private int xpos, ypos;
private TrackPane track;
public HorseThread(TrackPane track, int offset) {
xpos = X_START;
ypos = Y_START * offset;
horse = new Horse(xpos, ypos);
this.track = track;
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
horse.draw(g2);
}
/**
* Run method that thread executes and makes horses go across the screen
* racing.
*/
public void run() {
track.repaint();
}
}
public class Horse {
private int xTop;
private int yTop;
public static final int RING_WIDTH = 20;
public Horse(int x, int y) {
xTop = x;
yTop = y;
}
public void setXY(int dx, int dy) {
xTop = dx;
yTop = dy;
}
public void draw(Graphics2D g2) {
Ellipse2D.Double horse = new Ellipse2D.Double(xTop, yTop, RING_WIDTH, RING_WIDTH);
g2.setColor(Color.BLUE);
g2.fill(horse);
g2.setColor(Color.WHITE);
g2.draw(horse);
}
}
}
Also note that Swing is not thread safe, be careful using Threads in this environment ;)

Related

How to fix flickering of dynamic moving images over a JPanel that is on top of another pre-painted JPanel?

I have made 2 JPanels, Panel and BackGround, in a JFrame. I am dynamically painting the Panel after 10ms(using a Timer), but the BackGround is only painted once at the beginning of the game. The Panel is responsible for the displaying of the fighters(spacecrafts), the projectiles and the aliens. The BackGround is responsible for the displaying of the background scene which is non-dynamic. The paintComponent(Graphics) method does paint the fighters and the projectiles, but flickers when they are updating. Can someone find the cause.
This is my Frame:
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Frame extends JFrame {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 1280;
public static final int HEIGHT = 720;
public static final int DELAY = 10;
private Panel panel;
private Background bg;
public Frame() {
panel = new Panel();
bg = new Background();
initComponents();
}
public void initComponents() {
this.setSize(WIDTH, HEIGHT);
this.add(bg);
this.add(panel);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_LEFT) panel.moveLeft();
else if(e.getKeyCode() == KeyEvent.VK_RIGHT) panel.moveRight();
}
});
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Frame().setVisible(true);
}
});
}
}
This is my Panel:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Panel extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
public static final int DELAY = Frame.DELAY;
private Timer timer;
private BufferedImage fighter;
int x, y;
public Panel() {
timer = new Timer(DELAY, this);
try {
fighter = ImageIO.read(this.getClass().getResource("fighter.png"));
} catch (IOException e) {
e.printStackTrace();
}
initComponents();
timer.start();
}
public void initComponents() {
this.setSize(Frame.WIDTH, Frame.HEIGHT);
this.setDoubleBuffered(true);
this.setBackground(new Color(0, 0, 0, 0));
x = 150;
y = 200;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
doDrawing(g2d);
}
private void doDrawing(Graphics2D g2d) {
g2d.drawImage(fighter, x, y, null);
}
#Override
public void actionPerformed(ActionEvent arg0) {
this.repaint();
}
public void moveLeft() {
x -= 10;
}
public void moveRight() {
x += 10;
}
}
This is the BackGround:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Background extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
private BufferedImage backGround;
private Timer timer;
public Background() {
this.setSize(Frame.WIDTH, Frame.HEIGHT);
this.setBackground(new Color(0, 0, 0, 0));
timer = new Timer(Frame.DELAY, this);
try {
backGround = ImageIO.read(this.getClass().getResource("background.png"));
} catch (IOException e) {
e.printStackTrace();
}
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(backGround, 0, 0, null);
}
#Override
public void actionPerformed(ActionEvent e) {
this.repaint();
}
}
I expect the sprites not to flicker and not to lag(which is not happening after lots of trials).
Do not call repaint within a painting method
Get rid of the Background class and do all drawing in one JPanel. For example:
See example below of both as well as of MCVE design
whole thing can be copy/pasted into IDE and run
uses images available to all online, not on disk
I would also remove the Timer that simply calls repaint() and instead either
call repaint from within the KeyListener
or use the timer to do the actual sprite movement code (with repaint()). This would be useful if you want continuous movement
Example MCVE:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Frame1 extends JFrame {
// Image attribution:
// By Adam Evans - M31, the Andromeda Galaxy (now with h-alpha)
// Uploaded by NotFromUtrecht, CC BY 2.0,
// https://commons.wikimedia.org/w/index.php?curid=12654493
public static final String ANDROMEDA_IMAGE = "https://upload.wikimedia.org/wikipedia/commons/"
+ "thumb/9/98/Andromeda_Galaxy_%28with_h-alpha%29.jpg/"
+ "1280px-Andromeda_Galaxy_%28with_h-alpha%29.jpg";
public static final String SPRITE_IMAGE = "https://upload.wikimedia.org/wikipedia/commons/"
+ "thumb/a/a1/Glossy_3d_blue_blue2.png/" + "120px-Glossy_3d_blue_blue2.png";
private static final long serialVersionUID = 1L;
public static final int WIDTH = 1280;
public static final int HEIGHT = 720;
public static final int DELAY = 10;
private Panel1 panel;
// private Background bg;
public Frame1() {
panel = new Panel1();
// bg = new Background();
initComponents();
}
public void initComponents() {
this.setSize(WIDTH, HEIGHT);
// this.add(bg);
this.add(panel);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT)
panel.moveLeft();
else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
panel.moveRight();
}
});
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Frame1().setVisible(true);
}
});
}
}
class Panel1 extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
public static final int DELAY = Frame1.DELAY;
private Timer timer;
private BufferedImage fighter;
private BufferedImage background;
int x, y;
public Panel1() {
timer = new Timer(DELAY, this);
try {
URL url = new URL(Frame1.SPRITE_IMAGE);
// fighter = ImageIO.read(this.getClass().getResource("fighter.png"));
fighter = ImageIO.read(url);
url = new URL(Frame1.ANDROMEDA_IMAGE);
background = ImageIO.read(url);
} catch (IOException e) {
e.printStackTrace();
}
initComponents();
timer.start();
}
public void initComponents() {
this.setSize(Frame1.WIDTH, Frame1.HEIGHT);
this.setDoubleBuffered(true);
this.setBackground(new Color(0, 0, 0, 0));
x = 150;
y = 200;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, this);
g.drawImage(fighter, x, y, this);
}
#Override
public void actionPerformed(ActionEvent arg0) {
this.repaint();
}
public void moveLeft() {
x -= 10;
}
public void moveRight() {
x += 10;
}
}

how do I make this java awt/ swing animation work?

I'm pretty new to java coding, but i know the basic structures of how to code. I am not familiar with awt/swing, and don't know what my error is.
Background: I searched up ways to animate with java, found zetcode tutorials.
I copy/pasted their code, and tested the program, to make sure it works. the JFrame opened, but nothing drew. Maybe this is a system compatibility error? if so, how would I fix it?
these are the two separate classes:
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.JFrame;
public class ThreadAnimationExample extends JFrame {
public ThreadAnimationExample() {
initUI();
}
private void initUI() {
add(new Board());
setResizable(false);
pack();
setTitle("Star");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame ex = new ThreadAnimationExample();
ex.setVisible(true);
}
});
}
}
This is the main class.
Board.java
package com.zetcode;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Board extends JPanel
implements Runnable {
private final int B_WIDTH = 350;
private final int B_HEIGHT = 350;
private final int INITIAL_X = -40;
private final int INITIAL_Y = -40;
private final int DELAY = 25;
private Image star;
private Thread animator;
private int x, y;
public Board() {
initBoard();
}
private void loadImage() {
ImageIcon ii = new ImageIcon("star.png");
star = ii.getImage();
}
private void initBoard() {
setBackground(Color.BLACK);
setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
setDoubleBuffered(true);
loadImage();
x = INITIAL_X;
y = INITIAL_Y;
}
#Override
public void addNotify() {
super.addNotify();
animator = new Thread(this);
animator.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawStar(g);
}
private void drawStar(Graphics g) {
g.drawImage(star, x, y, this);
Toolkit.getDefaultToolkit().sync();
}
private void cycle() {
x += 1;
y += 1;
if (y > B_HEIGHT) {
y = INITIAL_Y;
x = INITIAL_X;
}
}
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (true) {
cycle();
repaint();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0) {
sleep = 2;
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("Interrupted: " + e.getMessage());
}
beforeTime = System.currentTimeMillis();
}
}
}
When I run the program, I get a blank black window. The program is supposed to draw a star. Here is what it is supposed to look like.

Java Animation with ActionListener

So I'm trying to draw 2 circles on top of each other (kinda like a snowman) and move the snowman to the right when the user clicks on the "Start" button and stop moving the snowman when the user clicks on the "Stop" button. However, the only thing that I am able to come up with is 2 snowmen drawn next to each other that don't react to the buttons.
Here is what I've come up with:
import java.awt.Graphics2D;
public interface MoveableShape {
void draw(Graphics2D g);
void translate(int dx, int dy);
}
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
public class SnowmanShape implements MoveableShape {
private int x;
private int y;
private int width;
public SnowmanShape(int x, int y, int width){
this.x = x;
this.y = y;
this.width = width;
}
#Override
public void draw(Graphics2D g2) {
// TODO Auto-generated method stub
Ellipse2D.Double head = new Ellipse2D.Double(0, 0, 10, 10);
Ellipse2D.Double body = new Ellipse2D.Double(0, 11, 10, 10);
g2.draw(head);
g2.draw(body);
}
#Override
public void translate(int dx, int dy) {
// TODO Auto-generated method stub
x += dx;
y += dy;
}
}
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class MyPanel extends JPanel{
MoveableShape s;
public MyPanel (MoveableShape m){
s = m;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
s.draw((Graphics2D)g);
}
}
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class AnimationTester {
private static final int DEFAULT_WIDTH = 400;
private static final int DEFAULT_HEIGHT = 200;
private static final int SNOWMAN_WIDTH = 50;
final static MoveableShape shape = new SnowmanShape(0, 0, SNOWMAN_WIDTH);
final static JPanel panel = new MyPanel(shape);
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame frame = new JFrame();
frame.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
frame.setLayout(new BorderLayout());
frame.add(panel);
frame.add(startButton, BorderLayout.NORTH);
frame.add(stopButton, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
final int DELAY = 100;
// Milliseconds between timer ticks
Timer t = new Timer(DELAY, translateSnowman());
startButton.addActionListener(startTimer(t));
stopButton.addActionListener(stopTimer(t));
}
public static ActionListener translateSnowman(){
return new ActionListener(){
public void actionPerformed(ActionEvent event){
shape.translate(1, 0);
panel.repaint();
}
};
}
public static ActionListener startTimer(final Timer t){
return new ActionListener(){
public void actionPerformed(ActionEvent event){
t.start();
}
};
}
public static ActionListener stopTimer(final Timer t){
return new ActionListener(){
public void actionPerformed(ActionEvent event){
t.stop();
}
};
}
}
Could someone please let me know where I went wrong or point me in the right direction?
EDIT: I fixed up the AnimationListener so now it doesn't draw 2 snowmans. The snowman still won't move however. I updated the code in the post as well.
Add g2.translate(x, y); to SnowmanShape#draw, before you are painting:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
class SnowmanShape implements MoveableShape {
static final Color headColor = new Color(0xFFE9C9);
static final Color bodyColor = new Color(0xEAF6FF);
static final Color outlineColor = new Color(0x252525);
int x;
int y;
int size;
Ellipse2D.Double head;
Ellipse2D.Double body;
SnowmanShape(int x, int y, int size) {
this.x = x;
this.y = y;
this.size = size;
initModel();
}
void initModel() {
head = new Ellipse2D.Double(0, 0, size, size);
body = new Ellipse2D.Double(0, head.height, size * 1.3d, size * 1.5d);
body.x -= (body.width - head.width) * (1 / 2d);
}
#Override
public void draw(Graphics2D g2) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.translate(x, y);
g2.setColor(headColor);
g2.fill(head);
g2.setColor(outlineColor);
g2.draw(head);
g2.setColor(bodyColor);
g2.fill(body);
g2.setColor(outlineColor);
g2.draw(body);
}
#Override
public void translate(int dx, int dy) {
x += dx;
y += dy;
}
}
I not an expert on doing things like this, but if I were you I would use the timer to move the objects and then call the paint to repaint the objects in a new position. Therefore, your ShapeIcon class would just keep track of the position of your objects. That probably wasn't all that helpful, so to point you in right direction, you can check out some code in this tutorial here.

Simple Java game draws only half window

I can not figure out why the game is only drawing only on half the window I make.
I add in actionPerformed to always implement to y position and it goes only on half the window , then the images stopes.
Main
import java.awt.EventQueue;
import javax.swing.JFrame;
public class Main extends JFrame{
public static void main(String[]args){
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame ex = new Main();
ex.setVisible(true);
}
});
}
public Main(){
setTitle("Maze");
add(new Game());
pack();
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Game
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Game extends JPanel implements ActionListener {
private final int GWIDTH = 400;
private final int GHEIGHT = 400;
private int GAME_DELAY = 10;
private Timer timer;
private Image player;
/*Player*/
private final int spawnPosition = 0;
int playerX = 0;
int playerY = spawnPosition;
/*Mouse*/
private Mouse m;
public Game(){
setFocusable(true);
setPreferredSize(new Dimension(GWIDTH, GHEIGHT));
addMouseListener(new Mouse());
initTime();
//Importam poza
loadPlayer();
//Mouse
m = new Mouse();
}
private void initTime(){
timer = new Timer(GAME_DELAY, this);
timer.start();
}
private void loadPlayer(){
ImageIcon img = new ImageIcon("smiley.png");
player = img.getImage();
}
public int getX(){ return playerX; }
public int getY() { return playerY; }
private void drawPlayer(Graphics2D g2d){
g2d.drawImage(player,getX(),getY(),null);
Toolkit.getDefaultToolkit().sync();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawPlayer(g2d);
g2d.dispose();
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
playerY += 1;
repaint();
}
}
Image

Java Graphics Checkout Simulation;

I am working on a project which is a Checkout Simulation. I have the code to make it work run but i am struggling to understand and implement how to add graphics(in my case a square) once a certain condition is true. For example i have made my code so that it goes through random numbers and if 2,4,6 or 8 has been randomly generated, someone will be added to the queue and the same goes for if they are even numbers 1 or 3, someone is removed from the queue. I basically just want to know how to add a square to the screen once i have met my condition (for example, generating a 4 should add a square to the screen but it doesn't)
ANY help would really be appreciated!
public class MainPanel extends JPanel {
private Queue<String> tillQueue;
private int rndNumber;
private int currentLength;
private ArrayList<Integer> lengthList;
private double mean;
private Random rand;
private int MAXLENGTH;
private static Random r = new Random();
private static Random r2 = new Random();
Color colour;
private static final int IMAGE_SIZE = 600;
private Timer timer;
private int delay;
private JButton startButton;
private JButton stopButton;
private BufferedImage buffer;
JToolBar toolbar;
public MainPanel() {
startButton = new JButton("START");
stopButton = new JButton("STOP");
toolbar = new JToolBar();
toolbar.add(startButton);
toolbar.add(stopButton);
this.buffer = new BufferedImage(IMAGE_SIZE, IMAGE_SIZE, BufferedImage.TYPE_INT_ARGB);
setDoubleBuffered(false);
StartActionHandler start = new StartActionHandler();
StopActionHandler stop = new StopActionHandler();
TimerEvent timerEvt = new TimerEvent();
startButton.addActionListener(start);
stopButton.addActionListener(stop);
delay = 50;
timer = new Timer(delay, timerEvt);
}
public class TimerEvent implements ActionListener {
public void actionPerformed(ActionEvent e) {
//drawNext(buffer.getGraphics());
for (int time = 1; time < 9; time++) {
rndNumber = rand.nextInt(6) + 1; //generates random number
if (rndNumber == 2 || rndNumber == 4 || rndNumber == 6 || rndNumber == 8) {
//time is added to queue
tillQueue.add(String.valueOf(time));
drawNext(buffer.getGraphics());
repaint();
}
}
}
}
public class StartActionHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
timer.start();
}
}
private void drawNext(Graphics g) {
int x = r.nextInt(IMAGE_SIZE);
int y = r.nextInt(IMAGE_SIZE);
int red = r2.nextInt(255);
int green = r2.nextInt(255);
int blue = r2.nextInt(255);
Color randomColour = new Color(red, green, blue);
g.setColor(randomColour);
g.fillRect(x, y, 10, 10);
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(buffer, 0, 0, this);
}
}
Note several changes to get rendering working:
For convenience, use the buffer's createGraphics() method and dispose() it when done.
Initialize the offscreen buffer to a known state.
One instance of Random is usually sufficient.
Limit variable scope to the extent possible, e.g. private class TimerEvent.
Override getPreferredSize() to establish the rendering area size.
As tested:
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.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.Timer;
/**
* #see https://stackoverflow.com/a/21238669/230513
*/
public class Test {
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MainPanel());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test().display();
}
});
}
private static class MainPanel extends JPanel {
private static final int SIZE = 500;
private static final int DELAY = 100;
private static final Random r = new Random();
private final Queue<String> tillQueue = new LinkedList<>();
private Timer timer;
private JButton startButton;
private JButton stopButton;
private BufferedImage buffer;
private JToolBar toolbar;
public MainPanel() {
super(new BorderLayout());
startButton = new JButton("START");
stopButton = new JButton("STOP");
toolbar = new JToolBar();
toolbar.add(startButton);
toolbar.add(stopButton);
buffer = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = buffer.createGraphics();
g.clearRect(0, 0, SIZE, SIZE);
g.dispose();
StartActionHandler start = new StartActionHandler();
TimerEvent timerEvt = new TimerEvent();
timer = new Timer(DELAY, timerEvt);
startButton.addActionListener(start);
add(new JLabel(new ImageIcon(buffer)));
add(toolbar, BorderLayout.SOUTH);
}
private class TimerEvent implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
for (int time = 1; time < 9; time++) {
if (r.nextInt(6) % 2 == 0) {
tillQueue.add(String.valueOf(time));
drawNext();
}
}
}
}
private class StartActionHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
}
}
private void drawNext() {
Graphics2D g = buffer.createGraphics();
int x = r.nextInt(SIZE);
int y = r.nextInt(SIZE);
g.setColor(new Color(r.nextInt()));
g.fillRect(x, y, 10, 10);
g.dispose();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(buffer, 0, 0, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
}
}
How is suposed to work? when you met the condition an item is added to tillQueue, but tillQueue is never readed...
I you want to draw something you can draw it in the method paintComponent.
To draw a rectangle simply use:
http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html#drawRect(int, int, int, int)
You can iterate the tillQueue in the paintComponent method and draw the corresponding rectangles.

Categories