Remove transparent JPanel from JPanel - java

I want to replace a panel by another one (all of them has transparent section).
The code is as followed:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class PhotoFrame extends JFrame {
public class PhotosDisplayPanel extends JPanel {
private static final long serialVersionUID = 1L;
private String[] imgsLink = null;
private long delay = 1000;
private long period = 1000;
private int curIdx = 0;
private PhotoDisplayPanel currentPhoto = null;
public PhotosDisplayPanel(String[] imgsLink) {
super();
this.imgsLink = imgsLink;
setBackground(new Color(0, 0, 0, 0));
setLayout(new GridLayout(1, 1));
currentPhoto = new PhotoDisplayPanel(imgsLink[curIdx]);
add(currentPhoto);
}
public void start() {
if (imgsLink == null) {
return;
}
curIdx = -1;
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
curIdx++;
if (curIdx >= imgsLink.length) {
curIdx = 0;
}
displayNextImage();
}
}, delay, period);
}
protected void displayNextImage() {
if (currentPhoto != null) {
remove(currentPhoto);
}
revalidate();
repaint();
currentPhoto = new PhotoDisplayPanel(imgsLink[curIdx]);
add(currentPhoto);
revalidate();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
}
public class PhotoDisplayPanel extends JPanel {
private static final long serialVersionUID = 1L;
private String imgLink;
public PhotoDisplayPanel(String imgLink) {
super();
this.imgLink = imgLink;
}
#Override
protected void paintComponent(Graphics g) {
if (imgLink != null && !imgLink.equals("")) {
System.out.println("Draw image");
// get dimension of the panel
int pWidth = getWidth();
int pHeight = getHeight();
g.setColor(new Color(255, 0, 0, 50));
g.fillRect(0, 0, pWidth, pHeight);
Image img = new ImageIcon(imgLink).getImage();
// Calculate positions and dimensions
int imgWidth = img.getWidth(this);
int imgHeight = img.getHeight(this);
int iwidth = 0;
int iheight = 0;
if (imgWidth / imgHeight > pWidth / pHeight) {
iwidth = pWidth;
iheight = imgHeight * pWidth / imgWidth;
} else {
iheight = pHeight;
iwidth = imgWidth * pHeight / imgHeight;
}
int ix = (pWidth - iwidth) / 2;
int iy = (pHeight - iheight) / 2;
// Fill the picture to the panel
g.drawImage(img, ix, iy, iwidth, iheight, this);
} else {
super.paintComponent(g);
}
}
}
private static final long serialVersionUID = 1L;
private static final int defaultWidth = 650;
private static final int defaultHeight = 400;
private int width = defaultWidth;
private int height = defaultHeight;
private PhotosDisplayPanel photoPanel; // is view panel which display
// input and output
private String[] imgsLink;
public PhotoFrame() {
initialize();
imgsLink = new String[] { "background.png", "screenShot.jpg" };
createControls();
}
private void createControls() {
setLayout(new GridLayout(0, 1));
photoPanel = new PhotosDisplayPanel(imgsLink);
add(photoPanel);
photoPanel.start();
}
private void initialize() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(width, height);
setTitle("PhotosFrame");
setAlwaysOnTop(false);
setBackground(Color.CYAN);
setLayout(new GridLayout(1, 1));
setContentPane(new JLabel(new ImageIcon("blue_sunset.jpg")));
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new PhotoFrame().setVisible(true);
}
});
}
}
In which, currentPhoto is a panel with transparent background. However, the image of the old panel is not cleaned totally, I can see the old one under the new one. Is there any way to clear the image of old panel comprehensively?
Thanks

However, the image of the old panel is not cleaned totally,
Check out Backgrounds With Transparency for the probable cause and a couple of solutions.
Basically when using transparent backgrounds Swing does not know that is need to repaint the background so you need to force the repainting.

Related

MouseListener for a custom circle object is not working when it is drawn to a JPanel Gameboard object

