Java代码中的计时器问题

Java代码中的计时器问题,java,graphics,timer,actionlistener,paintcomponent,Java,Graphics,Timer,Actionlistener,Paintcomponent,对于家庭作业,我必须制作一个程序,在这个程序中,一个窗口用三个按钮打开:Drop、Retrieve和Quit。按下drop(下降)按钮时,一个圆圈从显示面板的顶部下降到底部并停留在那里。当按下Retrieve(检索)按钮时,一条线应沿屏幕向下落至圆圈,并目视将圆圈拉回到屏幕顶部 我写了几乎所有我无法让线回到屏幕上的东西,在我的代码中,只有球做了,线保持在那里 import java.awt.*; import javax.swing.*; public class DisplayWindow

对于家庭作业,我必须制作一个程序,在这个程序中,一个窗口用三个按钮打开:Drop、Retrieve和Quit。按下drop(下降)按钮时,一个圆圈从显示面板的顶部下降到底部并停留在那里。当按下Retrieve(检索)按钮时,一条线应沿屏幕向下落至圆圈,并目视将圆圈拉回到屏幕顶部

我写了几乎所有我无法让线回到屏幕上的东西,在我的代码中,只有球做了,线保持在那里

import java.awt.*;
import javax.swing.*;

public class DisplayWindow extends JFrame {
    private Container c;

    public DisplayWindow() {
        super("Display");
        c = this.getContentPane();
    }

    public void addPanel(JPanel p) {
        c.add(p);
    }

