I am having trouble getting the animation visible on top of my garden grid panel. Whichever I add last to the contentpane that one shows. is there anyway to show multiple components at the same time. I've tried switching the classes animation and garden grid to extend jpanel but nothing has worked. Animation is a series of images that shows a character moving when you are dragging it with a mouse. I need that character to move on top of the garden grid panel. any help?
package view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.GridBagLayout;
import java.awt.Panel;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
public class Driver {
public static void main(String[] args) {
JFrame frame = new JFrame();
JLayeredPane pane = new JLayeredPane();
frame.add(pane);
Animation animation = new Animation();
GardenPanel garden = new GardenPanel(6,4,600,800);
pane.add(animation,new Integer(1));
pane.add(garden, new Integer(0));
frame.setSize(800, 600);
System.out.println(pane.highestLayer());// just to check I dont have hidden layers
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
while(true){
frame.repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
--------Animation Class-----------
you should see a moving orc. you can drag the orc using your mouse. If you press * your mouse without moving it, the power will increase. * */
package view;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
public class Animation extends JComponent implements MouseMotionListener, MouseListener{
final int frameCount = 10;
int picNum = 0;
BufferedImage[][] pics;
int xloc = 0;
int yloc = 0;
final int xIncr = 8;
final int yIncr = 2;
final static int frameWidth = 900;
final static int frameHeight = 600;
final static int imgWidth = 165;
final static int imgHeight = 165;
//basic info about the orc
BufferedImage seedImage;
int mouseX;
int mouseY;
int seedX = xloc;
int seedY = yloc;
boolean mouseholding;
boolean moving = false;
int power;
public enum stage {
MOVE, POWER
}
stage s;
//Override this JPanel's paint method to cycle through picture array and draw images
public void paint(Graphics g) {
picNum = (picNum + 1) % frameCount;
if(mouseholding && (s == s.POWER)){
System.out.println(power++);
}
g.drawImage(pics[0][picNum], xloc, yloc, Color.gray, this);
g.drawImage(seedImage, seedX, seedY, imgWidth/8, imgHeight/8, this);
}
//Constructor: get image, segment and store in array
public Animation(){
seedImage = createImage();
BufferedImage[] img = createAnimation();
pics = new BufferedImage[img.length][10];
for(int j = 0; j < img.length; j++){
for(int i = 0; i < frameCount; i++)
pics[j][i] = img[j].getSubimage(imgWidth*i, 0, imgWidth, imgHeight);
}
addMouseMotionListener(this);
addMouseListener(this);
}
//Read image from file and return
private BufferedImage[] createAnimation(){
BufferedImage[] bufferedImage = new BufferedImage[4];
try {
bufferedImage[0] = ImageIO.read(new File("images/orc_forward_southeast.png"));
bufferedImage[1] = ImageIO.read(new File("images/orc_forward_southwest.png"));
bufferedImage[2] = ImageIO.read(new File("images/orc_forward_northeast.png"));
bufferedImage[3] = ImageIO.read(new File("images/orc_forward_northwest.png"));
return bufferedImage;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private BufferedImage createImage(){
BufferedImage bufferedImage;
try {
bufferedImage = ImageIO.read(new File("images/seed.png"));
return bufferedImage;
} catch (IOException e) {
e.printStackTrace();
}
return null;
// TODO: Change this method so you can load other orc animation bitmaps
}
// implement the method in mouseListener and mouseMotionListener interface
@Override
public void mouseDragged(MouseEvent event) {
mouseX = event.getX();
mouseY = event.getY();
if( ( xloc<mouseX ) && (xloc+imgWidth >mouseX) && (yloc<mouseY) && (yloc+imgHeight>mouseY) && (s==stage.MOVE) ){
//System.out.println("Imagecoor:("+xloc+", "+yloc+")"+" mousecoor:("+mouseX+","+mouseY+")");
// you can print the coordinate if you want
xloc = mouseX-imgWidth/2;
yloc = mouseY-imgHeight/2;
seedX = mouseX;
seedY = mouseY;
}
} // draging the image
@Override
public void mouseMoved(MouseEvent arg0) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
// for increasing the power.
@Override
public void mousePressed(MouseEvent event) {
mouseholding = true;
mouseX = event.getX();
mouseY = event.getY();
if( (xloc == mouseX-imgWidth/2) && (yloc == mouseY-imgHeight/2) ){
s = stage.POWER;
}
}
@Override
public void mouseReleased(MouseEvent event) {
mouseholding = false;
s = stage.MOVE;
power = 0;
}
}
--------GardenPanel Class------------ should display 2 black lines
package view;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
public class GardenPanel extends JComponent {
private int numOfRows;
private int numOfColumns;
private int frameWidth;
private int frameHeight;
public GardenPanel(int numOfRows, int numOfColumns, int frameHeight, int frameWidth){
this.numOfRows = numOfRows;
this.numOfColumns = numOfColumns;
this.frameHeight = frameHeight;
this.frameWidth = frameWidth;
}
int secondX = ((frameWidth -((frameWidth/3) *2)) / 4) * 3;
@Override
public void paint(Graphics g){
g.drawLine((frameWidth/3) * 2, (frameHeight/4) * 3, (frameWidth/3 * 2) - 30, frameHeight/4);
g.drawLine(((frameWidth/3) * 2) + 200, (frameHeight/4) * 3, ((frameWidth -((frameWidth/3) *2)/4) * 3) - 30, frameHeight/4);
}
}
There are two ways to make the animation sit on top of the Garden Panel. However as pointed out by "Hovercraft Full Of Eels" there are issues with how you are using a "GridBagLayout".
When working with animations I tend to use absolution positioning, this way it is easy to manually specify the exact location of components, and you can ensure that everything will be visible. I do this by adding a jLayeredPane/jPanel to the jFrame and adding components to them instead of the jFrame.
Here are two ways you can make the animation sit on top of the GardenPanel.
1) Add the component in a different order for different results. Give it a try.
2) Once all components have been added to the "ContentPane" you can set the Z-Order of the component you want on top, something like this:
Edit: From what you have showed you have the basics, so here is a self contained example that you can compile that I believe demonstrates what you want to do.
The
animation
is represented by the red box, theGardenPanel
is represented by the blue area.Please note:
pane
. First:pane.add(animation);
Then:pane.add(GardenPanel);
.JLabel
instead of your customAnimation
component and aJLayeredPane
instead of yourGardenPanel
component, you should be able to just swap them both out.Remove the while loop in the Drive class, at least while testing. You can sort out the repaint issue later once you know both components are showing correctly.
}
Using this example code you can possibly adapt your original code to follow a similar path.
You state:
A JFrame's contentPane uses BorderLayout, and that's how BorderLayouts work. If you add a component by default (without an int 2nd parameter), it is placed by default in the BorderLayout.CENTER position and covers anything added there previously. You will want to read the Swing layout manager tutorial for more details on this.
Yes, use different layout managers and components. If you want components on top of each other, consider using a JLayeredPane.
Not sure what your exact question is here.