I am developing the peg game in java, and I have been stuck on getting a hole to change color when it is clicked on to indicate that it has been selected. I currently have 3 classes, all of which extend JPanel:
Display.java: creates the JFrame and renders the gameboard to the JFrame.
GameBoard.java: Holds the logic for rendering the gameboard.
Hole.java: Renders a hole and holds the logic for the MouseListener. When one clicks on a hole, it should turn blue to indicate that it is selected.
I am able to render the holes onto the gameboard, however, the MouseListener does not work; When I click on a hole, it does not turn blue.
Below are the three classes:
Display.java
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.logging.*;
public class Display extends JPanel {
private static final long serialVersionUID = 1L;
private static String staticClassName = Display.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private final static Logger LOGGER = Logger.getLogger(staticClassName);
private static String title;
private static int width;
private static int height;
private static JFrame frame;
private static JPanel mainPanel;
private static GameBoard gameBoard;
public Display(String title, int width, int height){
logger.info(staticClassName +".Constructor: Constructing Display");
Display.title = title;
Display.width = width;
Display.height = height;
logger.info(staticClassName +".Constructor: Display constructed.");
initDisplay();
}
private static void initDisplay() {
logger.info(staticClassName +".initDisplay(): Entering method");
try {
logger.info(staticClassName +".initDisplay(): About to create JFrame");
frame = new JFrame(title);
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
logger.info(staticClassName +".initDisplay(): About to create GameBoard object");
gameBoard = new GameBoard();
mainPanel.add(gameBoard);
frame.getContentPane().add(mainPanel);
frame.pack();
} catch (Exception e) {
logger.info(staticClassName +".initDisplay(): Failed to render display: " + e);
}
logger.info(staticClassName +".initDisplay(): Exiting Method");
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
LOGGER.setLevel(Level.INFO);
Display d = new Display("Peg Game", 800, 800);
} catch (Exception e) {
}
}
});
}
}
GameBoard.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import java.util.logging.Logger;
import javax.swing.JPanel;
public class GameBoard extends JPanel {
private static final long serialVersionUID = 1L;
private static String staticClassName = GameBoard.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private static final int RGB1 = 223;
private static final int RGB2 = 191;
private static final int RGB3 = 159;
private static final int WIDTH = 800;
private static final int HEIGHT = WIDTH;
private Path2D path = new Path2D.Double();
private static Color boardColor = new Color(RGB1, RGB2, RGB3);
private int [] adjacentHoles1;
public GameBoard() {
logger.info(staticClassName +".Constructor: Constructing GameBoard");
double firstX = (WIDTH / 2.0) * (1 - 1 / Math.sqrt(3));
double firstY = 3.0 * HEIGHT / 4.0;
path.moveTo(firstX, firstY);
path.lineTo(WIDTH - firstX, firstY);
path.lineTo(WIDTH / 2.0, HEIGHT / 4.0);
path.closePath();
logger.info(staticClassName +".Constructor: GameBoard constructed");
}
#Override
protected void paintComponent(Graphics g) {
logger.info(staticClassName +".paintComponent(): Entering method");
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(boardColor);
g2.fill(path);
int xPos = 390;
int yPos = 310;
// I was rendering up to 15 holes, but took them out for purpose of
// shortening my example
for (int i = 0; i < 15; i ++ ) {
if (i == 0) {
// Declare the hole here
Hole hole = new Hole(i, xPos, yPos, adjacentHoles1);
// Render it here
hole.paintComponent(g2);
yPos += 50;
}
}
logger.info(staticClassName +".paintComponent(): Exiting method");
}
#Override
public Dimension getPreferredSize() {
logger.info(staticClassName +".getPreferredSize(): Entering method");
if (isPreferredSizeSet()) {
logger.info(staticClassName +".getPreferredSize(): isPreferredSizeSet() == true. Exiting method");
return super.getPreferredSize();
}
logger.info(staticClassName +".getPreferredSize(): isPreferredSizeSet() == false. Exiting method");
return new Dimension(WIDTH, HEIGHT);
}
}
Hole.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.logging.Logger;
import javax.swing.JPanel;
public class Hole extends JPanel {
private static final long serialVersionUID = 1235245435988434L;
private static String staticClassName = Hole.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private int holeNumber;
private int xPos, yPos;
private final int HOLEWIDTH = 20;
private final int HOLEHEIGHT = HOLEWIDTH;
private static final int RGB1 = 0;
private static final int RGB2 = 0;
private static final int RGB3 = 0;
private static Color defaultCircleColor = new Color(RGB1, RGB2, RGB3);
private static Color selectedCircleColor = Color.BLUE;
private static Color circleColor = defaultCircleColor;
private int [] adjacentHoles;
public Hole (int holeNumber, int xPos, int yPos, int [] adjacentHoles) {
logger.info(staticClassName +".Constructor: Constructing Hole");
this.holeNumber = holeNumber;
this.xPos = xPos;
this.yPos = yPos;
this.adjacentHoles = adjacentHoles;
initComponents();
}
#Override
protected void paintComponent(Graphics g) {
logger.info(staticClassName +".paintComponent(): Entering method");
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(circleColor);
g2.fillOval(xPos,yPos,HOLEWIDTH,HOLEHEIGHT);
logger.info(staticClassName +".paintComponent(): Exiting method");
}
private void initComponents() {
addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent event) {
selectHole(event);
}});
}
public void selectHole(java.awt.event.MouseEvent event) {
logger.info(staticClassName +"------------------------------------------------");
logger.info(staticClassName +".selectHole(): Entering method");
if (circleColor == defaultCircleColor) {
circleColor = selectedCircleColor;
repaint();
}
else {
circleColor = defaultCircleColor;
repaint();
}
logger.info(staticClassName +".selectHole(): Exiting method");
logger.info(staticClassName +"------------------------------------------------");
}
#Override
public Dimension getPreferredSize() {
logger.info(staticClassName +".getPreferredSize(): Getting the preferred size of the circle.");
return new Dimension(800, 800);
}
}
As a side note, if you notice that I could be using better coding practices anywhere in my code, please let me know.
So, your basic problem is right here...
for (int i = 0; i < 15; i ++ ) {
if (i == 0) {
// Declare the hole here
Hole hole = new Hole(i, xPos, yPos, adjacentHoles1);
// Render it here
hole.paintComponent(g2);
yPos += 50;
}
}
Hole is component, you should never call any paint method of component, but, you component is also not "live", meaning that it can never receive ANY events.
What you should do instead, is attach the MouseListener to the GameBoard and test if the mouse was clicked at a place there is a hole.
The simplest solution is to make use of the "shapes" API and generate a list of "holes". This can then be simply iterated over to paint and check to see if the mouse was clicked within it.
I've not gone to a great deal of effort in determining the location of the holes, instead I've just laid them out in rows/cols, but you should get the basic idea of the intended solution
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Display extends JPanel {
private static final long serialVersionUID = 1L;
private static String staticClassName = Display.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private final static Logger LOGGER = Logger.getLogger(staticClassName);
private static String title;
private static int width;
private static int height;
private static JFrame frame;
private static JPanel mainPanel;
private static GameBoard gameBoard;
public Display(String title, int width, int height) {
logger.info(staticClassName + ".Constructor: Constructing Display");
Display.title = title;
Display.width = width;
Display.height = height;
logger.info(staticClassName + ".Constructor: Display constructed.");
initDisplay();
}
private static void initDisplay() {
frame = new JFrame(title);
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
gameBoard = new GameBoard();
mainPanel.add(gameBoard);
frame.getContentPane().add(mainPanel);
frame.pack();
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
LOGGER.setLevel(Level.INFO);
Display d = new Display("Peg Game", 800, 800);
} catch (Exception e) {
}
}
});
}
public static class GameBoard extends JPanel {
private static final long serialVersionUID = 1L;
private static String staticClassName = GameBoard.class.getName();
private static Logger logger = Logger.getLogger(staticClassName);
private static final int RGB1 = 223;
private static final int RGB2 = 191;
private static final int RGB3 = 159;
private static final int WIDTH = 800;
private static final int HEIGHT = WIDTH;
private Path2D path = new Path2D.Double();
private static Color boardColor = new Color(RGB1, RGB2, RGB3);
private int[] adjacentHoles1;
private Shape[] holes;
private Shape selectedHole;
public GameBoard() {
logger.info(staticClassName + ".Constructor: Constructing GameBoard");
double firstX = (WIDTH / 2.0) * (1 - 1 / Math.sqrt(3));
double firstY = 3.0 * HEIGHT / 4.0;
path.moveTo(firstX, firstY);
path.lineTo(WIDTH - firstX, firstY);
path.lineTo(WIDTH / 2.0, HEIGHT / 4.0);
path.closePath();
logger.info(staticClassName + ".Constructor: GameBoard constructed");
holes = new Shape[15];
int yPos = 310;
int index = 0;
for (int row = 0; row < 3; row++) {
int xPos = 390;
for (int col = 0; col < 5; col++) {
holes[index] = new Ellipse2D.Double(xPos, yPos, 50, 50);
index++;
xPos += 50;
}
yPos += 50;
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
selectedHole = null;
for (Shape hole : holes) {
if (hole.contains(e.getPoint())) {
selectedHole = hole;
break;
}
}
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
logger.info(staticClassName + ".paintComponent(): Entering method");
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(boardColor);
g2.fill(path);
g2.setColor(Color.BLACK);
for (Shape hole : holes) {
g2.fill(hole);
}
if (selectedHole != null) {
g2.setColor(Color.RED);
g2.fill(selectedHole);
}
logger.info(staticClassName + ".paintComponent(): Exiting method");
}
#Override
public Dimension getPreferredSize() {
logger.info(staticClassName + ".getPreferredSize(): Entering method");
if (isPreferredSizeSet()) {
logger.info(staticClassName + ".getPreferredSize(): isPreferredSizeSet() == true. Exiting method");
return super.getPreferredSize();
}
logger.info(staticClassName + ".getPreferredSize(): isPreferredSizeSet() == false. Exiting method");
return new Dimension(WIDTH, HEIGHT);
}
}
}

