在 Java Swing 中移动对象的问题

问题描述 投票:0回答:1

我在 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);

        });
    }

}


我想要显示纸张运动

java swing jframe jpanel jbutton
1个回答
0
投票

您的问题在这里:

您首先重写 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);

            }
        });
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.