对于家庭作业,我必须制作一个程序,其中一个窗口打开,有三个按钮:Drop,Retrieve和Quit。按下跌落时,圆圈从显示屏顶部落到底部并停留在那里。按下“检索”时,一条线应从屏幕向下落到圆圈,然后在视觉上将圆圈拉回到屏幕顶部。
我已经写了几乎所有我无法让线回到屏幕上的东西,在我的代码中只有球确实并且线路停留在那里。
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();
}
}
这是驱动程序:
public class DropDriver {
public static void main(String[] args) {
DisplayWindow d = new DisplayWindow();
DropPanel b = new DropPanel();
d.addPanel(b);
d.showFrame();
}
}
答案 0 :(得分:1)
您的代码格式化使其难以阅读,但我认为我发现了错误:
if(e.getSource()== ticker2) {
if (y2<550) {
y2=y2+2;
}
if (y2==550) {
ticker1.stop();
y=y-2;
y2=y2-2;
}
}
你有两个if语句,编译器将按照它们的写入顺序执行它们。因此,当y2==550
时,第二个if语句将执行y2=y2-2
,所以现在y2==448
。现在在下一个tick y2<550
为真,所以第一个if语句将执行y2=y2+2
所以现在y2==550
,然后第二个if语句将执行y2=y2-2
,所以现在{{1 ......并且球将继续上下移动2个像素。
我的建议是当球到达屏幕底部时使用设置为y2==448
的{{1}},并且只有当此布尔值为false时才会执行第一个if语句。
答案 1 :(得分:1)
首先分开责任区。试图将所有“动作”逻辑混合到一个方法中不仅是糟糕的设计,而且会给你带来很大的困惑。
每个计时器都应该有自己的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();
}
}
}
这基本上使用两个独立的计时器来执行各个工作单元。删除和检索。功能设置在这样的距离,你只能在一个球实际掉落时检索一个球,但不能丢球超过一个球...