use*_*242 3 java swing keylistener graphic paintcomponent
当你按下其中一个方向键时,我试图让球逐渐移动,现在它只是传送.我想要它,以便你可以看到它移动.基于这个例子,我使用的是键绑定,并且有一个名为delta的变量会导致球移动50个像素,但就像我说的那样,只要你按下箭头键,球就会出现50个像素,我想要它就像你要踢球一样,你可以看到它从a点到b点.转到我觉得问题所在的第89行.
package game;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
/**
* @see https://stackoverflow.com/questions/6991648
* @see https://stackoverflow.com/questions/6887296
* @see https://stackoverflow.com/questions/5797965
*/
public class LinePanel extends JPanel {
myObject ball;
private Point b1 = new Point(0,0);
private MouseHandler mouseHandler = new MouseHandler();
private Point p1 = new Point(100, 100);
private Point p2 = new Point(540, 380);
private boolean drawing;
public LinePanel() {
this.setPreferredSize(new Dimension(640, 480));
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.blue);
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(8,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
g.drawLine(p1.x, p1.y, p2.x, p2.y);
ball = new myObject(b1.x,b1.y,"Stuff/ball.png",50,50);
g.drawImage(ball.getImage(),ball.getX(),ball.getY(), ball.getWidth(), ball.getHeight(), null);
repaint();
}
private class MouseHandler extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
drawing = true;
p1 = e.getPoint();
p2 = p1;
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
drawing = false;
p2 = e.getPoint();
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
if (drawing) {
p2 = e.getPoint();
repaint();
}
}
}
private class ControlPanel extends JPanel {
private static final int DELTA = 50;
// above is telling the ball to move by 50 pixels
// I want it to move by 50 pixels but gradually I dont want it to teleport
public ControlPanel() {
this.add(new MoveButton("\u2190", KeyEvent.VK_LEFT, -DELTA, 0));
this.add(new MoveButton("\u2191", KeyEvent.VK_UP, 0, -DELTA));
this.add(new MoveButton("\u2192", KeyEvent.VK_RIGHT, DELTA, 0));
this.add(new MoveButton("\u2193", KeyEvent.VK_DOWN, 0, DELTA));
}
private class MoveButton extends JButton {
KeyStroke k;
int myX, myY;
public MoveButton(String name, int code, final int myX, final int myY) {
super(name);
this.k = KeyStroke.getKeyStroke(code, 0);
this.myX = myX;
this.myY = myY;
this.setAction(new AbstractAction(this.getText()) {
@Override
public void actionPerformed(ActionEvent e) {
LinePanel.this.b1.translate(myX, myY);
LinePanel.this.repaint();
}
});
ControlPanel.this.getInputMap(
WHEN_IN_FOCUSED_WINDOW).put(k, k.toString());
ControlPanel.this.getActionMap().put(k.toString(), new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
MoveButton.this.doClick();
}
});
}
}
}
private void display() {
JFrame f = new JFrame("LinePanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.add(new ControlPanel(), BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new LinePanel().display();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
任何动画的基本前提是随着时间的推移而变化.
你需要能够在给定的时间内将球从位置A移动到位置B. 要做到这一点,你需要某种"自动收报机",可以用来更新那段时间内球的位置.一般来说,25fps(或大约40毫秒)绰绰有余.
为了在Swing中安全地实现这一点,最简单的解决方案是使用Swing Timer.您可以使用a Thread,但后来您负责将更新同步回UI,而且在此阶段确实需要更复杂.
此示例使用1秒的持续时间将球从A点移动到B点.这是一个线性动画,您需要调查适当的动画框架以获得更复杂的解决方案.
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
public class LinePanel extends JPanel {
// myObject ball;
private Point b1 = new Point(0, 0);
private Point startPoint = new Point(0, 0);
private Point targetPoint = new Point(0, 0);
private MouseHandler mouseHandler = new MouseHandler();
private Point p1 = new Point(100, 100);
private Point p2 = new Point(540, 380);
private boolean drawing;
private Timer animate;
private long startTime;
private int duration = 1000;
public LinePanel() {
this.setPreferredSize(new Dimension(640, 480));
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
animate = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
long now = System.currentTimeMillis();
long dif = now - startTime;
if (dif >= duration) {
dif = duration;
((Timer)e.getSource()).stop();
}
float progress = (float)dif / (float)duration;
b1 = calculateProgress(startPoint, targetPoint, progress);
repaint();
}
});
animate.setRepeats(true);
animate.setCoalesce(true);
}
public void moveBallTo(Point target) {
if (animate.isRunning()) {
animate.stop();
}
startPoint = b1;
targetPoint = target;
startTime = System.currentTimeMillis();
animate.start();
}
public void moveBallBy(int xDelta, int yDelta) {
animate.stop();
Point t = new Point(targetPoint == null ? b1 : targetPoint);
t.x += xDelta;
t.y += yDelta;
moveBallTo(t);
}
public Point calculateProgress(Point startPoint, Point targetPoint, double progress) {
Point point = new Point();
if (startPoint != null && targetPoint != null) {
point.x = calculateProgress(startPoint.x, targetPoint.x, progress);
point.y = calculateProgress(startPoint.y, targetPoint.y, progress);
}
return point;
}
public int calculateProgress(int startValue, int endValue, double fraction) {
int value = 0;
int distance = endValue - startValue;
value = (int)Math.round((double)distance * fraction);
value += startValue;
return value;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.blue);
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(8,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
g.drawLine(p1.x, p1.y, p2.x, p2.y);
g.setColor(Color.RED);
g.drawOval(b1.x - 4, b1.y - 4, 8, 8);
// ball = new myObject(b1.x, b1.y, "Stuff/ball.png", 50, 50);
// g.drawImage(ball.getImage(), ball.getX(), ball.getY(), ball.getWidth(), ball.getHeight(), null);
repaint();
}
private class MouseHandler extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
drawing = true;
p1 = e.getPoint();
p2 = p1;
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
drawing = false;
p2 = e.getPoint();
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
if (drawing) {
p2 = e.getPoint();
repaint();
}
}
}
private class ControlPanel extends JPanel {
private static final int DELTA = 50;
// above is telling the ball to move by 50 pixels
// I want it to move by 50 pixels but gradually I dont want it to teleport
public ControlPanel() {
this.add(new MoveButton("\u2190", KeyEvent.VK_LEFT, -DELTA, 0));
this.add(new MoveButton("\u2191", KeyEvent.VK_UP, 0, -DELTA));
this.add(new MoveButton("\u2192", KeyEvent.VK_RIGHT, DELTA, 0));
this.add(new MoveButton("\u2193", KeyEvent.VK_DOWN, 0, DELTA));
}
private class MoveButton extends JButton {
KeyStroke k;
int myX, myY;
public MoveButton(String name, int code, final int myX, final int myY) {
super(name);
this.k = KeyStroke.getKeyStroke(code, 0);
this.myX = myX;
this.myY = myY;
this.setAction(new AbstractAction(this.getText()) {
@Override
public void actionPerformed(ActionEvent e) {
// LinePanel.this.b1.translate(myX, myY);
moveBallBy(myX, myY);
LinePanel.this.repaint();
}
});
ControlPanel.this.getInputMap(
WHEN_IN_FOCUSED_WINDOW).put(k, k.toString());
ControlPanel.this.getActionMap().put(k.toString(), new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
MoveButton.this.doClick();
}
});
}
}
}
private void display() {
JFrame f = new JFrame("LinePanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.add(new ControlPanel(), BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new LinePanel().display();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
看一眼 ...
边注
ball = new myObject(b1.x, b1.y, "Stuff/ball.png", 50, 50);在你的绘画方法中这样做是非常低效的. paint可以快速连续多次调用.在任何可能的情况下,您希望paint方法尽可能优化,在绘制方法上花费大量时间会使程序看起来很慢
| 归档时间: |
|
| 查看次数: |
1334 次 |
| 最近记录: |