    public void showFrame() {
        this.pack();
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
我的代码:

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

public class DropPanel extends JPanel implements ActionListener{  
    Timer ticker1= new Timer(20,this);
    int x=150; 
    int y=0;
    Timer ticker2= new Timer(20,this);
    int x2=175; 
    int y2=0;
    JButton drop=new JButton("Drop");
    JButton retrieve=new JButton("Retrieve");
    JButton quit=new JButton("Quit");

    public DropPanel(){
        setPreferredSize(new Dimension(300,600));    
        this.add(drop); drop.addActionListener(this);
        this.add(retrieve); retrieve.addActionListener(this);
        this.add(quit); quit.addActionListener(this);
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);      
        g.drawOval(x,y,50,50);
        g.drawLine(x2,0,x2,y2);
    }

    public void actionPerformed (ActionEvent e){
        if(e.getSource() == ticker1){
            if (y<550) 
                y=y+2;
        }

        if(e.getSource() == drop){
            ticker1.start();
        }         

        if(e.getSource()== ticker2){
            if (y2<550){
                y2=y2+2;
            }
            if (y2==550) {
                ticker1.stop(); 
                y=y-2; 
                y2=y2-2; 
            } 
        }

        if(e.getSource() == retrieve){
            ticker2.start();
            if(y2==550){
                y2=y2-2;
            }
        } 

        if(e.getSource()==quit){
            System.exit(0);
        }        
        repaint();
    }
}

代码的格式使其难以阅读,但我认为我发现了错误:

if(e.getSource()== ticker2) {
  if (y2<550) {
    y2=y2+2;
  }

  if (y2==550) {
    ticker1.stop(); 
    y=y-2; 
    y2=y2-2; 
  } 
}
if(例如getSource()==ticker2){

如果(y2从分离责任区域开始。试图将所有“行动”逻辑混合到一个方法中不仅是糟糕的设计,还会给你带来很多混乱

每个计时器都应该有自己的
ActionListener
。这意味着您可以单独隔离逻辑并专注于自己的工作单元,而不必不必要地混合其他对象的状态

例如

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DropBall {

    public static void main(String[] args) {
        new DropBall();
    }

    public DropBall() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

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

    public class TestPane extends JPanel {

        private JButton dropButton;
        private JButton retrieveButton;
        private AnimationPane animationPane;

        public TestPane() {
            setLayout(new BorderLayout());

            animationPane = new AnimationPane();
            add(animationPane);

            dropButton = new JButton("Drop");
            dropButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (animationPane.canDrop()) {
                        animationPane.drop();
                    }
                }
            });
            retrieveButton = new JButton("Retrieve");
            retrieveButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (animationPane.canRetrieve()) {
                        animationPane.retrieve();
                    }
                }
            });

            JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.CENTER));
            buttonPane.add(dropButton);
            buttonPane.add(retrieveButton);

            add(buttonPane, BorderLayout.SOUTH);
        }
    }

    public static class AnimationPane extends JPanel {

        protected static final int RUN_TIME = 1000;
        private Timer dropTimer;
        private Timer retrieveTimer;
        private Ellipse2D ball;
        private long startTime = -1;
        private Point ballPoint;
        private Point linePoint;

        public AnimationPane() {
            ball = new Ellipse2D.Float(0, 0, 10, 10);

            dropTimer = new Timer(30, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    long duration = System.currentTimeMillis() - startTime;
                    float progress = (float) duration / (float) RUN_TIME;

                    if (progress > 1f) {
                        progress = 1f;
                        ((Timer) e.getSource()).stop();
                    }

                    ballPoint = new Point();
                    ballPoint.x = getWidth() / 2;
                    ballPoint.y = Math.round(getHeight() * progress);

                    repaint();
                }
            });
            dropTimer.setRepeats(true);
            dropTimer.setCoalesce(true);
            dropTimer.setInitialDelay(0);

            retrieveTimer = new Timer(30, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    long duration = System.currentTimeMillis() - startTime;
                    float progress = (float) duration / (float) RUN_TIME;

                    linePoint = new Point();
                    linePoint.x = getWidth() / 2;

                    if (progress < 0.5f) {
                        linePoint.y = Math.round(getHeight() * (progress * 2));
                    } else {
                        if (progress > 1f) {
                            progress = 1f;
                            ((Timer) e.getSource()).stop();
                            linePoint = null;
                            ballPoint = null;
                        } else {
                            linePoint.y = Math.round(getHeight() * (progress * 2));
                            linePoint.y = getHeight() - (linePoint.y - getHeight());

                            ballPoint.y = linePoint.y;
                        }
                    }

                    repaint();
                }
            });
            retrieveTimer.setRepeats(true);
            retrieveTimer.setCoalesce(true);
            retrieveTimer.setInitialDelay(0);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (ballPoint != null) {

                int x = (int) (ballPoint.x - (ball.getWidth() / 2));
                int y = (int) (ballPoint.y - ball.getHeight());

                g2d.translate(x, y);
                g2d.draw(ball);
                g2d.translate(-x, -y);

            }
            if (linePoint != null) {
                int x = getWidth() / 2;
                int y = 0;

                g2d.drawLine(x, y, linePoint.x, linePoint.y);
            }
            g2d.dispose();
        }

        public boolean canDrop() {
            return !dropTimer.isRunning() && !retrieveTimer.isRunning() && ballPoint == null;
        }

        public boolean canRetrieve() {
            return !dropTimer.isRunning() && !retrieveTimer.isRunning() && ballPoint != null;
        }

        public void drop() {
            startTime = System.currentTimeMillis();
            dropTimer.start();
        }

        public void retrieve() {
            startTime = System.currentTimeMillis();
            retrieveTimer.start();
        }
    }
}
导入java.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.FlowLayout;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Point;
导入java.awt.Rectangle;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.geom.Ellipse2D;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.Timer;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公共级吊球{
公共静态void main(字符串[]args){
新落球();
}
公共投球{
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(新的BorderLayout());
frame.add(newtestpane());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
公共类TestPane扩展了JPanel{
私有JButton下拉按钮;
私有JButton检索按钮;
私有动画窗格动画窗格;
公共测试窗格(){
setLayout(新的BorderLayout());
animationPane=新建animationPane();
添加(动画窗格);
dropButton=新按钮(“Drop”);
addActionListener(新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
if(animationPane.canDrop()){
animationPane.drop();
}
}
});
retrieveButton=新的JButton(“Retrieve”);
retrieveButton.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
if(animationPane.canRetrieve()){
animationPane.retrieve();
}
}
});
JPanel buttonPane=newjpanel(newflowlayout(FlowLayout.CENTER));
按钮平面。添加(dropButton);
按钮平面。添加(检索按钮);
添加(按钮平面,边界布局。南部);
}
}
公共静态类AnimationPane扩展了JPanel{
受保护静态最终整数运行时间=1000;
私人定时器;
私人定时器检索定时器;
私人椭圆球;
私有长startTime=-1;
私人圆珠笔;
专用点线点;
公共动画窗格(){
ball=新的椭圆2d.浮动(0,0,10,10);
dropTimer=新计时器(30,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
长持续时间=System.currentTimeMillis()-startTime;
浮动进度=(浮动)持续时间/(浮动)运行时间;
如果(进度>1f){
进度=1f;
((计时器)e.getSource()).stop();
}
圆珠笔=新点();
ballPoint.x=getWidth()/2;
ballPoint.y=Math.round(getHeight()*进度);
重新油漆();
}
});
dropTimer.setRepeats(真);
dropTimer.setCoalesce(真);
dropTimer.setInitialDelay(0);
retrieveTimer=新计时器(30,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
长持续时间=System.currentTimeMillis()-startTime;
浮动进度=(浮动)持续时间/(浮动)运行时间;
linePoint=新点();
linePoint.x=getWidth()/2;
如果(进度<0.5f){
linePoint.y=Math.round(getHeight()*(progress*2));
}否则{
如果(进度>1f){
进度=1f;
((计时器)e.getSource()).stop();
linePoint=null;
圆珠笔=零;
}否则{
linePoint.y=Math.round(getHeight()*(progress*2));
linePoint.y=getHeight()-(linePoint.y-getHeight());
B
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DropBall {

    public static void main(String[] args) {
        new DropBall();
    }

    public DropBall() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

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

    public class TestPane extends JPanel {

        private JButton dropButton;
        private JButton retrieveButton;
        private AnimationPane animationPane;

        public TestPane() {
            setLayout(new BorderLayout());

            animationPane = new AnimationPane();
            add(animationPane);

            dropButton = new JButton("Drop");
            dropButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (animationPane.canDrop()) {
                        animationPane.drop();
                    }
                }
            });
            retrieveButton = new JButton("Retrieve");
            retrieveButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (animationPane.canRetrieve()) {
                        animationPane.retrieve();
                    }
                }
            });

            JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.CENTER));
            buttonPane.add(dropButton);
            buttonPane.add(retrieveButton);

            add(buttonPane, BorderLayout.SOUTH);
        }
    }

    public static class AnimationPane extends JPanel {

        protected static final int RUN_TIME = 1000;
        private Timer dropTimer;
        private Timer retrieveTimer;
        private Ellipse2D ball;
        private long startTime = -1;
        private Point ballPoint;
        private Point linePoint;

        public AnimationPane() {
            ball = new Ellipse2D.Float(0, 0, 10, 10);

            dropTimer = new Timer(30, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    long duration = System.currentTimeMillis() - startTime;
                    float progress = (float) duration / (float) RUN_TIME;

                    if (progress > 1f) {
                        progress = 1f;
                        ((Timer) e.getSource()).stop();
                    }

                    ballPoint = new Point();
                    ballPoint.x = getWidth() / 2;
                    ballPoint.y = Math.round(getHeight() * progress);

                    repaint();
                }
            });
            dropTimer.setRepeats(true);
            dropTimer.setCoalesce(true);
            dropTimer.setInitialDelay(0);

            retrieveTimer = new Timer(30, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    long duration = System.currentTimeMillis() - startTime;
                    float progress = (float) duration / (float) RUN_TIME;

                    linePoint = new Point();
                    linePoint.x = getWidth() / 2;

                    if (progress < 0.5f) {
                        linePoint.y = Math.round(getHeight() * (progress * 2));
                    } else {
                        if (progress > 1f) {
                            progress = 1f;
                            ((Timer) e.getSource()).stop();
                            linePoint = null;
                            ballPoint = null;
                        } else {
                            linePoint.y = Math.round(getHeight() * (progress * 2));
                            linePoint.y = getHeight() - (linePoint.y - getHeight());

                            ballPoint.y = linePoint.y;
                        }
                    }

                    repaint();
                }
            });
            retrieveTimer.setRepeats(true);
            retrieveTimer.setCoalesce(true);
            retrieveTimer.setInitialDelay(0);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (ballPoint != null) {

                int x = (int) (ballPoint.x - (ball.getWidth() / 2));
                int y = (int) (ballPoint.y - ball.getHeight());

                g2d.translate(x, y);
                g2d.draw(ball);
                g2d.translate(-x, -y);

            }
            if (linePoint != null) {
                int x = getWidth() / 2;
                int y = 0;

                g2d.drawLine(x, y, linePoint.x, linePoint.y);
            }
            g2d.dispose();
        }

        public boolean canDrop() {
            return !dropTimer.isRunning() && !retrieveTimer.isRunning() && ballPoint == null;
        }

        public boolean canRetrieve() {
            return !dropTimer.isRunning() && !retrieveTimer.isRunning() && ballPoint != null;
        }

        public void drop() {
            startTime = System.currentTimeMillis();
            dropTimer.start();
        }

        public void retrieve() {
            startTime = System.currentTimeMillis();
            retrieveTimer.start();
        }
    }
}