我在 Jpanel 中显示已添加到 Jframe 的自定义 Jbutton 对象的移动时遇到问题。 图表已显示,但当调用 startMovement 方法时,图表在 Jpanel 下消失。
我已经和这个问题斗争了好几天了,但还是无法解决。
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);
});
}
}
我想要显示纸张运动
您的问题在这里:
您首先重写 JButton
public class MovingButton extends JButton implements ActionListener {
并为其指定 x 和 y 字段。请注意,如果稍后您提供类
public int getX()
和 getY()
方法,这本身就可能很危险,因为这些方法将覆盖用于放置组件的关键 Swing 组件方法。我已经被这个烧伤了。
private int x;
private int y;
在 Swing Timer 的 ActionListener 中,您推进 x 和 y 值并调用
repaint()
all 来帮助为该组件绘制的图像的运动设置动画:
@Override
public void actionPerformed(ActionEvent e) {
//Effetto movimento
if (e.getSource().equals(timerMovimento)) {
//...
x += deltaX;
y += deltaY;
myPanel.repaint();
}
repaint();
}
在 PaintComponent 方法中,您绘制图像,由 x 和 y 保存的值转换:
@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();
}
但是请注意,x 和 y 是相对于这个组件本身(这个 JButton)的。因此,当您绘制 10 像素 x 10 像素的图像时,无论该组件位于何处,它都会显示图像相对于自身移动了 10 x 10 像素,而这不是您想要的。
相反,您想要在 0, 0 相对于组件本身处绘制图像,并平移组件在容器中的位置,即按钮的位置。
我自己,如果我要做这种动画,我只需移动图像并使其不扩展组件。
位于 imgs 目录中,该目录是此类文件所在的子目录,我可以执行以下操作:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
class MyPanel02 extends JPanel {
private static final int TIMER_DELAY = 20;
private static final int DELTA = 3;
private static final int PANEL_WIDTH = 1200;
private static final int PANEL_HEIGHT = 800;
private BufferedImage backgroundImage;
private BufferedImage frontCardImage;
private BufferedImage pressedCardImage;
private int cardX = 0;
private int cardY = 0;
private Timer animationTimer = new Timer(TIMER_DELAY, e -> timerAxnPerformed());
private Shape shape;
private boolean isPressed = false;
public MyPanel02(String imagePath) {
addComponentListener(new MyComponentAdapter());
try {
URL cardUrl = getClass().getResource(imagePath);
frontCardImage = ImageIO.read(cardUrl);
int newW = frontCardImage.getWidth();
int newH = frontCardImage.getHeight();
// create pressed card image for when the mouse button is pressed over the card
pressedCardImage = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = pressedCardImage.createGraphics();
g2d.drawImage(frontCardImage, 0, 0, null);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, newW, newH);
g2d.dispose();
shape = new Rectangle(0, 0, newW, newH);
} catch (IOException e) {
e.printStackTrace();
}
animationTimer.start();
addMouseListener(new MyMouseAdapter());
}
private class MyComponentAdapter extends ComponentAdapter {
@Override
public void componentResized(ComponentEvent e) {
backgroundImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = backgroundImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(new GradientPaint(0, 0, Color.RED, getWidth(), getHeight(), Color.YELLOW));
g2.fillRect(0, 0, getWidth(), getHeight());
g2.dispose();
}
}
@Override // get preferred size of the panel
public Dimension getPreferredSize() {
return new Dimension(PANEL_WIDTH, PANEL_HEIGHT);
}
private void timerAxnPerformed() {
cardX += DELTA;
cardY += DELTA;
if (cardX > getWidth() || cardY > getHeight()) {
cardX = 0;
cardY = 0;
}
shape = new Rectangle(cardX, cardY, shape.getBounds().width, shape.getBounds().height);
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImage != null) {
g.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);
}
if (frontCardImage != null && !isPressed) {
g.drawImage(frontCardImage, cardX, cardY, this);
}
if (pressedCardImage != null && isPressed) {
g.drawImage(pressedCardImage, cardX, cardY, this);
}
}
private class MyMouseAdapter extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (shape.contains(e.getPoint())) {
if (animationTimer.isRunning()) {
animationTimer.stop();
}
isPressed = true;
repaint();
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (!isPressed) {
return;
}
isPressed = false;
repaint();
if (!animationTimer.isRunning()) {
animationTimer.start();
}
}
}
}
public class MovingBtnMain {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
MyPanel02 myPanel = new MyPanel02("imgs/PlayingCard.jpg");
frame.add(myPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}