I've been working on creating shapes such as rectangles using an ArrayList in java. I'm trying to get the rectangles to appear in the panel one at a time and slowly build an actual image. I've had no problem getting them to appear and stay as random rects (location, size, color)...but when I attempt to make these rects static...it all falls apart. Suggestions will be welcome.
Full code so far below:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.List;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.sound.midi.ControllerEventListener;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GraphicMusicPlayer
implements ControllerEventListener {
static JFrame f = new JFrame("Graphic Music");
static MyDrawPanel myPanel;
#Override
public void controlChange(ShortMessage event) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
GraphicMusicPlayer mini = new GraphicMusicPlayer();
mini.go();
// TODO Auto-generated method stub
}
public void setUpGui() {
// Create the panel within the frame
myPanel = new MyDrawPanel();
f.setContentPane(myPanel);
f.setBounds(700, 700, 800, 800);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void go() {
setUpGui();
try {
// Make and open a sequencer.
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
// Register for events. 127 is the event.
sequencer.addControllerEventListener(myPanel, new int[] {93});
Sequence seq = new Sequence(Sequence.PPQ, 4);
Track track = seq.createTrack();
int r = 0;
int[] tonesList = new int[] {
65, 64, 65, 64, 65, 60, 63, 61,
58,65, 64, 65, 64, 65, 60, 63, 61,
58};
for (int i = 0; i < 18; i +=1) {
r = tonesList[i];
if (r>0){
track.add(makeEvent(144,5,r,93,i));//144 = NOTE_ON
track.add(makeEvent(176,5,93,125,i));//176 = get event
track.add(makeEvent(128,5,r,46,i+1));//128 = NOTE_OFF
}//end loop
sequencer.setSequence(seq);
sequencer.setTempoInBPM(30);
sequencer.start();
}
}
catch (Exception ex) {ex.printStackTrace();}
}
public static MidiEvent makeEvent(int comd, int chan, int one, int two, int tick) {
MidiEvent event = null;
try {
ShortMessage a = new ShortMessage();
a.setMessage(comd, chan, one, two);
event = new MidiEvent(a, tick);
} catch (Exception e) { }
return event;
}
#SuppressWarnings("serial")
class MyDrawPanel extends JPanel implements ControllerEventListener {
boolean msg = false;
ArrayList<Rectangle> rectangleList = new ArrayList<Rectangle>();
Map<Rectangle, Color> rectangleColors = new HashMap<Rectangle, Color>();
public void addRectangle(Rectangle rect){
rectangleList.add(rect);
}
public void controlChange(ShortMessage event) {
msg = true;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.BLACK);
while (msg) {
Graphics2D g2 = (Graphics2D) g;
int red = (int) (Math.random() * 250);
int green = (int) (Math.random() * 250);
int blue = (int) (Math.random() * 250);
Color rcolor = new Color(red, green, blue);
int x = (int) (Math.random() * 750);
int y = (int) (Math.random() * 750);
int width = (int) (Math.random() * 100);
int height = (int) (Math.random() * 100);
Rectangle nextRect = new Rectangle(x,y,width,height);
rectangleList.add(nextRect);
g.setColor(rcolor);
rectangleColors.put(nextRect, rcolor);
//paint all of the rectangles
for (Rectangle rect : rectangleList){
Color rectColor = rectangleColors.get(rect);
g.setColor(rectColor);
// Fill the rectangle with the rectangle color
g2.fill(rect);
}
msg = false;
}
}
}
}
Related
I'm trying to develop a game, it's one of my assignments. In this game, I have several ball draw using pain and I have 3 panels. One plays the role of paddle and 2 others play the roles of obstacles. So I have an issue when trying to detect the collision between the balls and the panel (paddle and obstacle), and another issue is when the collision occurs the ball must move in a different position like the reflection of light on an object.
Find down my code:
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BallWindow extends JFrame implements ActionListener{
JButton btnStop = new JButton("STOP");
JButton btnSave = new JButton("SAVE");
Vector<BallP> ballVector = new Vector<BallP>();
JPanel p1 = createPanel(280, 200, 200, 20, Color.gray);
JPanel p2 = createPanel(280, 300, 200, 20, Color.gray);
JPanel lborder = createPanel(10, 10, 2, 560, Color.black);
JPanel rborder = createPanel(720, 10, 2, 560, Color.black);
JPanel tborder = createPanel(10, 10, 710, 2, Color.black);
//Movement
private static final int Y = 500;
private static final int WIDTH = 60;
private static final int HEIGHT = 10;
int x = 10;
int xa = 0;
JPanel bottomp = createPanel(x, Y, WIDTH, HEIGHT, Color.black);
public BallWindow() {
addKeyListener(new KeyListener()
{
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_LEFT)
bottomp.setLocation(bottomp.getLocation().x -6, bottomp.getLocation().y);
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
bottomp.setLocation(bottomp.getLocation().x + 6, bottomp.getLocation().y);
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
});
setFocusable(true);
setLayout(null);
btnStop.setBounds(12, 15, 100, 30);
btnStop.addActionListener(this);
add(btnStop);
btnSave.setBounds(12, 50, 100, 30);
//btnSave.addActionListener(this);
add(btnSave);
Random r = new Random();
for(int i=0; i<5; i++){
BallP bp = new BallP(r.nextInt(740), r.nextInt(590));
Thread t = new Thread(bp);
ballVector.add(bp);
t.start();
add(bp);
}
add(p1);
add(p2);
Rectangle b = bottomp.getBounds();
add(bottomp);
// add(lborder);
// add(rborder);
// add(tborder);
setSize(740, 570);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
repaint();
}
JPanel createPanel(int x, int y, int width, int height, Color pColor){
JPanel temp = new JPanel();
temp.setBackground(pColor);
temp.setBounds(x, y, width, height);
return temp;
}
public static void main(String[] args) {
new BallWindow();
}
#Override
public void actionPerformed(ActionEvent arg0) {
for (BallP ball : ballVector) {
ball.pleaseWait = !ball.pleaseWait;
}
if( btnStop.getText().equalsIgnoreCase("STOP"))
btnStop.setText("START");
else
btnStop.setText("STOP");
// if(arg0.getSource())
}
}
Here is the code for the ball
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class BallP extends JPanel implements Runnable {
int RED, GREEN, BLUE;
int Xdirection = 1, Ydirection = 1;
boolean pleaseWait = false;
BallP(int X, int Y){
locateBall(X, Y, 30, 30);
/* Random r = new Random();
RED = r.nextInt(255);
GREEN = r.nextInt(255);
BLUE = r.nextInt(255);
*/
}
public void paint(Graphics g){
int panelWidth = this.getWidth();
int panelHeight = this.getHeight();
// g.setColor( new Color(RED, GREEN, BLUE ));
g.setColor(Color.ORANGE);
g.fillOval(panelWidth/2, panelHeight/2,panelWidth/2, panelHeight/2);
}
public void locateBall(int x, int y, int width, int height){
setBounds(x, y, width, height);
repaint();
}
public void run() {
int width = this.getWidth();
int height = this.getHeight();
Random r = new Random();
while(true){
if(!pleaseWait){
int lastX = this.getX();
int lastY = this.getY();
if (lastX > 675) Xdirection = -1;
if (lastY > 485) Ydirection = -1;
if (lastX < -5) Xdirection = 1;
if (lastY < -5) Ydirection = 1;
/* if(lastX > 280 && lastY > 170){
Xdirection = -1;
Ydirection = -1;
}
*/
locateBall(lastX + Xdirection*r.nextInt(3),
lastY + Ydirection*r.nextInt(3),
width, height );
}
try{
Thread.sleep(5);
}catch(Exception e){};
}
}
}
So I'm new at java and need some help with my breakout game. My JFrame is just blank and i don't know how to fix it?
So I have a ball class, paddle class, canvas class and a brick class as well as a main class. In my canvas class I set all functions the ball, paddle and bricks has etc. In brick class I draw the bricks. And in my main I do the JFrame but it's blank
Main class :
public class Main {
public static void main(String[] args){
JFrame frame = new JFrame();
Canvas c = new Canvas();
frame.add(c);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I expect the JFrame to show the game instead of just blank window
package breakout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.KeyEvent;
import breakout.Bricks.Type;
public class Canvas extends JPanel implements ActionListener, MouseMotionListener, MouseListener, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final int HEIGHT = 600;
public static final int WIDTH = 720;
private int horizontalCount;
private BufferedImage image;
private Graphics2D bufferedGraphics;
private Timer time;
private static final Font endFont = new Font(Font.SANS_SERIF, Font.BOLD, 20);
private static final Font scoreFont = new Font(Font.SANS_SERIF, Font.BOLD, 15);
private Paddle player;
private Ball ball;
ArrayList<ArrayList<Bricks>> bricks;
public Canvas() {
super();
setPreferredSize( new Dimension(WIDTH, HEIGHT));
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
bufferedGraphics = image.createGraphics();
time = new Timer (15, this);
player = new Paddle((WIDTH/2)-(Paddle.PADDLE_WIDTH/2));
ball = new Ball (((player.getX() + (Paddle.PADDLE_WIDTH / 2 )) - (Ball.DIAMETER / 2)), (Paddle.Y_POS - (Ball.DIAMETER + 10 )), -5, -5);
bricks = new ArrayList<ArrayList<Bricks>>();
horizontalCount = WIDTH / Bricks.BRICK_WIDTH;
for(int i = 0; i < 8; ++i) {
ArrayList<Bricks> temp = new ArrayList<Bricks>();
#SuppressWarnings("unused")
Type rowColor = null;
switch(i) {
case 0 :
case 2:
rowColor = Type.LOW;
break;
case 1 :
case 3 :
case 5 :
rowColor = Type.MEDIUM;
break;
case 4 :
case 6 :
rowColor = Type.HIGH;
break;
case 7 :
default :
rowColor = Type.ULTRA;
break;
}
for(int j = 0; j < horizontalCount; ++j) {
Bricks tempBrick = new Bricks();
temp.add(tempBrick);
}
bricks.add(temp);
addMouseMotionListener(this);
addMouseListener(this);
addKeyListener(this);
requestFocus();
}
}
public void actionPerformed(ActionEvent e) {
checkCollisions();
ball.Move();
for(int i = 0; i < bricks.size(); ++i) {
ArrayList<Bricks> al = bricks.get(i);
for(int j = 0; j < al.size(); ++j) {
Bricks b = al.get(j);
if(b.dead()) {
al.remove(b);
}
}
}
repaint();
}
private void checkCollisions() {
if(player.hitPaddle(ball)) {
ball.setDY(ball.getDY() * -1);
return;
}
if(ball.getX() >= (WIDTH - Ball.DIAMETER) || ball.getX() <= 0) {
ball.setDX(ball.getDX() * -1);
}
if(ball.getY() > (Paddle.Y_POS + Paddle.PADDLE_HEIGHT + 10)) {
resetBall();
}
if(ball.getY() <= 0) {
ball.setDY(ball.getDY() * -1);
}
int brickRowActive = 0;
for(ArrayList<Bricks> alb : bricks) {
if(alb.size() == horizontalCount) {
++brickRowActive;
}
}
for(int i = (brickRowActive==0) ? 0 : (brickRowActive - 1); i < bricks.size(); ++i) {
for(Bricks b : bricks.get(i)) {
if(b.hitBy(ball)) {
player.setScore(player.getScore() + b.getBrickType().getPoints());
b.decrementType();
}
}
}
}
private void resetBall() {
if(gameOver()) {
time.stop();
return;
}
ball.setX(WIDTH/2);
ball.setDY((HEIGHT/2) + 80);
player.setLives(player.getLives() -1);
player.setScore(player.getScore() <= 1);
}
private boolean gameOver() {
if(player.getLives() <= 1) {
return true;
}
return false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
bufferedGraphics.clearRect(0, 0, WIDTH, HEIGHT);
player.drawPaddle(bufferedGraphics);
player.drawBall(bufferedGraphics);
for(ArrayList<Bricks> row : bricks) {
for(Bricks b : row) {
b.drawBrick(bufferedGraphics);
}
}
bufferedGraphics.setFont(scoreFont);
bufferedGraphics.drawString("Score: " + player.getScore(), 10, 25);
if(gameOver() && ball.getY() >= HEIGHT) {
bufferedGraphics.setColor(Color.black);
bufferedGraphics.setFont(endFont);
bufferedGraphics.drawString("Game Over Score: " + player.getScore(), (WIDTH /2) -85, (HEIGHT/2));
}
if(empty()) {
bufferedGraphics.setColor(Color.black);
bufferedGraphics.setFont(endFont);
bufferedGraphics.drawString("You won. Score: " + player.getScore(), (WIDTH /2) -85, (HEIGHT /2));
time.stop();
}
g.drawImage(image, 0, 0, this);
Toolkit.getDefaultToolkit().sync();
}
private boolean empty() {
for(ArrayList<Bricks> al : bricks) {
if(al.size() != 0) {
return false;
}
}
return true;
}
#Override
public void mouseMoved(MouseEvent e) {
player.setX(e.getX() - (Paddle.PADDLE_WIDTH / 2));
}
#Override
public void mouseClicked(MouseEvent e) {
if(time.isRunning()) {
return;
}
time.start();
}
#Override
public void mouseDragged(MouseEvent e) { }
#Override
public void mouseEntered(MouseEvent arg0) {}
#Override
public void mouseExited(MouseEvent arg0) {}
#Override
public void mousePressed(MouseEvent arg0) {}
#Override
public void mouseReleased(MouseEvent arg0) {}
#Override
public void keyPressed(KeyEvent arg0) {}
#Override
public void keyReleased(KeyEvent arg0) {}
#Override
public void keyTyped(KeyEvent arg0) {}
}
Preparing an MCVE, as required in SO, not only it makes helping much easier.
In many case, while preparing one, you are likely to find the problem, so it is a good debugging tool.
To answer "why is my JFrame blank ?" you could create the minimal code example like the following (copy-paste the entire code into GameBoard.java and run):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameBoard extends JPanel {
static final int HEIGHT = 600, WIDTH = 720, BRICK_ROWS = 8;
private final int horizontalCount;
private static final Font scoreFont = new Font(Font.SANS_SERIF, Font.BOLD, 15);
private final Paddle player;
private final Ball ball;
ArrayList<ArrayList<Brick>> bricks;
public GameBoard() {
super();
setPreferredSize( new Dimension(WIDTH, HEIGHT));
player = new Paddle(WIDTH/2-Paddle.PADDLE_WIDTH/2);
ball = new Ball (player.getX() + Paddle.PADDLE_WIDTH / 2 - Ball.DIAMETER / 2,
Paddle.Y_POS - (Ball.DIAMETER + 10 ));
bricks = new ArrayList<>();
horizontalCount = WIDTH / Brick.BRICK_WIDTH;
for(int i = 0; i < BRICK_ROWS; ++i) {
ArrayList<Brick> temp = new ArrayList<>();
for(int j = 0; j < horizontalCount; ++j) {
Brick tempBrick = new Brick(j*Brick.BRICK_WIDTH , Brick.BRICK_YPOS + i*Brick.BRICK_HEIGHT);
temp.add(tempBrick);
}
bricks.add(temp);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D)g;
g2D.clearRect(0, 0, WIDTH, HEIGHT);
player.drawPaddle(g2D);
ball.drawBall(g2D);
for(ArrayList<Brick> row : bricks) {
for(Brick b : row) {
b.drawBrick(g2D);
}
}
g2D.setFont(scoreFont);
g2D.drawString("Score: " + player.getScore(), 10, 25);
}
}
class Paddle{
public final static int PADDLE_WIDTH = 100, PADDLE_HEIGHT= 30, Y_POS = GameBoard.HEIGHT - 2* PADDLE_HEIGHT;
private int xPos, score;
Paddle(int xPos) {
this.xPos = xPos;
}
void setX(int xPos) {this.xPos = xPos;}
int getX() {return xPos;}
String getScore() {
return String.valueOf(score);
}
void drawPaddle(Graphics2D g2D) {
g2D.setColor(Color.GREEN);
g2D.fillRect(xPos, Y_POS, PADDLE_WIDTH, PADDLE_HEIGHT);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(400,250);
frame.add(new GameBoard());
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}
class Brick{
final static int BRICK_WIDTH = 80, BRICK_HEIGHT = 15, BRICK_YPOS = 50;
int xPos, yPos;
Brick(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBrick(Graphics2D g2D) {
g2D.setColor(Color.RED);
g2D.fillRect(xPos, yPos, BRICK_WIDTH, BRICK_HEIGHT);
g2D.setColor(Color.BLACK);
g2D.drawRect(xPos, yPos, BRICK_WIDTH, BRICK_HEIGHT);
}
}
class Ball{
final static int DIAMETER = 40;
int xPos, yPos;
Ball(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall(Graphics2D g2D) {
g2D.setColor(Color.BLUE);
g2D.fillOval(xPos, yPos, DIAMETER, DIAMETER);
}
}
This produces the following result, which I believe can serve as the basis of what you wanted to achieve:
Now start adding the missing functionality and see what breaks it.
I am working on music application which creates a square and repaint the screen at every single event. The events are the sounds, I created them with sound.midi API. However, when I run the app the squares do not appear on the window! Could someone tell me what I am doing wrong?
Here is my main class :
import javax.sound.midi.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
public class BeatBoxProject {
static JFrame f = new JFrame ("My first mucic video");
static DrawPanel m1;
public static void main(String[] args) {
BeatBoxProject mini = new BeatBoxProject();
mini.go();
}
public void setUpGui(){
m1 = new DrawPanel();
f.setContentPane(m1);
f.setBounds(30, 30, 300, 300);
f.setVisible(true);
}
public void go(){
setUpGui();
try{ Sequencer player = MidiSystem.getSequencer();
player.open(); // we need the open the sequencer
player.addControllerEventListener(m1, new int [] {127});
Sequence seq = new Sequence( Sequence.PPQ, 4);
Track track = seq.createTrack();
int r = 0;
for (int i = 0; i < 60; i+=4) {
r = (int) ((Math.random()*50)+ 1);
track.add(makeEvent(144,1,r,100,i));
track.add(makeEvent(176,1,127,0,i));
track.add(makeEvent(128,1,r,100,i+2));
}
player.setSequence(seq); // lets put the disk into the player
player.setTempoInBPM(120); // lets set the beat(beat per minutes)
player.start();
}catch (Exception ex){
ex.printStackTrace();
}
}
public static MidiEvent makeEvent (int comd, int chan, int one, int two, int tick){
MidiEvent event = null;
try{
ShortMessage a = new ShortMessage();
a.setMessage(comd, chan, two, two);
event = new MidiEvent(a,tick);
}catch(Exception e) {}
return event;
}
}
And here is the DrawPanel Class:
import javax.sound.midi.ControllerEventListener;
import java.awt.*;
import javax.sound.midi.ShortMessage;
import javax.swing.*;
public class DrawPanel extends JPanel implements ControllerEventListener {
boolean msg = false; // its false unles we gonna have an event
public void controlChange(ShortMessage event) {
msg = true;
repaint();
}
public void paintComponent (Graphics g){
if (msg){ // wee need the msg because other thing can repaint the panel but we only want when event occurs
Graphics2D g2 = (Graphics2D) g;
int r = (int) (Math.random()* 250);
int gr = (int) (Math.random()* 250);
int b = (int) (Math.random()* 250);
g.setColor(new Color(r,gr,b));
int ht = (int) ((Math.random()*120) +10);
int width = (int) ((Math.random()*120) +10);
int x = (int) ((Math.random()*40) +10);
int y = (int) ((Math.random()*40) +10);
g.fillRect(x, y, width, HEIGHT);
msg=false;
}
}
}
Change
player.addControllerEventListener(m1, new int [] {127});
to
player.addControllerEventListener(m1, new int [] {0});
I'm trying to make it so that both shapes move when the commands are pressed. My question is: How do I get the blue polygon to move along with the yellow rectangle? I can't seem to figure it out, no matter what I do. Any help is appreciated! thanks!
EDIT: Removed Timer Code (it is for something different)
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.Color;
import java.awt.Polygon;
import java.util.Scanner;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Original {
public static void main(String[] args) {
// contruction of new JFrame object
JFrame frame = new JFrame();
// mutators
frame.setSize(400,400);
frame.setTitle("SwingBot");
// program ends when window closes
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Robot r = new Robot();
frame.add(r);
// voila!
frame.setVisible(true);
// your Scanner-based command loop goes here
int noend = 0;
System.out.println("Type a Command:");
while(noend == 0)
{
Scanner input = new Scanner(System.in);
String command = input.next();
if(command.equals("left"))
r.moveBot(-10,0);
if(command.equals("right"))
r.moveBot(10,0);
if(command.equals("down"))
r.moveBot(0,10);
if(command.equals("up"))
r.moveBot(0,-10);
}
// call methods on the Robot instance like w.moveBot(10,10) in response to
// user input
}
public static class Robot extends JComponent
{
private Rectangle rect = new Rectangle(20,60);
private Polygon poly = new Polygon();
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
// set the color
g2.setColor(Color.ORANGE);
// draw the shape`
g2.fill(rect);
int xPoly[] = {75, 125, 170, 170, 200, 105, 60};
int yPoly[] = {75, 50, 88, 111, 125, 180, 150};
poly = new Polygon(xPoly, yPoly, xPoly.length);
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawPolygon(poly);
}
public void moveBot(int x, int y)
{
// move the rectangle
rect.translate(x,y);
poly.translate(x,y);
// redraw the window
repaint();
}
}
}
Suggestions:
Don't create the shapes in the paintComponent method.
When creating them give them variables that can be changed
In the Timer or key press, or where ever you are trying to move them, change those variable and call repaint()
For multiple objects you can have a an interface like Shape where each Shape has a move() method that can be called.
Loop through an data structure of those objects and call their move() methods, then repaint()`
A Shape can have a drawShape(Graphics g) method, and you can loop through the data structure of Shape inside the paintComponent method and call drawShape(g)
You can see this answer for an example.
UPDATE
Here's an example of all the points I mention above.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class MoveShape extends JPanel {
List<Shape> shapes;
public MoveShape() {
shapes = createShapeList();
InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke("RIGHT"), "moveRight");
ActionMap am = getActionMap();
am.put("moveRight", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
for (Shape sh : shapes) {
sh.moveRight();
repaint();
}
}
});
}
private List<Shape> createShapeList() {
List<Shape> list = new ArrayList<>();
int xPoly[] = {75, 125, 170, 170, 200, 105, 60};
int yPoly[] = {75, 50, 88, 111, 125, 180, 150};
list.add(new MyPolygon(xPoly, yPoly, 6));
list.add(new MyRectangle(75, 250, 150, 150));
return list;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Shape sh : shapes) {
sh.drawShape(g);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(450, 450);
}
public class MyRectangle implements Shape {
int x, y, width, height;
public MyRectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
#Override
public void drawShape(Graphics g) {
g.fillRect(x, y, width, height);
}
#Override
public void moveRight() {
x += INCREMENT;
}
}
public class MyPolygon implements Shape {
int[] xPoints;
int[] yPoints;
int numPoints;
public MyPolygon(int[] xPoints, int[] yPoints, int numPoints) {
this.xPoints = xPoints;
this.yPoints = yPoints;
this.numPoints = numPoints;
}
#Override
public void drawShape(Graphics g) {
g.fillPolygon(xPoints, yPoints, numPoints);
}
#Override
public void moveRight() {
for (int i = 0; i < xPoints.length; i++) {
xPoints[i] += INCREMENT;
}
}
}
public interface Shape {
public static final int INCREMENT = 5;
public void drawShape(Graphics g);
public void moveRight();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Move Shapes");
frame.add(new MoveShape());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
As #peeskillet has already pointed out...in your paintComponent method, you were re-creating the poly object each time it was called...meaning it never moved, and in fact was potential NullPointerException waiting to happen...
public void paintComponent(Graphics g)
{
//...
// This is a bad idea...
poly = new Polygon(xPoly, yPoly, xPoly.length);
//...
}
Instead, create the poloygon in the constructor to your Robot panel.
This example also demonstrates Initial Threads and key bindings and Stroking and Filling Graphics Primitives
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Original {
public static void main(String[] args) {
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.setSize(400, 400);
frame.setTitle("SwingBot");
Robot r = new Robot();
frame.add(r);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class Robot extends JComponent {
private Rectangle rect = new Rectangle(20, 60);
private Polygon poly = new Polygon();
public Robot() {
int xPoly[] = {75, 125, 170, 170, 200, 105, 60};
int yPoly[] = {75, 50, 88, 111, 125, 180, 150};
poly = new Polygon(xPoly, yPoly, xPoly.length);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "Up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "Down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "Left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "Right");
ActionMap am = getActionMap();
am.put("Up", new MoveAction(0, -10));
am.put("Down", new MoveAction(0, 10));
am.put("Left", new MoveAction(-10, 0));
am.put("Right", new MoveAction(10, 0));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
// set the color
g2.setColor(Color.ORANGE);
// draw the shape`
g2.fill(rect);
g2.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2.drawPolygon(poly);
g2.dispose();
}
public void moveBot(int x, int y) {
// move the rectangle
rect.translate(x, y);
poly.translate(x, y);
// redraw the window
repaint();
}
public class MoveAction extends AbstractAction {
private int xDelta;
private int yDelta;
public MoveAction(int xDelta, int yDelta) {
this.xDelta = xDelta;
this.yDelta = yDelta;
}
#Override
public void actionPerformed(ActionEvent e) {
moveBot(xDelta, yDelta);
}
}
}
}
Please, make sure you give all credit to #peeskillet, I just wanted to highlight some problem areas and solutions you might consider
I am trying to paint JFrame when music is played , these shapes are created on random no calculation and when a there is some music played there pops up a JFrame and these shapes are painted there, problem is that when i run this code there is no musical sound and shapes drawn but just a frame pops up and nothing else , Plase check this code and help me to correct it ..
public class MusicBeatsDrawing {
static JFrame frame;
DrawPanel dp =new DrawPanel();
public static void main(String[] args)
{
MusicBeatsDrawing mbd= new MusicBeatsDrawing();
mbd.go();
}
public void SetGui(){
frame= new JFrame("Simple frame ; ");
frame.setBounds(100, 100, 200, 200);
frame.setContentPane(dp);
frame.setVisible(true);
}
public void go()
{
SetGui();
try
{
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
Sequence seq= new Sequence(Sequence.PPQ, 4);
sequencer.addControllerEventListener(dp,new int [] {127});
Track track = seq.createTrack();
int r = 0;
for (int i = 0; i < 60 ; i+= 4) {
r = (int) Math.random()*50;
track.add(MakeEvent(144,1,r,100,i));
track.add(MakeEvent(176,1,127,0,i));
track.add(MakeEvent(128,1,r,100,i ));
}
sequencer.setSequence(seq);
sequencer.start();
}
catch(Exception e)
{e.printStackTrace(); }
}
public MidiEvent MakeEvent(int one , int two , int three , int four , int tick)
{
MidiEvent event= null;
try
{
ShortMessage sm= new ShortMessage();
sm.setMessage(one,two, three, four);
event= new MidiEvent(sm , tick );
} catch (InvalidMidiDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return event;
}
class DrawPanel extends JPanel implements ControllerEventListener
{
boolean msg= false ;
public void paintComponent(Graphics g)
{
if(msg){ Graphics2D g2d= (Graphics2D) g;
int red= (int) (Math.random()*255);
int green= (int) (Math.random()*255) ;
int blue= (int) (Math.random()*255);
g.setColor(new Color(red, green , blue));
int height= (int)Math.random()*255;
int width= (int)Math.random()*255;
int x= (int)Math.random()*255;
int y= (int)Math.random()*255;
g.fillRect(height, width, x, y);
msg = false;
}
}
#Override
public void controlChange(ShortMessage event) {
msg= true;
repaint();
}}
}
Swing GUI objects should be constructed and manipulated only on the event dispatch thread. With this change, your program works. A telltale symptom is that the program runs when you resize the frame, which causes the system to invoke repaint() repeatedly.
Addendum: Some additional issues merit attention,
Make setVisible() last.
The sequencer startup latency may be worth moving to the background.
Use named constants, e.g. ShortMessage.NOTE_ON, rather than magic numbers.
Instantiate Random for later use.
Follow Java naming conventions.
Revised SSCCE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.sound.midi.ControllerEventListener;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see http://stackoverflow.com/a/17767350/230513
*/
public class MidiDrawing {
private static final Random R = new Random();
public static void main(String[] args) {
EventQueue.invokeLater(new MidiDrawing()::display);
}
public void display() {
JFrame frame = new JFrame("Midi Drawing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DrawPanel dp = new DrawPanel();
frame.add(dp);
Sequencer sequencer = initSequencer(dp);
JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT));
p.add(new JButton(new AbstractAction("Start") {
#Override
public void actionPerformed(ActionEvent e) {
sequencer.setTickPosition(0);
sequencer.start();
}
}));
frame.add(p, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private Sequencer initSequencer(DrawPanel dp) {
try {
Sequencer sequencer = MidiSystem.getSequencer();
Sequence seq = new Sequence(Sequence.PPQ, 3);
Track track = seq.createTrack();
int n = 60; // middle C
for (int i = 0; i < 3 * 12; i += 3) {
track.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, 0, 0, n), i));
track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_ON, 0, n, 127), i));
track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_ON, 0, n + 3, 127), i));
track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_OFF, 0, n, 127), i + 3));
track.add(new MidiEvent(new ShortMessage(ShortMessage.NOTE_OFF, 0, n + 3, 127), i + 3));
n++;
}
sequencer.open();
sequencer.setSequence(seq);
sequencer.addControllerEventListener(dp, new int[]{0});
return sequencer;
} catch (InvalidMidiDataException | MidiUnavailableException e) {
e.printStackTrace(System.err);
}
return null;
}
private static class DrawPanel extends JPanel implements ControllerEventListener {
private final Font font = this.getFont().deriveFont(24f);
private int data;
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.getHSBColor(R.nextFloat(), 1, 1));
g.fillRect(0, 0, getWidth(), getHeight());
g.setFont(font);
g.setColor(Color.black);
g.drawString(String.valueOf(data), 8, g.getFontMetrics().getHeight());
}
#Override
public void controlChange(ShortMessage event) {
data = event.getData2();
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(256, 128);
}
}
}