我正在为我的java课程进行keylistener练习,但过去一周一直困扰着。我感谢任何有用的建议。练习是:
“编写一个使用箭头键绘制线段的程序 线从框架的中心开始向东,向北, 西,或右箭头键,向上箭头键,左箭头键, 单击或向下箭头键。“
通过调试我发现KeyListener可以正常工作 得到drawComponent(图形g),但它只在我按下时绘制 向下或向右,只在前几次有效。这是我的代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class EventProgrammingExercise8 extends JFrame {
JPanel contentPane;
LinePanel lines;
public static final int SIZE_OF_FRAME = 500;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
EventProgrammingExercise8 frame = new EventProgrammingExercise8();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public EventProgrammingExercise8() {
setTitle("EventExercise8");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(SIZE_OF_FRAME, SIZE_OF_FRAME);
contentPane = new JPanel();
lines = new LinePanel();
contentPane.add(lines);
setContentPane(contentPane);
contentPane.setOpaque(true);
lines.setOpaque(true);
lines.setFocusable(true);
lines.addKeyListener(new ArrowListener());
}
private class LinePanel extends JPanel {
private int x;
private int y;
private int x2;
private int y2;
public LinePanel() {
x = getWidth() / 2;
y = getHeight() / 2;
x2 = x;
y2 = y;
}
protected void paintComponent(Graphics g) {
g.drawLine(x, y, x2, y2);
x = x2;
y = y2;
}
public void drawEast() {
x2 += 5;
repaint();
}
public void drawWest() {
x2 -= 5;
repaint();
}
public void drawNorth() {
y2 -= 5;
repaint();
}
public void drawSouth() {
y2 += 5;
repaint();
}
}
private class ArrowListener extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_RIGHT) {
lines.drawEast();
} else if (key == KeyEvent.VK_LEFT) {
lines.drawWest();
} else if (key == KeyEvent.VK_UP) {
lines.drawNorth();
} else {
lines.drawSouth();
}
}
}
}
感谢。
答案 0 :(得分:1)
有些事情在我身上跳出来......
public LinePanel() {
x = getWidth() / 2;
y = getHeight() / 2;
这将是一个问题,因为在您构建类时,它的大小为0x0
除了你没有打电话给super.paintComponent
打破油漆链的事实,你似乎认为这幅画是准确的......
protected void paintComponent(Graphics g) {
g.drawLine(x, y, x2, y2);
x = x2;
y = y2;
}
Swing中的绘画具有破坏性。也就是说,您应该擦除Graphics
上下文并从头开始重建输出。作业paintComponent
用于清除准备好绘制的Graphics
上下文,但是您没有调用super.paintComponent
,打破了绘画链并打开了许多非常难看的绘画工件< / p>
在框架上调用setSize(SIZE_OF_FRAME, SIZE_OF_FRAME);
是危险的,因为它无法保证框架边框插入,这将减少可用的可视区域。
此....
contentPane = new JPanel();
lines = new LinePanel();
contentPane.add(lines);
setContentPane(contentPane);
不是必需的,它只会给代码增加混乱。对于您的代码出了什么问题,这也是一个很好的暗示。
JPanel
默认使用FlowLayout
。 FlowLayout
使用组件的首选大小来确定如何最好地布局组件。组件的默认首选大小为0x0
你可以使用......
lines = new LinePanel();
add(lines);
代替或设置contentPane
使用BorderLayout
,这将有助于......
尝试添加lines.setBorder(new LineBorder(Color.RED));
添加,看看你得到了什么......
奇怪的是,在我的测试中,你的KeyListener
工作得很好......
基本上...
getPreferredSize
的{{1}}方法,并返回您要使用的面板的大小。LinePanel
维护需要绘制的java.util.List
列表。Point
方法中,使用paintComponent
Point
实际渲染线条。这将有点棘手,因为你需要两个点而List
可能包含奇数个点,但是可行。List
(例如使用Point
并监控ComponentListener
方法。这会变得棘手,因为您的组件可能会调整大小首次创建并发布到屏幕的次数,一旦有了第一个点,您将希望忽略未来的事件。)