0

I am learning java for like 3 months already, and this is my second project in swing. My problem now is that I don't know how to make a JButton move some image by redrawing it, to make it look like a motion movement, so far everything I could do is make it move while hovering on the button, or when I keep it pressed, but the motion doesn't happen just when I click the button. Basically the button is supposed to be part of an elevator console, which by clicking on it makes the elevator move to the specified floor. Lemme know if u have an idea, or if it is possible at all to do what I am looking for. Maybe this whole thing has to be done in a completely different manner, I am open to suggestions and I appreciate the help.

Many thanks, and kind regards!


Things I tried:

◘ JButton.getModel().isArmed();

◘ JButton.getModel().isRollOver();

◘ JButton.getModel().isClicked();

◘ while loop(it made the elvator teleport directly) - in button's action listener and in the method:

JButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
while(yPosition!=300){
yPosition = yPosition - yVelocity;
repaint();
}
}
} );

◘ for loop - as in the button's action listener and in the method:

floor1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for(int i = 500; i <= 300; i--){

yPosition = yPosition - yVelocity;
repaint();
}
}
} );

/////////////////////////////////////////////////////////////////////////

Actual code(there is a separate frame class where this panel is added to):

// MainClass

public class Main {
    public static void main(String[] args) {

        new Frame();
    }
}

// FrameClass
import javax.swing.*;

public class Frame extends JFrame {

    Frame(){
    ElevatorPanel elevatorPanel = new ElevatorPanel();

        this.setSize(elevatorPanel.PANEL_WIDTH, elevatorPanel.PANEL_HEIGHT);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.add(elevatorPanel);
        this.setVisible(true);

    }

}

// PanelClass

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class ElevatorPanel extends JPanel implements ActionListener {
    /*final int r = 1;
    final int g = 100;
    final int b = 100;
    final int a = 100;
     */
    final int PANEL_HEIGHT = 800;
    final int PANEL_WIDTH = 800;
    final int BUTTON_HEIGHT = 40;
    final int BUTTON_WIDTH = 130;
    int xVelocity = 1;
    int yVelocity = 1;
    int xPosition = 120;
    int yPosition = 500;
    Image elevator;
    JButton groundLvl = new JButton();
    JButton floor1 = new JButton();
    JButton floor2 = new JButton();


    ElevatorPanel() {
        Timer time = new Timer(20, this);
        time.start();

        elevator = new ImageIcon("Elevator\\Resources\\elevator.png").getImage();

        groundLvl.setBounds(500, 550, BUTTON_WIDTH, BUTTON_HEIGHT);
        groundLvl.setText("Ground level");
        groundLvl.setFocusable(false);

        floor1.setBounds(500, 500, BUTTON_WIDTH, BUTTON_HEIGHT);
        floor1.setText("1st Floor");
        floor1.setFocusable(false);
        floor1.addActionListener(this);
        /*floor1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                for(int i = 500; i <= 300; i--){

                    yPosition = yPosition - yVelocity;
                    repaint();

                }

            }
        } );
         */

        floor2.setBounds(500, 450, BUTTON_WIDTH, BUTTON_HEIGHT);
        floor2.setText("2nd Floor");
        floor2.setFocusable(false);

        this.add(groundLvl);
        this.add(floor1);
        this.add(floor2);
        this.setOpaque(false);
        this.setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
        this.setLayout(null);
    }
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2D = (Graphics2D) g;
        //g2D.drawImage(bg,0,0,null);
        g2D.drawImage(elevator, xPosition, yPosition, null);

    }

    @Override
    public void actionPerformed(ActionEvent ex) {
        if (ex.getSource() == floor1) {

            yPosition = yPosition - yVelocity;
            repaint();

        }
    }
}

Demo User
  • 11
  • 2
  • can you share your runing code – DEV Oct 15 '22 at 19:55
  • [Avoid null layouts in Swing](https://technojeeves.com/index.php/aliasjava1/114-avoid-null-layouts-in-swing) Also, in ```JPanel``` you need to override ```paintComponent``` – g00se Oct 15 '22 at 20:54
  • Updated the post with the entire code, it is structured in 3 classes. Apologies if it's more annoying to work with like this. – Demo User Oct 15 '22 at 21:45
  • Your ActionListener code is wrong. If you want animation, you can't use a loop since the GUI will not repaint itself until the entire loop is finished. Instead, you need to schedule the animation by using a `Swing Timer`. When the Timer fires you change the position of the image and repaint. Check out: https://stackoverflow.com/questions/54028090/get-width-and-height-of-jpanel-outside-of-the-class/54028681#54028681 for an example of using a Timer to animate the motion of objects. – camickr Oct 15 '22 at 21:46
  • 1
    Just looked more closely at your added code and I don't understand what you are doing. You have loops and a Timer. Again, you don't need the loop, only the Timer. Take the time to understand the code from the above link. Note, your class should NOT implement ActionListener. Your class needs an ActionListener for the buttons and for the Timer, so you should be using either anonymous inner classes or lambdas for the listeners. Then when you click the button, you start the Timer. When the Timer fires you change the y offset. – camickr Oct 15 '22 at 21:56
  • 2
    I'd start by looking at [The Event Dispatch Thread](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) for reasons why this approach isn't going to work and then look at [How to Use Swing Timers](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) for a possible solution – MadProgrammer Oct 15 '22 at 22:49
  • Oh, so my approach was completely wrong. I did not know I can do such things with the Java timer, since I am self learning java and I figure myself how deep I go into each class that java has. Very useful information, this is definitely gonna help me . FYI - The loops at the top are just to show my ways of trying to do the motion of the image, they are not in the actual code, each of them were at some point, tho :D – Demo User Oct 16 '22 at 09:54

0 Answers0