increase height of a jlabel in positive y direction?

When i setSize of a jLabel, normally it grows towards bottom. How can i increase the height in positive y direction ?
After pressing init
Current Result
Expected result
My source code
private void initActionPerformed(java.awt.event.ActionEvent evt) {
int p = Integer.parseInt(abc[0].getText());
int q = Integer.parseInt(abc[1].getText());
int r = Integer.parseInt(abc[2].getText());
int s = Integer.parseInt(abc[3].getText());
int t = Integer.parseInt(abc[4].getText());
one.setSize(20, p*10 );
one.setBackground(Color.decode("#03A9F4"));
two.setSize(20, q*10 );
two.setBackground(Color.decode("#03A9F4"));
three.setSize(20, r*10 );
three.setBackground(Color.decode("#03A9F4"));
four.setSize(20, s*10 );
four.setBackground(Color.decode("#03A9F4"));
five.setSize(20, t*10 );
five.setBackground(Color.decode("#03A9F4"));
}
one,two,three are the label names.
abc is an array containing all the labels
You're finding out that Java considers positive y direction graphics to be down, which is in keeping with how computer monitors see y direction. Solutions include:
Figure out a maximum size, and subtract your y height from it to figure out where to start your JLabel.
Even better, don't use JLabels but draw within a JPanel's paintComponent, using the same calculations as above.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
#SuppressWarnings("serial")
public class GraphicsEg extends JPanel {
private static final int DATA_COLUMNS = 5;
private List<JSlider> sliders = new ArrayList<>();
private DrawPanel drawPanel = new DrawPanel(DATA_COLUMNS);
public GraphicsEg() {
JPanel sliderPanel = new JPanel(new GridLayout(1, 0, 5, 5));
SliderListener sliderListener = new SliderListener();
for (int i = 0; i < DATA_COLUMNS; i++) {
JSlider slider = new JSlider(0, 100, 50);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setPaintTrack(true);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
slider.setOrientation(SwingConstants.VERTICAL);
slider.addChangeListener(sliderListener);
sliders.add(slider);
sliderPanel.add(slider);
}
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(drawPanel, BorderLayout.CENTER);
add(sliderPanel, BorderLayout.PAGE_END);
sliderValuesIntoDrawPanel();
}
private void sliderValuesIntoDrawPanel() {
int[] data = new int[DATA_COLUMNS];
for (int i = 0; i < data.length; i++) {
data[i] = sliders.get(i).getValue();
}
drawPanel.setData(data);
}
private class SliderListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
sliderValuesIntoDrawPanel();
}
}
private static void createAndShowGui() {
GraphicsEg mainPanel = new GraphicsEg();
JFrame frame = new JFrame("GraphicsEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class DrawPanel extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = 400;
private static final int PAD = 20;
private static final Color BORDER_COLOR = Color.BLUE;
private static final Color COLUMN_COLOR = Color.RED;
private static final double RELATIVE_COL_WIDTH = 2.0 / 3.0;
private int dataColumns = 0;
private int[] data;
public DrawPanel(int dataColumns) {
this.dataColumns = dataColumns;
data = new int[dataColumns];
setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
}
public void setData(int[] data) {
this.data = data;
repaint();
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < data.length; i++) {
drawColumn(g, i, data[i]);
}
}
private void drawColumn(Graphics g, int index, int columnHeight) {
g.setColor(COLUMN_COLOR);
int width = (int) (RELATIVE_COL_WIDTH * (PREF_W - 2 * PAD) / dataColumns);
int x = PAD + (index * (PREF_W - 2 * PAD)) / dataColumns;
int height = (columnHeight * (PREF_H - 2 * PAD)) / 100;
int y = PREF_H - PAD - height;
g.fillRect(x, y, width, height);
}
}

