I'm having trouble displaying the movement of a custom Jbutton object in Jpanel that has been added to the Jframe. The chart is displayed but when the startMovement method is called the chart disappears under the Jpanel.
I've been fighting it for days but I can't resolve it.
public class MyPanel extends JPanel {
private BufferedImage backgroundImage;
public MyPanel(String imagePath) {
try {
backgroundImage = ImageIO.read(new File(imagePath));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImage != null) {
g.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);
}
}
}
import view.MyPanel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class MovingButton extends JButton implements ActionListener {
private String cartaVisualizzataPath;
private String retroCartaVisualizzataPath;
private int x;
private int y;
private int deltaX;
private int deltaY;
private Timer timerMovimento;
private Timer timerRotazione;
private int finalx;
private int finaly;
private BufferedImage frontCardImage;
private BufferedImage backCardImage;
private boolean revealing = false;
private double scaleX = 1.0;
static JFrame frame = new JFrame();
static MyPanel myPanel = new MyPanel("/Users/andrea/Il mio Drive/Università/- Metodologie di programmazione/BackGround_Resized.png");
public MovingButton(int x, int y, String cartaVisualizzataPath, String retroCartaVisualizzataPath) {
this.x = x;
this.y = y;
this.cartaVisualizzataPath = cartaVisualizzataPath;
this.retroCartaVisualizzataPath = retroCartaVisualizzataPath;
timerMovimento = new Timer(10, this);
timerRotazione = new Timer(10, this);
// Caricamento dell'immagine dal percorso specificato
try {
frontCardImage = ImageIO.read(new File(this.cartaVisualizzataPath));
backCardImage = ImageIO.read(new File(this.retroCartaVisualizzataPath));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void actionPerformed(ActionEvent e) {
//Effetto movimento
if (e.getSource().equals(timerMovimento)) {
System.out.println("Sono qui");
System.out.println("x: " + x);
System.out.println("y: " + x);
if (x == finalx && y == finaly) {
timerMovimento.stop();
System.out.println("Terminato movimento");
}
if (x == finalx)
deltaX = 0;
if (y == finaly)
deltaY = 0;
x += deltaX;
y += deltaY;
myPanel.repaint();
}
//Effetto rotazione
if (e.getSource().equals(timerRotazione)) {
// Aggiorna l'effetto di girata della carta
scaleX -= 0.01; // Modifica questo valore per regolare la velocità di girata
if (scaleX <= 0 && !revealing) {
scaleX = 0;
revealing = true; // Inizia a rivelare la carta sottostante
timerRotazione.setDelay(20); // Riduci la velocità di rivelazione
} else if (scaleX <= -1.0 && revealing) {
scaleX = -1.0;
timerRotazione.stop(); // Ferma il timer quando la carta è completamente rivelata
}
// Ridisegna il pannello
myPanel.repaint();
}
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int centerX = x + frontCardImage.getWidth() / 2;
int centerY = y + frontCardImage.getHeight() / 2;
// Disegna la carta frontale (superiore)
Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(centerX, centerY);
g2d.scale(scaleX, 1.0); // Scala sull'asse X
if (!revealing)
g2d.drawImage(frontCardImage, -frontCardImage.getWidth(null) / 2, -frontCardImage.getHeight(null) / 2, null);
else
g2d.drawImage(backCardImage, frontCardImage.getWidth(null) / 2, -backCardImage.getHeight(null) / 2, -backCardImage.getWidth(null), backCardImage.getHeight(null), null);
g2d.dispose();
}
public void avviaMovimento(int finalx, int finaly, int deltaX, int deltaY) {
this.finalx = finalx;
this.finaly = finaly;
this.deltaX = deltaX;
this.deltaY = deltaY;
timerMovimento.start();
}
public void avviaRotazione() {
this.timerRotazione.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
String frontCardPath = "/Users/andrea/Il mio Drive/Università/- Metodologie di programmazione/iloveimg-resized/CartaCoperta.png";
String backCardPath = "/Users/andrea/Il mio Drive/Università/- Metodologie di programmazione/iloveimg-resized/CuoriAsso.png";
// frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(new Dimension(1440, 900)); // Imposta le dimensioni della finestra
frame.setLayout(new BorderLayout());
// myPanel = new MyPanel("/Users/andrea/Il mio Drive/Università/- Metodologie di programmazione/BackGround_Resized.png");
myPanel.setSize(new Dimension(800,800));
myPanel.setLayout(null);
MovingButton button = new MovingButton(0,0, backCardPath, backCardPath);
button.setBounds(0,0,77, 88);
myPanel.add(button);
frame.add(new JButton("Ciao"), BorderLayout.NORTH);
frame.add(myPanel, BorderLayout.CENTER);
frame.add(new JButton("Ciao"), BorderLayout.SOUTH);
frame.add(new JButton("Ciao"), BorderLayout.LINE_START);
frame.add(new JButton("Ciao"), BorderLayout.LINE_END);
frame.setVisible(true); // Rendi la finestra visibile
button.avviaMovimento(400,400,1,1);
});
}
}
I would like the paper movement to be displayed
Your problems are here:
You first override a JButton
and give it an x and y fields. Note that this could itself can be dangerous if later you give the class
public int getX()andgetY()methods, since these would override key Swing component methods for placement of a component. I've been burned on this.In your Swing Timer's ActionListener, you advance the x and y values and call
repaint()all to help animate the movement of the image that this component paints:And in the paintComponent method you draw the image, translated by the values held by x and y:
But note that x and y are relative to this component itself, this JButton. And so when you draw the image 10 pixels by 10 pixels, then no matter where this component is located, it will show the image moved relative to itself by 10 x 10 pixels, and this is not what you want.
So, while the button may originally look like this:

as it animates, the image will start moving off of the button,
and then...

Instead, you want to draw the image at 0, 0 relative to the component itself, and translate the location of the component in the container, the location of the button.
Myself, if I were doing this sort of animation however, I'd just move an image and make it not extend a component.
For example, using this image:

located in a imgs directory that is a subdirectory of where this class file is located, I could do something like:
Which could look like this: