简体   繁体   中英

Making a shape move back and forth using EventHandlers in Java

I think my title pretty well sums up my problem. I'm really new to programming (about 2-3 weeks of self teaching using Head First Java) and I am trying to use Action Listener to make a square move back and forth on screen until the user terminates the program. My issue is that I have one Timer and 2 classes implementing Action Listener. I can get it to run back and forth once, but that's all I can get it to do.

package Animation;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class Window extends JPanel implements ActionListener{
int x = 100;
Timer timer = new Timer(5, this);
int velX = 2;

public void paintComponent(Graphics  g){
    super.paintComponent(g);
    this.setBackground(Color.BLACK);
    g.setColor(Color.BLUE);
    g.fill3DRect(x, 150, 200, 200, true);
    timer.start();
    if(x >= 1000){
        timer.addActionListener(new HandlerClass());
            }//end if

    }//end paintComponent

public void actionPerformed(ActionEvent e){
    x += velX;
    repaint();
}//end actionP method

public class HandlerClass implements ActionListener{
    @Override
    public void actionPerformed(ActionEvent e) {
        if(x >= 100){
        x -= velX;
        repaint();
        }
    }//end actionP
}//end Handler

}//end Window

I've seen questions where people use buttons to move things back and forth or move things a set number of times, but I want the timer to do everything till the user exits. That way the user only has to watch. I Didn't include the class with my main method because that just sets up the gui and calls this class.

First, take a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing.

Basically, Swing uses a passive rendering algorithm, this means that a paint cycle may occur at any time for any reason, most of the time without your direct intervention.

You should never change the state of a component from within any paint method, paint methods should paint, that's it.

There are a number of small problems, to start with, you are adding the Window class AND the HandlerClass as ActionListener 's to the Timer , this means that you could potentially get into a position where these two listeners compete with each other over which way the object should move. Better to place your movement logic into a single method, for example:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Window extends JPanel {

    int x = 100;
    Timer timer = new Timer(5, new HandlerClass());
    int velX = 2;

    public Window() {
        this.setBackground(Color.BLACK);
        timer.start();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 400);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLUE);
        g.fill3DRect(x, 150, 200, 200, true);

    }//end paintComponent

    public class HandlerClass implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            x += velX;
            if (x + 200 >= getWidth()) {
                x = getWidth() - 200;
                velX *= -1;
            } else if (x < 0) {
                x = 0;
                velX *= -1;
            }
            repaint();
        }//end actionP
    }//end Handler

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new Window());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}//end Window

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM