效果
题目
*16.9(用箭头键画线)编写一个程序,使用箭头键绘制线段。所画的线从框架的中心开始,当敲击向右、向上、向左或向下的箭头键时,相应地向东、向北、向西或向南方向画线。
代码
package Test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
public class Exercise16_9 extends JFrame {
private KeyBoardPanel keyBoardPanel=new KeyBoardPanel();
public Exercise16_9(){
add(keyBoardPanel);
keyBoardPanel.setFocusable(true);
}
public static void main(String[] args) {
Exercise16_9 frame=new Exercise16_9();
frame.setTitle("Exercise16_9");
frame.setSize(400,200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
static class KeyBoardPanel extends JPanel{
private int x,y,x1,y1;
private ArrayList point=new ArrayList();
private static int i=0;
public KeyBoardPanel(){
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
switch (e.getKeyCode()){
case KeyEvent.VK_DOWN:y+=10;i++;break;
case KeyEvent.VK_UP:y-=10; i++;break;
case KeyEvent.VK_LEFT:x-=10;i++;break;
case KeyEvent.VK_RIGHT:x+=10;i++;break;
}
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(i==0) {
x1 = getWidth() / 2;
y1 = getHeight() / 2;
g.drawLine(x1, y1, getWidth() / 2 + x, getHeight() / 2 + y);
point.add(x1);
point.add(y1);
}
else{
x1+=x;
y1+=y;
point.add(x1);
point.add(y1);
for (int j = 0,i=0; j <point.size()/2-1; j++,i+=2) {
g.drawLine((int)point.get(i),(int)point.get(i+1),(int)point.get(i+2),(int)point.get(i+3));
}
x=y=0;
}
}
}
}
思路解析
键盘监听事件采用了匿名内类的方式,根据输入的键位进行坐标的记录。由于需要动态的增加每条直线之间的坐标,所以采用了ArrayList的方式,每次存入两个坐标点,绘制直线时将上一个点的终点坐标作为下一条直线的起点,因为考虑到坐标的移动和循环的控制,所以一个变量是不够的的,所以采用了双变量循环。
一句话概括:每次触发事件后,将点之间的坐标保存起来,每次刷新视图的时候,其实都是重新绘制了这些点,然后加上新的点。由于刷新速度太快,所以好像是跟着键盘走的。