Placement of a JPanel within a JPanel

I'm trying to code a simple Pong and I have the background panel which contains a Bar panel. So of course I need to be able to place the bar on the size and move it vertically at request. Now I'm just trying to put it in a starting position. If I don't disable the layout the bar gets placed in the top center regardless of location setting, but if I disable the layout and set location it just doesn't show up. I'm not sure what I missing. Here is a code snippet if it can be relevant:
public PongPanel() {
setLayout(null);
setPreferredSize(SIZE);
setBackground(Color.BLACK);
player_one_bar = new Bar();
add(player_one_bar);
player_one_bar.setLocation(10, getSize().height/2-3);
}
If you set the layout manager as null you'll have to specify the exact coordinates of the panel, meaning something like -
setBounds(10, 10, 20, 100);
Will put the panel at location (10,10) with Width of 20 and Height of 100.
If by "bar" you mean Pong game paddle, then it shouldn't be a component at all but rather a logical entity that represents a position, which is visually represented by a sprite that gets drawn in the JPanel's paintComponent method.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class PongPaddle extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 500;
private static final int RECT_X = 20;
private static final int RECT_W = 10;
private static final int RECT_H = 60;
private static final int STARTING_Y = (PREF_H - RECT_H) / 2;
private static final int TIMER_DELAY = 15;
private static final int DELTA_PADDLE = 3;
private boolean paddle1GoingDown = true;
private boolean paddle2GoingDown = false;
private Rectangle paddle1 = new Rectangle(RECT_X, STARTING_Y, RECT_W, RECT_H);
private Rectangle paddle2 = new Rectangle(PREF_W - RECT_X - RECT_W,
STARTING_Y, RECT_W, RECT_H);
public PongPaddle() {
setBackground(Color.black);
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int deltaPaddle1 = paddle1GoingDown ? 1 : -1;
deltaPaddle1 *= DELTA_PADDLE;
int x = paddle1.getLocation().x;
int y = paddle1.getLocation().y + deltaPaddle1;
if (y + RECT_H >= PREF_H) {
paddle1GoingDown = false;
}
if (y <= 0) {
paddle1GoingDown = true;
}
paddle1.setLocation(x, y);
int deltaPaddle2 = paddle2GoingDown ? 1 : -1;
deltaPaddle2 *= DELTA_PADDLE;
x = paddle2.getLocation().x;
y = paddle2.getLocation().y + deltaPaddle2;
if (y + RECT_H >= PREF_H) {
paddle2GoingDown = false;
}
if (y <= 0) {
paddle2GoingDown = true;
}
paddle2.setLocation(x, y);
repaint();
if (!PongPaddle.this.isShowing()) {
((Timer) e.getSource()).stop();
}
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.white);
if (paddle1 != null) {
g2.fill(paddle1);
}
if (paddle2 != null) {
g2.fill(paddle2);
}
}
private static void createAndShowGui() {
PongPaddle mainPanel = new PongPaddle();
JFrame frame = new JFrame("PongPaddle");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

How to make animation move its legs while moving?

So right now when you press go it just moves across the screen, but I also want it to move its legs so its doing something and not just standing still. Any tips on how to do that? I know it would be moving the 2nd leg pointers back and forth but I'm not sure how to do that
Class Stick2 :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Stick2 extends JFrame implements ActionListener {
// Declares constants
public static final int FRAME_WIDTH = 500;
private static final int FRAME_HEIGHT = 500;
private static final int FRAME_X_ORIGIN = 150;
private static final int FRAME_Y_ORIGIN = 200;
private static final int BUTTON_WIDTH =80;
private static final int BUTTON_HEIGHT = 30;
JPanel buttonPanel, panel;
MovingBanner2 myBanner;
JButton startButton, stopButton;
Thread thrd;
public static void main(String[] args)
{
Stick2 frame = new Stick2();
frame.setVisible(true);
}
public Stick2(){
Container contentPane= getContentPane();
// Sets Frame
setSize(FRAME_WIDTH,FRAME_HEIGHT);
setResizable(false);
setTitle("Animation");
setLocation(FRAME_X_ORIGIN, FRAME_Y_ORIGIN);
// Sets layout manager
contentPane.setLayout(new BorderLayout(10,0));
buttonPanel = new JPanel();
JButton startButton = new JButton("Start");
startButton.setSize(BUTTON_WIDTH, BUTTON_HEIGHT);
buttonPanel.add(startButton);
startButton.addActionListener(this);
JButton stopButton = new JButton("Stop");
stopButton.setSize(BUTTON_WIDTH,BUTTON_HEIGHT);
buttonPanel.add(stopButton);
stopButton.addActionListener(this);
contentPane.add (buttonPanel, BorderLayout.SOUTH);
// Creates a balloon
myBanner = new MovingBanner2();
panel = myBanner;
panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
contentPane.add(panel, BorderLayout.CENTER);
}
public void actionPerformed (ActionEvent event){
JButton clickedButton = (JButton) event.getSource();
String buttonText = clickedButton.getText();
if (buttonText.equals("Stop")) {
myBanner.stopAnimation();
thrd = null;
}
else {
myBanner.startAnimation();
thrd = new Thread (myBanner);
thrd.start();
}
}
}
Class MovingBanner2:
class MovingBanner2 extends JPanel implements Runnable {
private int x;
private Boolean animate;
int bodyX = 250;
int bodyY1 = 160;
int bodyY2 = 210;
int armHeight = 190;
int armLength = bodyX + 30;
int armLength1 = bodyX - 30;
int legY = 340;
public MovingBanner2() {
x=10;
animate = true;
}
// Draws the String
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
//g.drawString("I love Java", x,50);
g.drawLine(bodyX + x, bodyY1, bodyX + x, bodyY2); //body
g.drawOval(bodyX + x - 15, bodyY1 - 40, 40, 40); //head
g.drawLine(armLength + x,armHeight, armLength1 + x, armHeight); //arms
g.drawLine(bodyX + x, bodyY2, bodyX + 20 + x,legY); //leg
g.drawLine(bodyX + x, bodyY2, bodyX - 20 + x, legY); //leg
}
public void run() {
while (animate) {
changeX();
repaint();
try {Thread.sleep(100); } catch(Exception e){};
}
}
public void changeX() {
if (x <= Stick2.FRAME_WIDTH - 240)
x++;
else x = 10;
}
public void stopAnimation() {
animate = false;
}
public void startAnimation() {
animate = true;
}
}
There are probably many answers to the question. The best I can come up with is basically to devise some kind of "cycle".
A cycle is a known period of time over which animation can run. In this example, it's 1 second.
You then need to provide a series of Animatable objects that are notified of a change to the cycle over time, which allows them to make changes accordingly. You can also ignore the cycle for those elements that don't need to cycle.
The intention is provide a single animation engine that can be responsible for updating the entire state in one go, rather then trying to use multiple threads/timers which may reduce the systems performance.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestAnimation06 {
public static void main(String[] args) {
new TestAnimation06();
}
public TestAnimation06() {
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 interface Animatable {
public void update(float progress);
}
public class AnimationEngine {
private List<Animatable> animations;
private int cycleTime = 1000;
private long startTime = -1;
public AnimationEngine() {
animations = new ArrayList<>(25);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
}
long duration = System.currentTimeMillis() - startTime;
float progress = (float)duration / (float)cycleTime;
if (duration >= cycleTime) {
progress = 1f;
startTime = System.currentTimeMillis();
}
for (Animatable animatable : animations) {
animatable.update(progress);
}
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
public void add(Animatable animatable) {
animations.add(animatable);
}
}
public class TestPane extends JPanel {
private AnimationEngine engine;
public TestPane() {
setLayout(null);
engine = new AnimationEngine();
Legs legs = new Legs();
Walker walker = new Walker(legs);
engine.add(legs);
engine.add(walker);
walker.setSize(walker.getPreferredSize());
add(walker);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class Walker extends JPanel implements Animatable {
private int speed = 2;
public Walker(Legs legs) {
setLayout(new GridBagLayout());
add(legs);
}
#Override
public void update(float progress) {
Container parent = getParent();
int width = parent.getWidth();
int xPos = getX() + speed;
if (xPos <= 0) {
speed *= -1;
xPos = 0;
} else if (xPos + getWidth() >= width) {
speed *= -1;
xPos = width - getWidth();
}
System.out.println(xPos);
setLocation(xPos, (parent.getHeight() - getHeight()) / 2);
repaint();
}
}
public class Legs extends JPanel implements Animatable {
private float frameProgress;
public Legs() {
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(25, 50);
}
#Override
public void update(float progress) {
frameProgress = progress;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
g.setColor(Color.BLACK);
g.drawLine(width / 2, 0, (int)(width * frameProgress), height);
g.drawLine(width / 2, 0, width - (int)(width * frameProgress), height);
}
}
}

Rotate rectangle and move it in sin wave - Help using graphics2D

Hi!
I have the code below using previous Stackoverflow posts.
I want to just rotate the rectangle by some angle and make it move in sin wave.
This code rotates the whole sin wave too.
I understand why it is happening , but I don't know how to achieve my intention.
please help!!!
Thanks a lot for taking time.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Withrotation {
public static int i = 1;
public static Ticker t;
public static Repainter r;
public static int newx, newy;
public static void main(String[] args) {
final JFrame frame = new JFrame("Wavy!");
final WavyPanel wp = new WavyPanel();
frame.getContentPane().add(wp, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t = new Ticker(wp);
r = new Repainter(wp);
frame.pack();
frame.setVisible(true);
final Timer tickTimer = new Timer();
final Timer paintTimer = new Timer();
paintTimer.schedule(r, 1000, 50);
tickTimer.schedule(t, 1000, 10);
}
private static class WavyPanel extends JPanel {
private final Dimension size = new Dimension(640, 480);
private int amplitude = 50;
private int frequency = 5;
private double x1 = 0;
private double y1 = 500;
private int yBase = 0;
WavyPanel() {
super(true);
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2 = (Graphics2D) g;
AffineTransform old = g2.getTransform();
g2.rotate(Math.toRadians(-30));
g2.clearRect(0, 0, this.getSize().width, this.getSize().height);
g2.setColor(Color.BLACK);
g2.fillRect((int) x1, (int) y1, 20, 80);
g2.setTransform(old);
}
#Override
public Dimension getPreferredSize() {
return size;
}
#Override
public Dimension getMinimumSize() {
return size;
}
#Override
public Dimension getMaximumSize() {
return size;
}
public void tick() {
x1 = x1 + 1;
final int waveLength = size.width / frequency;
yBase = (++yBase) % waveLength;
final double normalized = (double) yBase / (double) waveLength;
final double radians = normalized * Math.PI * 2;
final double sine = Math.sin(radians);
y1 = (int) (sine * amplitude);
}
}
private static class Ticker extends TimerTask {
private final WavyPanel panel;
Ticker(final WavyPanel panel) {
this.panel = panel;
}
#Override
public void run() {
panel.tick();
}
}
private static class Repainter extends TimerTask {
private final WavyPanel panel;
Repainter(final WavyPanel panel) {
this.panel = panel;
}
#Override
public void run() {
panel.repaint();
}
}
}
+1 for SSCCE
1) Dont forget to have call to super.paintComponent(); as first statement in your overridden paintComponent(..) method.
2) Swing UI should be created on EDT and used in conjunction with Swing Timers
3) Java variable naming convention for classes is uppercase letter for each new word i.e WithRotation.
4) No need for frame.getContentPane.add(..) simply use add(..) as all calls are forwarded to its contentPane.
Here is the example I made (basically your code with above fixes implemented), which only rotates the rectangle which follows the graph and not the whole graphics object using AffineTransform#createTransformedShape():
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class WithRotation {
private JFrame frame;
private WavyPanel wp;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new WithRotation();
}
});
}
public WithRotation() {
initComponents();
}
private void initComponents() {
frame = new JFrame("Wavy!");
wp = new WavyPanel();
frame.add(wp, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
createAndStartTimers();
}
private void createAndStartTimers() {
new Timer(50, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
wp.repaint();
}
}).start();
new Timer(10, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
wp.tick();
}
}).start();
}
class WavyPanel extends JPanel {
private final Dimension size = new Dimension(640, 480);
private int amplitude = 50;
private int frequency = 5;
private double x1 = 0;
private double y1 = 500;
private int yBase = 0;
WavyPanel() {
super(true);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.clearRect(0, 0, this.getSize().width, this.getSize().height);
g2.setColor(Color.BLACK);
Rectangle rect = new Rectangle((int) x1, (int) y1, 20, 80);
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(-30), rect.getX() + rect.width / 2, rect.getY() + rect.height / 2);
Shape transformed = transform.createTransformedShape(rect);
g2.fill(transformed);
}
#Override
public Dimension getPreferredSize() {
return size;
}
#Override
public Dimension getMinimumSize() {
return size;
}
#Override
public Dimension getMaximumSize() {
return size;
}
public void tick() {
x1 = x1 + 1;
final int waveLength = size.width / frequency;
yBase = (++yBase) % waveLength;
final double normalized = (double) yBase / (double) waveLength;
final double radians = normalized * Math.PI * 2;
final double sine = Math.sin(radians);
y1 = (int) (sine * amplitude);
}
}
}

Categories

Resources